Receiving Messages on Reactor
Blockchain applications that receive messages from Reactor will need to implement the execute
function. The execute
function is where
application logic, like validating the message sender and source chain, takes place. It also responsible for parsing the data from the
message’s payload
and performing tasks based on the application’s use cases.
Execute Function
function execute(
string calldata _sourceChainName,
string calldata _sourceAddress,
string calldata _action,
bytes calldata _payload
) external;
Execute message parameters
_sourceChainName
: Name of blockchain where message came from._sourceAddress
: Address for the sender of the message on the source chain._action
: Type of message that was received._payload
: Encoded action-specific data for the message.
Source Chain Name
Source Chain Names are unique identifiers that conveys the sending chain of the message. This allows the receiving application to add checks to ensure that it process messages that originate on known blockchains.
Source Address
The address of the sender from the source chain. The receiving application can use the source address to further check via a whitelist to verify that a message is coming from a trusted source.
Action
Actions are the way that convey to Reactor the intent behind the message that is being received. This allows Reactor to be simple and flexible to cover the workflows required today while staying open to enable the emerging use cases in the future.
The following actions are currently supported:
cross_chain
: Send data between blockchains.web_request
: Get or post data on a web resource (i.e. web service or API).
Although these are the only supported actions at the moment, receiving applications should anticipate new actions in the future. The choice is up to the implementer of the receiving application, but taking an approach that allows a receiving application to grow as more scenarios are enabled by Reactor allows the application to evolve to adapt to changing requirements.
Payload
On Reactor, any data that can be encoded into bytes can be delivered as the payload for a message. It is the job of the receiving application to parse the payload
and extract the needed data. This can be as simple as decoding the payload via abi
’s decode
function or a custom decoding scheme that meets the requirements of
the application. While cross_chain
or web-to-chain messages can contain any byte-encoded data, messages like web_request
will follow a predefined format.
In the case of web_request
messages, the payload received will be an ABI encoded value with the HTTP response code, the response body, and the names and values
of the response headers as message parameters. An example of how to parse a
web_request
message is below.
Message Parameters
At times, there is a need to convey additional information related to a message between Reactor and the applications. In these scenarios, like request and response headers
for web_request
messages, Reactor payloads can be encoded with parameters.
// Example of web request with headers
bytes memory web_request_payload = abi.encode("GET", "https://docs.reactor.network", "");
bytes memory payload = abi.encode(web_request_payload, ["header.NAME_1", "header.NAME_2"], ["VALUE_1", "VALUE_2"]);
For web_request
messages, the payload delivered to the contract at the destination address on
the destination chain will be encoded with parameters that include any response headers along with the HTTP response.
Since any data that is delivered to the contracts will be persisted to the blockchain, it is important to handle sensitive data in a secure manner. For these cases,
please contact the [Reactor Team] so that overrides can be added to remove any sensitive data before it is sent to contracts. In the future, there will be a self-service
portal that will allow for the management of sensitive data like API keys, credentials, or other private information for messages coming into Reactor and going out of
Reactor. This includes using this sensitive data in outgoing web_request
messages.
Examples
Here’s are two basic examples of implementing the execute
function for a message receiving contract:
Cross-Chain Message
// Example of receiving a cross_chain message
function execute(string calldata _sourceChainName, string calldata _sourceAddress, string calldata _action, bytes calldata _payload) external
{
sourceChainName = _sourceChainName;
sourceAddress = _sourceAddress;
action = _action;
payload = _payload;
last_message = abi.decode(_payload, (string));
emit ExecutableCrossChainMessageReceiverSuccess(_sourceChainName, _sourceAddress, _action, keccak256(_payload));
}
Web Request Message
// Example of receiving a web_request message
function execute(string calldata _sourceChainName, string calldata _sourceAddress, string calldata _action, bytes calldata _payload) external
{
sourceChainName = _sourceChainName;
sourceAddress = _sourceAddress;
action = _action;
payload = _payload;
(last_http_response_status_code,last_http_response_body, last_http_response_header_names, last_http_response_header_values) = abi.decode(_payload, (uint256, string, string[], string[]));
emit ExecutableWebRequestReceiverSuccess(_sourceChainName, _sourceAddress, _action, keccak256(_payload));
}