Replies: 4 comments 16 replies
-
I wonder if we could avoid meta-transactions here if we make it so that there is not a special pathway needed for the relayer to handle the case of transactions which could trigger promises on NEAR. Currently, the flow for sending transactions to the chain is:
To accommodate the possibility of transactions which trigger further operations on NEAR, I think we only need to change step 2 as follows:
Now instead of a relayer account calling the engine, this new async account calls itself (and will have internal logic to call the Engine). This should not be much more expensive in terms of NEAR gas than the current flow because the first receipt is "local". I think this is nicer because the change is entirely internal; users will not suddenly be prompted to sign arbitrary messages instead of submitting a normal transaction if a dapp decides to start using the functionality. I also like that the relayer doesn't need to do any special dispatch depending on the type of input it receives. (To make this work with silos some dispatching may still be needed, but at least the type of the input will always be the same.) Regarding the question of guaranteeing that transactions which cause the Engine to return promises to be scheduled will always have those promises created; I think that it could be a feature, as opposed to a bug, if those promises could actually cross NEAR transaction boundaries. The reason is because we may already be tight on NEAR gas with just the Aurora execution, so the created promises may run out of gas. In this situation I think it would be good if the first transaction called the Engine directly (instead of |
Beta Was this translation helpful? Give feedback.
-
@mfornet |
Beta Was this translation helpful? Give feedback.
-
We must have versioned calls. If others have the possibility of using a different version of a call in the future, we need to be able to handle this for compatibility in case something changes. We could also have the enum parser trick which will simply try to parse each input to match the correct structure, not exactly requiring a version # at all. So if input latest structure fails, downgrade and try the next. It would increase gas slightly for the 2nd option if others are using an older call, but it's ideal IMO. In general, even if Aurora handles the ecosystem entirely, anything cross contract should require some form of handling of possible new structs down the line. So, two options. |
Beta Was this translation helpful? Give feedback.
-
Some comments from my side...
Now, a bit of the philosophy. The above discussion is centred around how to implement the functionality. I would like to put on the table a bit of what is expected. Ethereum ecosystem is a thing-in-itself. Even though functionality to call NEAR contracts interacts with something external to Aurora, the interface for this functionality should live inside Aurora. Simply, just to allow all the complicated interaction with this piece created by 3rd party contracts (imagine: getting a loan, putting a part of the tokens to a farm, sending another part to NEAR farm, saving some tokens on interim account to allow for potential losses because of closing the opportunity because of the async execution on NEAR). Moreover, mainly, user would like to get the result of the interaction back, since just scheduling some call doesn't make sense. And such results must be delivered in the familiar form -- as results of the transaction execution. From my point of view, for the Aurora developer the simplest construct would be the following.
Separation of the execution. The actual call outside Aurora may be executed inside an initial Aurora tx or completely separate, opening a market for those who want to pay for such calls. Obviously, Aurora Sender identifier. Now, an important thing that should be solved is how to correctly pass through the promise its' creator. This can be done at least through a new NIP, which would specify the interface for the meta-txs on NEAR (maybe there's already one?). Alternatively, Aurora contract can spawn Storage considerations. Additional tricky point in this approach is the storage of the execution results. From one hand, if you want to separate the execution and the usage of the results into multiple NEAR transactions (and I believe this is what should be done), you either should store the execution results OR use NEAR light client to prove the results of the execution on the go. Second option from my point of view is an overhead for this use case and it complicates the usage of the functionality too much. From the other hand, if you need to store the data, then you face the problem of bloating the state. And this would be particularly an issue in the case of massive communications with NEAR contracts. So a piece that manages the lifetime of keeping the results on-chain is necessary. If can be as simple as 1) one needs to pay for the allocation of the storage for the result of the promise during scheduling it (and pay for it's execution), 2) a creator of the promise may delete the execution result through ordinary Ethereum means, which will result in returning the gas costs. This logic may become more complicated with some automation in the future. The above approach is from my point of view is that is the simplest schema and thus can can be comprehended by Ethereum developers much faster than the NEAR runtime. This approach can be extended to message passing interfaces (specifically, MPI) that are the most scalable approach for cross-program interactions in supercomputers (i.e. environments with parallel execution). The details of the implementation of this scheme is out of the scope of this post, but for sure need to be dived deep into. |
Beta Was this translation helpful? Give feedback.
-
The idea of this document is fully describe how a cross contract call on NEAR can be initiated by an Aurora address.
The following considerations were taking into account while making this design:
aurora-engine
High level description
A new contract,
async.aurora
, is created and it is used to initiate transactions from NEAR to Aurora and schedule promises "created" inside aurora EVM.The workflow is as follow:
Off-chain
T
and sends it to the RPC. She pays the gas using ETH.async.aurora.submit(T)
. This is a NEAR tx so RPC should pay NEAR Gas.On-chain
async.aurora
schedules a call to aurora evm contract:aurora.submit(T)
and attaches a callback to itself to wait for the result.Vec<Promises>
, and all these promises are created.Notes:
async.aurora
. The consecuences would be that the tx would have an impact on aurora, but promises will not be scheduled.1) User sign a transaction
Alice signs a regular tx using their wallet of their preference.
2) Aurora RPC
If the tx is expecting any promises to be triggered after its execution it should be invoked through
async.aurora
. Aurora RPC needs a mechanism to tell those txs apart:The proposed solution is to have a contract deployed on aurora that will have an interface to route txs and returns promises. Aurora RPC will send all txs that target this contract through
async.aurora
.Notice: In practice nothing prevents the relayer from sending any tx through
aurora
orasync.aurora
, so it is responsibility of each aurora contract to verify if the predecessor account id is the one they expect. This is possible after #462.Implementation details of
async.aurora
Aurora Engine
CallArgs
definition.Implementation details of Aurora router contract
The main goal of this contract is to provide a signal to the RPC that this tx should be routed through
async.aurora
, only tx sent fromasync.aurora
will be accepted.Relevant notes
Changelog
Beta Was this translation helpful? Give feedback.
All reactions