elixir-omg
elixir-omg copied to clipboard
Endpoint: /block.validate
In the current setup, the child chain composes a block and submits to the root chain without any further validation from an external component. This poses the risk of a byzantine event due to a software error in the child chain.
The following flow is envisioned to mitigate this:
*The Vault
will manage block submission to the Ethereum Network
- Child chain requests the Vault to publish a block (Merkle) root hash
- Vault calls
child_chain.get_block(root_hash)
- Vault calls Watcher to perform stateful block validation.
- If the validation is successful, publish. If it's not successful send an alarm on multiple channels.
References:
- https://omisego.atlassian.net/wiki/spaces/SEC/pages/264831041/Feature+team+block+validation
- https://omisego.atlassian.net/wiki/spaces/SC/pages/194871396/Pre-submit+block+verifier
- https://github.com/omisego/immutability-eth-plugin
Todo for @thec00n: SLA margin is applied to specific exit scenarios that allows the chch to have a grace period, e.g. there is a double spend but if it happens within a margin it's ok since it can be challenged later. So make sure to consider all such scenarios that a malicious user could leverage to still include an invalid tx and analyze their impact.
Checklist:
- [x] Stateless validation: given Merkle root matches reconstructed Merkle root
- [x] Stateless validation: all transactions are correctly formed
- [ ] Stateful validation: UTXOs in the given transactions are not spent by a child chain transaction
- [ ] Stateful validation: UTXOs in the given transactions are not spent by an exit.
- [ ] Stateful validation: Checking if the Watcher is synced to the block number it is receiving.
- [ ] Stateful validation:
Vault
should call this endpoint before submitting the block.
To discuss: where/how do we draw the line between what is validated by the Watcher and what is left to the exit/challenge game?
Here is my brainstorming list for:
Stateless validation rules
Some of them might be already covered by the existing implementation of /block.validate
:
Payment Tx (Ref: https://github.com/omgnetwork/elixir-omg/blob/master/docs/transaction_validation.md):
- A tx input can not be spent by another tx in the same block
- Match the payment tx type and must meet all the other payment tx type requirements
Fee Tx (Ref: https://github.com/omgnetwork/elixir-omg/blob/master/docs/fee_design.md):
- Match the fee tx type, must have 0 inputs, 1 output and must meet all the other fee tx type requirements
- Fee tx address should be matched against a specific value?
Block:
- Block has less than 2^16 tx and more than 0 tx
- Fee tx need to come at the end of a block after all other tx
- 1 fee tx per asset
- An input can only be spent once (per block).
Stateful validation rules
Payment Tx (Ref: https://github.com/omgnetwork/elixir-omg/blob/master/docs/transaction_validation.md):
- A tx input has to be included in a previous block (including deposit blocks) and therefore has to be included in the list of unspent utxos
- A tx input from must have a valid signature from the owner
- The sum of tx inputs for a currency needs to be greater than the sum of tx outputs
Fee Tx (Ref: https://github.com/omgnetwork/elixir-omg/blob/master/docs/fee_design.md):
- The sum of inputs minus the sum of outputs for a given currency across all payment tx is the amount that the operator can transfer to himself.
Block:
- Needs to be the next block
Checklist
Rule | Type | Status | |
---|---|---|---|
Block hash matches reconstructed Merkle root hash | Stateless | ✅ | |
Payment transactions are correctly formed | Stateless | ✅ | Using Transaction.Recovered |
Fee transactions are correctly formed | Stateless | ✅ | Using Transaction.Recovered |
No duplicate inputs in a block | Stateless | ✅ | |
Number of transactions within accepted range | Stateless | ✅ | |
Fee transactions comes after all other transactions | Stateless | ✅ | |
One fee transaction per currency | Stateless | ✅ |
For transparency I am recapping the functionality of Transaction.Recovered
Transaction.Signed.decode(encoded_signed_tx)
- Validates that RLP is correctly-formed.
- Validate that witnesses are constructed as a list
- Validates that each witness is a binary
- Validates that each witness is correct length
- Validates the existence of the given transaction type
- Reconstructs the transaction as per its type:
- Payment
- Validates that there are 4 inputs or less
- Validates that input decodes into a valid position
- Validates between 1 and 4 outputs
- Validates each output is correctly constructed (valid type, non-zero owner, non-zero amount, valid address)
- Validates that metadata is binary and correct length
- Validates each output matches payment output type
- Validates
txData
RLP. - Validates that metadata is binary and correct length
- Fee
- Validates that each output is correctly constructed (valid type, non-zero owner, non-zero amount, valid address)
- Validates that nonce is binary and correct length
- Payment
- Checks no duplicate inputs
- If payment, validates number of signatures matches number of inputs
- If fee, validates only one output
@okalouti should we start documentation around stateless and stateful block validation here https://github.com/omgnetwork/elixir-omg/tree/master/docs? I will never find that list again 😄
@okalouti is this done?
@InoMurko I left it open in case we wanted to add stateful validation to this endpoint. But you took this over and from your question I gather we can close it!