-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a table with limitations and some more scripts to limits. Also mo…
…ved relayer discovery to move dir
- Loading branch information
Showing
4 changed files
with
292 additions
and
195 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
# Relayer Discovery | ||
|
||
The only information about an incoming contract call through axelar are | ||
|
||
- Command Id: A unique identifier for the command approving the call, 32 bytes long. | ||
- Source Chain: The name of the source chain, as a String | ||
- Source Address: The caller, as a String. | ||
- Destination Chain: “Sui” for the purposes of this document | ||
- Destination Address: The destination, a Sui address. | ||
|
||
As we already explained, the destination address will be the `ID` of a `GatewayChannel` object that needs to be provided to consume the call. However there is no way for a relayer to know what they are supposed to call to get the call to be consumed, since they should not have access to the `GatewayChannel` object itself. This creates the need to make the destination for each incoming call publicly known so that any relayer can query it. | ||
|
||
## Transaction Object | ||
|
||
The following objects are defined in the `axelar::discovery` module and can be used to register/decode transactions. | ||
|
||
```rust | ||
struct Function has store, copy, drop { | ||
package_id: address, | ||
module_name: String, | ||
name: String, | ||
} | ||
|
||
/// Arguments are prefixed with: | ||
/// - 0 for objects followed by exactly 32 bytes that cointain the object id | ||
/// - 1 for pures followed by the bcs encoded form of the pure object | ||
/// - 2 for the ApprovedCall object, followed by nothing (to be passed into the target function) | ||
/// - 3 for the payload of the contract call (to be passed into the intermediate function) | ||
/// - 4 for an argument returned from a previous move call, followed by a u8 specified which call to get the return of (0 for the first transaction AFTER the one that gets ApprovedCall out), and then another u8 specifying which argument to input. | ||
struct MoveCall has store, copy, drop { | ||
function: Function, | ||
arguments: vector<vector<u8>>, | ||
type_arguments: vector<String>, | ||
} | ||
|
||
public struct Transaction has store, copy, drop { | ||
is_final: bool, | ||
move_calls: vector<MoveCall>, | ||
} | ||
``` | ||
|
||
As seen above there are some options to allow for dynamic objects to be referenced that could not be known on chain, since they do not exist on chain (the `ApprovedCall` object, the payload of the incoming call and the returned arguments of a previous `MoveCall`). | ||
|
||
## Relayer Discovery | ||
|
||
First the relayer needs to get a contract call approved: | ||
|
||
```mermaid | ||
graph | ||
process([axelar::gateway::process_commands]) | ||
subgraph tx1[Get Approval] | ||
subgraph pure1[pure] | ||
input[/commands input: vector<u8>/] | ||
end | ||
subgraph public0[public] | ||
gateway{Gateway} | ||
end | ||
input & gateway --> process | ||
end | ||
``` | ||
|
||
Next, they need to figure out what to actually call to execute: | ||
|
||
```mermaid | ||
graph | ||
getTransaction([axelar::discovery::get_transaction]) | ||
subgraph public1[pubic] | ||
discovery{RelayerDiscovery} | ||
end | ||
transaction[/Transaction/] | ||
channelId[/Channel Id/] | ||
discovery & channelId --> getTransaction --> devInspect[Dev Inspect] --> transaction | ||
transaction --> |is_final == true| block[Ready to Execute] | ||
transaction --> |is_final == false| devInspect[Dev Inspect] | ||
``` | ||
|
||
Finally, they need to get the `ApprovedCall` object from the gateway and use it to execute: | ||
|
||
```mermaid | ||
graph | ||
subgraph public | ||
Gateway{Gateway} | ||
end | ||
subgraph pure | ||
commandId[/command_id: vector<u8>/] | ||
sourceChain[/source_chain: String/] | ||
sourceAddress[/source_address: String/] | ||
destinationAddress[/destination_channel_id: address/] | ||
payload[/payload: vector<u8>/] | ||
end | ||
subgraph hotpotato[Hot Potato] | ||
ApprovedCall((ApprovedCall)) | ||
end | ||
takeCall([axelar::gateway::takeContractCall]) | ||
Gateway & commandId & sourceChain & sourceAddress & destinationAddress & payload --> takeCall --> ApprovedCall | ||
ApprovedCall --> execute[Execute As Described by `Transaction` Above] | ||
``` | ||
|
||
## Application | ||
|
||
Anyone can register a `Transaction` for their channel using `axelar::discovery::register_transaction`: | ||
|
||
```mermaid | ||
graph | ||
register([axelar::discovery::register_transaction]) | ||
newFunction([axelar::discovery::new_function]) | ||
newMoveCall([axelar::discovery::new_move_call]) | ||
newTransaction([axelar::discovery::new_transaction]) | ||
function[/Function/] | ||
moveCall[/MoveCall/] | ||
transaction[/Transaction/] | ||
subgraph pure1[pure] | ||
packageId[/package id: address/] | ||
moduleName[/module name: String/] | ||
functionName[/function name: String/] | ||
end | ||
subgraph pure2[pure] | ||
arguments[/arguments: vector<vector<u8>>/] | ||
types[/type aguments: vector<String>/] | ||
end | ||
subgraph pure3[pure] | ||
isFinal[is_final: bool] | ||
end | ||
subgraph public | ||
discovery{RelayerDiscovery} | ||
end | ||
subgraph user | ||
channel{{GatewayChannel}} | ||
end | ||
packageId & moduleName & functionName --> newFunction --> function | ||
function & arguments & types --> newMoveCall --> moveCall | ||
moveCall & isFinal --> newTransaction --> transaction | ||
discovery & channel & transaction --> register | ||
``` | ||
|
||
Note that `new_transaction` takes a vector of `Transaction` objects, so the above is slightly simplified. To allow for complicated call receiving, the `is_final` field of a `Transaction` tells the relayer what to do with a given `Transaction` . | ||
|
||
When a `Transaction` is final, the relayer will execute it. Note that during the transaction the application needs to consume the `ApprovedCall` object: | ||
|
||
```mermaid | ||
graph | ||
subgraph user | ||
channel{{GatewayChannel}} | ||
end | ||
subgraph hotpotato[Hot Potato] | ||
ApprovedCall((ApprovedCall)) | ||
end | ||
consume([axelar::channel::consume_approved_call]) | ||
channel & ApprovedCall --> consume --> source_chain[/source_chain: String/] & source_address[/source_address: String/] & payload[/payload: vector<u8>/] | ||
``` | ||
|
Oops, something went wrong.