Initial In Instructions pallet and Serai client lib (#233)

* Initial work on an In Inherents pallet

* Add an event for when a batch is executed

* Add a dummy provider for InInstructions

* Add in-instructions to the node

* Add the Serai runtime API to the processor

* Move processor tests around

* Build a subxt Client around Serai

* Successfully get Batch events from Serai

Renamed processor/substrate to processor/serai.

* Much more robust InInstruction pallet

* Implement the workaround from https://github.com/paritytech/subxt/issues/602

* Initial prototype of processor generated InInstructions

* Correct PendingCoins data flow for InInstructions

* Minor lint to in-instructions

* Remove the global Serai connection for a partial re-impl

* Correct ID handling of the processor test

* Workaround the delay in the subscription

* Make an unwrap an if let Some, remove old comments

* Lint the processor toml

* Rebase and update

* Move substrate/in-instructions to substrate/in-instructions/pallet

* Start an in-instructions primitives lib

* Properly update processor to subxt 0.24

Also corrects failures from the rebase.

* in-instructions cargo update

* Implement IsFatalError

* is_inherent -> true

* Rename in-instructions crates and misc cleanup

* Update documentation

* cargo update

* Misc update fixes

* Replace height with block_number

* Update processor src to latest subxt

* Correct pipeline for InInstructions testing

* Remove runtime::AccountId for serai_primitives::NativeAddress

* Rewrite the in-instructions pallet

Complete with respect to the currently written docs.

Drops the custom serializer for just using SCALE.

Makes slight tweaks as relevant.

* Move instructions' InherentDataProvider to a client crate

* Correct doc gen

* Add serde to in-instructions-primitives

* Add in-instructions-primitives to pallet

* Heights -> BlockNumbers

* Get batch pub test loop working

* Update in instructions pallet terminology

Removes the ambiguous Coin for Update.

Removes pending/artificial latency for furture client work.

Also moves to using serai_primitives::Coin.

* Add a BlockNumber primitive

* Belated cargo fmt

* Further document why DifferentBatch isn't fatal

* Correct processor sleeps

* Remove metadata at compile time, add test framework for Serai nodes

* Remove manual RPC client

* Simplify update test

* Improve re-exporting behavior of serai-runtime

It now re-exports all pallets underneath it.

* Add a function to get storage values to the Serai RPC

* Update substrate/ to latest substrate

* Create a dedicated crate for the Serai RPC

* Remove unused dependencies in substrate/

* Remove unused dependencies in coins/

Out of scope for this branch, just minor and path of least resistance.

* Use substrate/serai/client for the Serai RPC lib

It's a bit out of place, since these client folders are intended for the node to
access pallets and so on. This is for end-users to access Serai as a whole.

In that sense, it made more sense as a top level folder, yet that also felt
out of place.

* Move InInstructions test to serai-client for now

* Final cleanup

* Update deny.toml

* Cargo.lock update from merging develop

* Update nightly

Attempt to work around the current CI failure, which is a Rust ICE.

We previously didn't upgrade due to clippy 10134, yet that's been reverted.

* clippy

* clippy

* fmt

* NativeAddress -> SeraiAddress

* Sec fix on non-provided updates and doc fixes

* Add Serai as a Coin

Necessary in order to swap to Serai.

* Add a BlockHash type, used for batch IDs

* Remove origin from InInstruction

Makes InInstructionTarget. Adds RefundableInInstruction with origin.

* Document storage items in in-instructions

* Rename serai/client/tests/serai.rs to updates.rs

It only tested publishing updates and their successful acceptance.
This commit is contained in:
Luke Parker
2023-01-20 11:00:18 -05:00
committed by GitHub
parent e13cf52c49
commit 8ca90e7905
53 changed files with 1613 additions and 403 deletions

View File

@@ -3,90 +3,94 @@
Instructions are used to communicate with networks connected to Serai, and they
come in two forms:
- In Instructions are [Application Calls](../Serai.md#application-calls),
paired with incoming funds. Encoded in transactions on connected networks,
Serai will parse out instructions when it receives funds, executing the included
calls.
- In Instructions are programmable specifications paired with incoming coins,
encoded into transactions on connected networks. Serai will parse included
instructions when it receives coins, executing the included specs.
- Out Instructions detail how to transfer assets, either to a Serai address or
an address native to the asset in question.
- Out Instructions detail how to transfer coins, either to a Serai address or
an address native to the coin in question.
A transaction containing an In Instruction and an Out Instruction (to a native
address) will receive funds to Serai and send funds from Serai, without
address) will receive coins to Serai and send coins from Serai, without
requiring directly performing any transactions on Serai itself.
All instructions are encoded under [Shorthand](#shorthand). Shorthand provides
frequent use cases to create minimal data representations on connected networks.
Instructions are interpreted according to their non-Serai network. Addresses
have no validation performed, beyond being a valid enum entry (when applicable)
of the correct length, unless otherwise noted. If the processor is instructed to
act on invalid data, or send to itself, it will drop the entire instruction.
have no validation performed unless otherwise noted. If the processor is
instructed to act on invalid data, it will drop the entire instruction.
### Serialization
- Numbers are exclusively unsigned and encoded as compact integers under
SCALE.
- Enums are prefixed by an ordinal byte of their type, followed by their
actual values.
- Vectors are prefixed by their length.
- In Instruction fields are numbered and sequentially encoded, allowing
omission, each prefixed by an ordinal byte. This is due to its fields being more
frequently omitted than not, making their presence what's notable.
- All other types have their fields sequentially encoded with no markers.
Instructions are SCALE encoded.
Certain fields may be omitted depending on the network in question.
### Application Call
### In Instructions
- `application` (u16): The application of Serai to call. Currently, only 0,
Serai DEX is valid.
- `data` (Data): The data to call the application with.
- `origin` (Address): Address from the network of origin which sent funds in.
- `target` (Address): The ink! contract to transfer the incoming funds to.
- `data` (Vec\<u8>): The data to call `target` with.
### In Instruction
InInstruction is an enum of SeraiAddress and ApplicationCall.
The specified target will be minted an appropriate amount of the respective
Serai token. If an Application Call, the encoded call will be executed.
### Refundable In Instruction
- `origin` (Option\<ExternalAddress>): Address, from the network of origin,
which sent coins in.
- `instruction` (InInstruction): The action to perform with the incoming
coins.
Networks may automatically provide `origin`. If they do, the instruction may
still provide `origin`, overriding the automatically provided value. If no
`origin` is provided, the instruction is dropped.
still provide `origin`, overriding the automatically provided value.
Upon receiving funds, the respective Serai Asset contract is called, minting the
appropriate amount of coins, and transferring them to `target`, calling it with
the attached data.
If the instruction fails, coins are scheduled to be returned to `origin`,
if provided.
If the instruction fails, funds are scheduled to be returned to `origin`.
### Destination
### Out Instructions
Destination is an enum of SeraiAddress and ExternalAddress.
- `destination` (Enum { Native(Address), Serai(Address) }): Address to receive
funds to.
- `data` (Option\<Vec\<u8>>): The data to call
the target with.
### Out Instruction
Transfer the funds included with this instruction to the specified address with
the specified data. Asset contracts perform no validation on native
addresses/data.
- `destination` (Destination): Address to receive coins to.
- `data` (Option\<Data>): The data to call the destination with.
Transfer the coins included with this instruction to the specified address with
the specified data. No validation of external addresses/data is performed
on-chain. If data is specified for a chain not supporting data, it is silently
dropped.
### Shorthand
Shorthand is an enum which expands to an In Instruction.
Shorthand is an enum which expands to an Refundable In Instruction.
##### Raw
Raw Shorthand encodes a raw In Instruction with no further processing. This is
a verbose fallback option for infrequent use cases not covered by Shorthand.
Raw Shorthand encodes a raw Refundable In Instruction in a Data, with no further
processing. This is a verbose fallback option for infrequent use cases not
covered by Shorthand.
##### Swap
- `origin` (Option\<Address>): In Instruction's `origin`.
- `coin` (Coin): Coin to swap funds for.
- `minimum` (Amount): Minimum amount of `coin` to receive.
- `out` (Out Instruction): Final destination for funds.
- `origin` (Option\<ExternalAddress>): Refundable In Instruction's `origin`.
- `coin` (Coin): Coin to swap funds for.
- `minimum` (Amount): Minimum amount of `coin` to receive.
- `out` (Out Instruction): Final destination for funds.
which expands to:
```
In Instruction {
RefundableInInstruction {
origin,
target: Router,
data: swap(Incoming Asset, out, minimum)
instruction: ApplicationCall {
application: DEX,
data: swap(Incoming Asset, coin, minimum, out)
}
}
```
@@ -99,19 +103,23 @@ where `swap` is a function which:
##### Add Liquidity
- `origin` (Option\<Address>): In Instruction's `origin`.
- `minimum` (Amount): Minimum amount of SRI to receive.
- `gas` (Amount): Amount of SRI to send to `address` to cover
gas in the future.
- `address` (Address): Account to send the created liquidity tokens.
- `origin` (Option\<ExternalAddress>): Refundable In Instruction's `origin`.
- `minimum` (Amount): Minimum amount of SRI tokens to swap
half for.
- `gas` (Amount): Amount of SRI to send to `address` to
cover gas in the future.
- `address` (Address): Account to send the created liquidity
tokens.
which expands to:
```
In Instruction {
RefundableInInstruction {
origin,
target: Router,
data: swap_and_add_liquidity(Incoming Asset, address, minimum, gas)
instruction: ApplicationCall {
application: DEX,
data: swap_and_add_liquidity(Incoming Asset, minimum, gas, address)
}
}
```
@@ -120,5 +128,5 @@ where `swap_and_add_liquidity` is a function which:
1) Swaps half of the incoming funds for SRI.
2) Checks the amount of SRI received is greater than `minimum`.
3) Calls `swap_and_add_liquidity` with the amount of SRI received - `gas`, and
a matching amount of the incoming asset.
a matching amount of the incoming coin.
4) Transfers any leftover funds to `address`.