Table of Contents
- elixir-omg applications
- Child chain server
- Using the child chain server's API
- Ethereum private key management
- Managing the operator address
- Nonces restriction
- Funding the operator address
- Watcher and Watcher Info
elixir-omg
is an umbrella app comprising of several Elixir applications:
The general idea of the apps responsibilities is:
omg
- common application logic used by both the child chain server and watcheromg_bus
- an internal event bus to tie services togetheromg_child_chain
- child chain server- tracks Ethereum for things happening in the root chain contract (deposits/exits)
- gathers transactions, decides on validity, forms blocks, persists
- submits blocks to the root chain contract
- see
apps/omg_child_chain/lib/omg_child_chain/application.ex
for a rundown of children processes involved
omg_child_chain_rpc
- an HTTP-RPC server being the gateway toomg_child_chain
omg_db
- wrapper around the child chain server's database to store the UTXO set and blocks necessary for state persistenceomg_eth
- wrapper around the Ethereum RPC clientomg_status
- application monitoring facilitiesomg_utils
- various non-omg-specific shared codeomg_watcher
- the Watcheromg_watcher_info
- the Watcher Infoomg_watcher_rpc
- an HTTP-RPC server being the gateway toomg_watcher
See application architecture for more details.
:omg_child_chain
is the Elixir app which runs the child chain server, whose API is exposed by :omg_child_chain_rpc
.
For the responsibilities and design of the child chain server see Plasma Blockchain Design document.
The child chain server is listening on port 9656
by default.
HTTP-RPC requests are served up on the port specified in omg_child_chain_rpc
's config
(:omg_child_chain_rpc, OMG.RPC.Web.Endpoint, http: [port: ...]
).
The available RPC calls are defined by omg_child_chain
in api.ex
- paths follow RPC convention e.g. block.get
, transaction.submit
.
All requests shall be POST with parameters provided in the request body in JSON object.
Object's properties names correspond to the names of parameters. Binary values shall be hex-encoded strings.
For API documentation see: https://docs.omg.network/.
Currently, the child chain server assumes that the authority account is unlocked or otherwise available on the Ethereum node. This might change in the future.
(a.k.a authority address
)
The Ethereum address which the operator uses to submit blocks to the root chain is a special address which must be managed accordingly to ensure liveness and security.
The reorg protection mechanism enforces there to be a strict relation between the submitBlock
transactions and block numbers.
Child block number 1000
uses Ethereum nonce 1
, child block number 2000
uses Ethereum nonce 2
, always.
This provides a simple mechanism to avoid submitted blocks getting reordered in the root chain.
This restriction is respected by the child chain server, whereby the Ethereum nonce is simply derived from the child block number.
As a consequence, the operator address must never send any other transactions, if it intends to continue submitting blocks. (Workarounds to this limitation are available, if there's such requirement.)
NOTE Ethereum nonce 0
is necessary to call the RootChain.init
function, which must be called by the operator address.
This means that the operator address must be a fresh address for every child chain brought to life.
The address that is running the child chain server and submitting blocks needs to be funded with Ether. At the current stage this is designed as a manual process, i.e. we assume that every gas reserve checkpoint interval, someone will ensure that gas reserve worth of Ether is available for transactions.
Gas reserve must be enough to cover the gas reserve checkpoint interval of submitting blocks, assuming the most pessimistic scenario of gas price.
Calculate the gas reserve as follows:
gas_reserve = child_blocks_per_day * days_in_interval * gas_per_submission * highest_gas_price
where
child_blocks_per_day = ethereum_blocks_per_day / submit_period
Submit period is the number of Ethereum blocks per a single child block submission) - configured in :omg_child_chain, :child_block_submit_period
Highest gas price is the maximum gas price which the operator allows for when trying to have the block submission mined (operator always tries to pay less than that maximum, but has to adapt to Ethereum traffic) - configured in (TODO when doing OMG-47 task)
Example
Assuming:
- submission of a child block every Ethereum block
- 15 second block interval on Ethereum, on average
- weekly cadence of funding, i.e.
days_in_interval == 7
- allowing gas price up to 40 Gwei
gas_per_submission == 71505
(checked forRootChain.sol
at this revision. C.f. here)
we get
gas_reserve ~= (4 * 60 * 24 / 1) * 7 * 71505 * (40 / 10**9) ~= 115 ETH
NOTE that the above calculation doesn't imply this is what is going to be used within a week, just a pessimistic scenario to calculate an adequate reserve. If one assumes an average gas price of 4 Gwei, the amount is immediately reduced to ~11.5 ETH weekly.
The Watcher is an observing node that connects to Ethereum and the child chain server's API. It ensures that the child chain is valid and notifies otherwise. It exposes the information it gathers via an HTTP-RPC interface (driven by Phoenix). It provides a secure proxy to the child chain server's API and to Ethereum, ensuring that sensitive requests are only sent to a valid chain.
For more on the responsibilities and design of the Watcher see Plasma Blockchain Design document.
The watcher can be run in one of two modes:
- security-critical only
- intended to provide light-weight Watcher just to ensure security of funds deposited into the child chain
- this mode will store all of the data required for security-critical operations (exiting, challenging, etc.)
- it will not store data required for current and performant interacting with the child chain (spending, receiving tokens, etc.)
- it will not expose some endpoints related to current and performant interacting with the child chain (
account.get_utxos
,transaction.*
, etc.) - it will only require the
OMG.DB
key-value store database - this mode will prune all security-related data not necessary anymore for security reasons (from
OMG.DB
) - some requests to the API might be slow but must always work (called rarely in unhappy paths only, like mass exits)
- security-critical and informational API
- intended to provide convenient and performant API to the child chain data, on top of the security-related one
- this mode will provide/store everything the security-critical mode does
- this mode will store easily accessible register of all transactions for a subset of addresses (currently, all addresses)
- this mode will leverage the PostgreSQL - based
WatcherDB
database
In releases, watcher
refers to the security-critical mode, while watcher_info
refers to the security-critical and informational API mode.
The watcher is listening on port 7434
by default. And watcher info listens on port 7534
.
For API documentation see: https://docs.omg.network/
Watcher doesn't hold or manage user's keys. All signatures are assumed to be done outside.
For docker deployments, and release deployments please refer to Deployment Configuration.
NOTE: all margins are denominated in Ethereum blocks
-
submission_finality_margin
- the margin waited before mined block submissions are purged fromBlockQueue
's memory -
block_queue_eth_height_check_interval_ms
- polling interval for checking whether the root chain had progressed for theBlockQueue
exclusively -
fee_adapter_check_interval_ms
- interval for checking fees updates from the fee adapter. -
fee_buffer_duration_ms
- duration for which a fee is still valid after beeing updated. -
block_submit_every_nth
- how many new Ethereum blocks must be mined, since previous submission attempt, before another block is going to be formed and submitted. -
block_submit_max_gas_price
- the maximum gas price to use for block submission. The first block submission after application boot will use the max price, and gradually adjusts to the current optimum price for subsequent blocks. -
fee_specs_file_path
- path to the file which defines fee requirements -
fee_adapter
- is a tuple, where first element is a module name implementingFeeAdapter
behaviour, e.g.OMG.ChildChain.Fees.FileAdapter
and the second element is a Keyword[opts: fee_adapter_opts]
Options of the fee adapter, depends on adapterspecs_file_path
- [FileAdaper only] path to file (including the file name) which defines fee requirements, see fee_specs.json for an example.fee_feed_url
- [FeedAdapter only] url to the fee service, that privides actual fees prices. Response should follow the file specs format.fee_change_tolerance_percent
- [FeedAdapter only!] positive integer describes significance of price change. When price in new reading changes above tolerance level, prices are updated immediately. Otherwise update interval is preserved.stored_fee_update_interval_minutes
- [FeedAdapter only!] positive integer describes time interval in minutes. The updates of token prices are carried out in update intervals as long as the changes are within tolerance.
-
deposit_finality_margin
- the margin that is waited after aDepositCreated
event in the root chain contract. Only after this margin had passed:- the child chain will allow spending the deposit
- the watcher and watcher info will consider a transaction spending this deposit a valid transaction
It is important that for a given child chain, the child chain server and watchers use the same value of this margin.
NOTE: This entry is defined in
omg
, despite not being accessed there, only inomg_child_chain
andomg_watcher
. The reason here is to minimize risk of Child Chain server's and Watcher's configuration entries diverging. -
ethereum_events_check_interval_ms
- polling interval for pulling Ethereum events (logs) from the Ethereum client. -
coordinator_eth_height_check_interval_ms
- polling interval for checking whether the root chain had progressed for theRootChainCoordinator
. Affects how quick the services reading Ethereum events realize there's a new block. -
exit_processor_sla_margin
- the margin to define the notion of a "late", invalid exit. After this margin passes, every invalid exit is deemed a critical failure of the child chain (unchallenged_exit
). Such event will prompt a mass exit and stop processing new blocks. See exit validation documentation for details. Cannot be larger thanmin_exit_period_seconds
because otherwise it leads to a dangerous setup of the Watcher (in particular - muting the reports of unchallenged_exits). Override using theEXIT_PROCESSOR_SLA_MARGIN
system environment variable. -
exit_processor_sla_margin_forced
- if set totrue
, will allow one to set aexit_processor_sla_margin
that is larger than themin_exit_period_seconds
of the child chain we're running for. Set totrue
only when you know what you are doing. Defaults tofalse
, override using theEXIT_PROCESSOR_SLA_MARGIN_FORCED
system environment variable. -
maximum_block_withholding_time_ms
- for how long the Watcher will tolerate failures to get a submitted child chain block, before reporting a block withholding attack and stopping -
maximum_number_of_unapplied_blocks
- the maximum number of downloaded and statelessly validated child chain blocks to hold in queue for applying -
exit_finality_margin
- the margin waited before an exit-related event is considered final enough to pull and process -
block_getter_reorg_margin
- the margin considered byOMG.Watcher.BlockGetter
when searching for recent child chain block submission events. This is driving the process of determining the height and particular event related to the submission of a particular child chain block
-
path
- path to the directory holding the LevelDB data store -
server_module
- the module to use when talking to theOMG.DB
-
server_name
- the named process to refer to when talking to theOMG.DB
All binary entries are expected in hex-encoded, 0x
-prefixed.
-
contract_addr
- the address of the root chain contract -
authority_address
- the address used by the operator to submit blocks -
txhash_contract
- the Ethereum-transaction hash holding the deployment of the root chain contract -
eth_node
- the Ethereum client which is used:"geth" | "infura"
. -
node_logging_in_debug
- whether the output of the Ethereum node being run in integration test should be printed to:debug
level logs. If you set this to false, remember to set the logging level to:debug
to see the logs -
child_block_interval
- mirror of contract configurationuint256 constant public CHILD_BLOCK_INTERVAL
fromRootChain.sol
-
min_exit_period_seconds
- mirror of contract configurationuint256 public minExitPeriod
-
ethereum_block_time_seconds
- mirror the block time of the underlying root chain. Defaults to 15 seconds, suitable for public networks (mainnet
and testnets). Override using theETHEREUM_BLOCK_TIME_SECONDS
system environment variable.