Skip to content

AMB Home-to-Foreign async calls #570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 6, 2021
Merged

AMB Home-to-Foreign async calls #570

merged 10 commits into from
May 6, 2021

Conversation

k1rill-fedoseev
Copy link
Member

Closes #492

@k1rill-fedoseev k1rill-fedoseev self-assigned this Jan 11, 2021
Copy link
Collaborator

@akolotov akolotov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's think of this feature more.

  1. Imagine that we would like to get not only information provided by a method call, but also some data which cannot be received within a contract execution environment. E.g. what a block hash for the block with the number X, or whether a transaction Y is in a blockchain, or does a token Z was indeed transferred from Alice to Bob? What if requireToGetInformation is extended by an ability to specify a selector of an RPC call where eth_call is just one of them (e.g. bytes4(keccak256("eth_call")))? The AMB oracles will call the corresponding RPC with specified parameters assuming that some predefined format of the return value exists for specific RPC calls (most probably ABI v2 will be required to encode the return value on the oracle side and to decode it on the contract-recipient side).

  2. Does it makes sense to specify a method selector that must be called as a callback instead of assuming that it will by always onInformationReceived(bytes32,bool,bytes). The reason is that some contract would like to have more specific response like onInformationReceived(bytes32,bool,uint256) or onInformationReceived(bytes32,bool,bytes32). Moreover, since the contract receiving the data can be prepared with the pragma ABIEncoderV2, the input data could be quite complex (take a look at https://gist.github.com/akolotov/7ecccc0914af4869825f275305dbcf69). That's why consider a suggestion to expect the method selector from the invoking contract assuming that first two parameters of this method are messageId and status.

What do you think?

@akolotov
Copy link
Collaborator

Another thing to think (or at lease to provide reasoning) whether we need:

  • to introduce a new method confirmInformation or we can use existing one confirmAffirmation and handleMessage;
  • to introduce a new event UserRequestForInformation or we can use UserRequestForSignature -- assuming that we will up-issue the message format so there will be a special flag in the message (message header?) that means the type of action: read or write.

@k1rill-fedoseev
Copy link
Member Author

Let's think of this feature more.

  1. Imagine that we would like to get not only information provided by a method call, but also some data which cannot be received within a contract execution environment. E.g. what a block hash for the block with the number X, or whether a transaction Y is in a blockchain, or does a token Z was indeed transferred from Alice to Bob? What if requireToGetInformation is extended by an ability to specify a selector of an RPC call where eth_call is just one of them (e.g. bytes4(keccak256("eth_call")))? The AMB oracles will call the corresponding RPC with specified parameters assuming that some predefined format of the return value exists for specific RPC calls (most probably ABI v2 will be required to encode the return value on the oracle side and to decode it on the contract-recipient side).

Do you think it also makes sense to allow users to specify the exact timestamp/block number for the async call for oracles to use? Should we allow to make eth_call at the particular block in the past?

  1. Does it makes sense to specify a method selector that must be called as a callback instead of assuming that it will by always onInformationReceived(bytes32,bool,bytes). The reason is that some contract would like to have more specific response like onInformationReceived(bytes32,bool,uint256) or onInformationReceived(bytes32,bool,bytes32). Moreover, since the contract receiving the data can be prepared with the pragma ABIEncoderV2, the input data could be quite complex (take a look at https://gist.github.com/akolotov/7ecccc0914af4869825f275305dbcf69). That's why consider a suggestion to expect the method selector from the invoking contract assuming that first two parameters of this method are messageId and status.

I agree that in order to support different async call types, we should use ABIv2 encoder. But then I would prefer to use a generic onInformationReceived(bytes32,bytes) callback, where the second argument is the ABI-encoded result of the part of JSON-RPC response. Receiver contract can use abi.decode() solidity function for parsing it in the whatever type is required. This will eliminate the problem of passing/storing/reading and using of the dynamic function selector.

Another thing to think (or at lease to provide reasoning) whether we need:

  • to introduce a new method confirmInformation or we can use existing one confirmAffirmation and handleMessage;
  • to introduce a new event UserRequestForInformation or we can use UserRequestForSignature -- assuming that we will up-issue the message format so there will be a special flag in the message (message header?) that means the type of action: read or write.

Not sure about the confirmInformation and handleMessage for now, will be clear later on. But as for event, I am sure that we need a separate event for information requests. This will not break any existing monitoring tools, which expect 1-to-1 correspondence between UserRequestForSignature and RelayedMessage events. This new event can also contain indexed fields that will be very useful for monitoring async requests (call selector, request executor, request sender).

@k1rill-fedoseev k1rill-fedoseev marked this pull request as ready for review January 30, 2021 12:21
@akolotov
Copy link
Collaborator

Do you think it also makes sense to allow users to specify the exact timestamp/block number for the async call for oracles to use? Should we allow to make eth_call at the particular block in the past?

It could make sense in the following flow:

  1. a contract requests if a particular event happens
  2. as soon as it gets information which block this event happens it requests the data for this specific block

@akolotov
Copy link
Collaborator

akolotov commented Apr 20, 2021

I agree that in order to support different async call types, we should use ABIv2 encoder. But then I would prefer to use a generic onInformationReceived(bytes32,bytes) callback, where the second argument is the ABI-encoded result of the part of JSON-RPC response. Receiver contract can use abi.decode() solidity function for parsing it in the whatever type is required. This will eliminate the problem of passing/storing/reading and using of the dynamic function selector.

Agree

Not sure about the confirmInformation and handleMessage for now, will be clear later on. But as for event, I am sure that we need a separate event for information requests. This will not break any existing monitoring tools, which expect 1-to-1 correspondence between UserRequestForSignature and RelayedMessage events. This new event can also contain indexed fields that will be very useful for monitoring async requests (call selector, request executor, request sender).

Agree -- the separate event will protect from modifying existing bridge tooling. But if I develop a standard for AMB I would have the same event for both types of messages.

@k1rill-fedoseev
Copy link
Member Author

So, I have considered a way of supporting custom block requests (e.g. eth_getBalance, eth_call, eth_getTransactionCount, eth_getStorageAt). It seems that no changes are required for the contracts regarding such support. Since we are already using abi encoding into bytes blobs, the extra block number parameter can be passed in the same blob. I have added the corresponding request selectors in the oracle code PR.

@akolotov akolotov merged commit 07afe27 into develop May 6, 2021
@akolotov akolotov deleted the amb-async-calls branch May 6, 2021 10:33
akolotov added a commit that referenced this pull request May 7, 2021
This set of changes includes the following improvements and fixes:
  * [Improvement] AMB Home-to-Foreign async calls (#570), closes #492
  * [Improvement] Add GSN support for erc20-to-native bridge mode (#571)
  * [Fix] Fix issues with packages versions and linter (#600)
  * [Other] Bump package version before 6.0.0-rc0 (#598)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants