Abstract

The Crosschain Interoperability Specification is a set of documents that define the implementation requirements for Enterprise Ethereum clients that do cross-blockchain communications. It defines the architectures, protocols and interfaces that facilitate discovery and enable scaleable crosschain communications.

This document describes the Crosschain Function Call interfaces and protocols that can be used to provide function calls across blockchains for Crosschain Applications.

This is a working document. It is inappropriate to cite this document other than as a work in progress.

Please send any comments to the editors of this document.

Github Issues are preferred for discussion of this document.

This document is available under the terms of the Apache License 2.0.

When referencing this document, the following citation format should be used:

[eeaciw-functioncall-v1.0] EEA CIW - Technical Specification Function Call Interface Draft Version 1.0. Edited by Weijia Zhang, Peter Robinson and Aiman Baharna. 28 February 2022. EEA CIW. https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec_function.html . Latest stage: https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec_function.html .

Introduction

The Crosschain Protocol Stack defines a way for enterprises to create interoperable components for crosschain communications. As shown in the diagram below, Crosschain Applications use Crosschain Function calls to allow business logic to be executed across blockchains. Components in the Crosschain Function Call layer rely on components in the Crosschain Messaging layer to deliver information from one blockchain to another such that the information can be trusted. This specification defines the interface that components in the Crosschain Application layer can use to call functions across blockchains, authenticate the identity of calling parties, and manage contract locking.

Crosschain Protocol Stack

Crosschain function call protocols can be atomic or non-atomic. Non-atomic protocols do not ensure consistency across blockchains. That is, a segment of the overall crosschain transaction may occur on a source blockchain, with associated updates, but the transaction on the destination blockchain may fail, and hence the updates would not be applied on the destination blockchain. A crosschain transaction segment could fail for any of the reasons described below. Non-atomic protocols must provide a mechanism to resolve failures such that consistency is restored.

Additionally, failures could occur on the source blockchain.

Atomic protocols ensure consistency across blockchains. That is, crosschain transaction segments either all succeed and updates are committed, or one or more segments fail and all updates are discarded. The precise locking model is defined by the application layer.

Section 2 defines Solidity interfaces that must be implemented by complying protocol implementations. Section 3 defines the Simple Function Call protocol, a non-atomic protocol. Section 4 defines the General Purpose Atomic Crosschain Transaction (GPACT) protocol.

The specification is currently targetted at Ethereum Virtual Machine (EVM) compatible blockchains. It defines interfaces using the Solidity programming language. It is expected that the interfaces should be able to be written in other programming languages to offer the same functionality on other blockchains.

Function Call Layer Solidity Interfaces and Helper Functions

This section defines Solidity interfaces between the Crosschain Application Layer and the Crosschain Function Call Layer for both Non-Atomic and Atomic Function Call protocols.

Non-Atomic Function Call Protocols

The sub-sections below describe Solidity interfaces and helper functions between the Crosschain Application Layer and the Crosschain Function Call Layer for Non-Atomic Function Call implementations.

CrosschainFunctionCallInterface

The Crosschain Function Call Interface allows applications to call functions on other blockchains.

R1: Non-Atomic Function Call implementations MUST support the CrosschainFunctionCallInterface interface.


pragma solidity >=0.8;

interface CrosschainFunctionCallInterface { 
  function crossBlockchainCall(uint256 _blockchainId, 
    address _contract, 
    bytes calldata _functionCallData)
    external;
}

Function crossBlockchainCall: Call a function on another blockchain.

Parameters:

  • _blockchainId: Blockchain identifier of remote blockchain to be called in EIP 3220 format.
  • _contract: Address of the contract on the remote blockchain to be called.
  • _functionCallData: The function selector and parameter data encoded using Application Binary Interface (ABI) ABI encoding rules.

Helper Functions: Application Authentication Parameters

Crosschain function call components need to determine the source blockchain and contract address on the source blockchain that initiated the crosschain function call. Functions in contracts on destination blockchains use this information to determine if the caller is authorised to execute the functionality in the function. To prevent possible attacks, these authentication parameters are provided as hidden parameters that exist outside the scope of a functions declared parameters. The parameters are appended to the call data of a function call by the function call component and extracted by the application.

R2: Non-Atomic Function Call implementations MUST encode the hidden authentication parameters using the encodeNonAtomicAuthParams function described below.

O1: Non-Atomic Function Call Applications MAY decode the parameters using the decodeNonAtomicAuthParams function to determine which contract on which blockchain called the function being executed.


pragma solidity >=0.8;
abstract contract NonAtomicHiddenAuthParams {
  function encodeNonAtomicAuthParams(
    bytes memory _functionCall,
    uint256 _sourceBlockchainId,
    address _sourceContract
  ) internal pure returns (bytes memory) {
    return bytes.concat(_functionCall, abi.encodePacked(_sourceBlockchainId, _sourceContract));
  }

  function decodeNonAtomicAuthParams()internal pure returns (
    uint256 _sourceBlockchainId,
    address _sourceContract) {
    bytes calldata allParams = msg.data;
    uint256 len = allParams.length;

    assembly {
      calldatacopy(0x0, sub(len, 52), 32)
      _sourceBlockchainId := mload(0)
      calldatacopy(12, sub(len, 20), 20)
      _sourceContract := mload(0)
  }
}        

Function encodeNonAtomicAuthParams: Append authentication parameters to the function selector and parameter data.

Parameters:

  • _functionCall: ABI encoded function selector and parameters of fuction to be called.
  • _sourceBlockchainId: Blockchain identifier of the blockchain that is calling the function, in EIP 3220 format.
  • _sourceContract: The address of the contract that is calling the function.

Function decodeNonAtomicAuthParams: Extract authentication parameters from the end of the call data.

Parameters:

  • None.

Returns:

  • _sourceBlockchainId: Blockchain identifier of the blockchain that is calling the function, in EIP 3220 format.
  • _sourceContract: The address of the contract that is calling the function.

Atomic Function Call Protocols

The sub-sections below describe Solidity interfaces and helper functions between the Crosschain Application Layer and the Crosschain Function Call Layer for Atomic Function Call implementations.

CrosschainFunctionCallInterface

The Crosschain Function Call Interface is defined in Section 2.1.1.

R3: Atomic Function Call implementations MUST support the CrosschainFunctionCallInterface interface.

CrosschainLockingInterface

The Crosschain locking interface defines the API to be used by lockable storage contracts to indicate to the function call layer that a contract has provisional updates due to the current crosschain function call.

R4: Atomic Function Call implementations MUST support the CrosschainLockingInterface interface.


interface CrosschainLockingInterface {
    /**
     * Called by a lockable storage contract to indicate that it contains one
     * or more storage locations that are being locked by the current function
     * call.
     *
     * @param _contractToLock The address of the contract contained the locked
     *        storage locations.
     */
    function addToListOfLockedContracts(address _contractToLock) external;

    /**
     * Get the combined Root Blockchain / Crosschain Transaction id for the
     * current crosschain transaction.
     *
     * @return Crosschain Root Blockchain / Transaction Id. The value is zero
     *         if there is no active crosschain call (and this is a single
     *         blockchain function call).
     */
    function getActiveCallCrosschainRootTxId() external view returns (bytes32);

    function isSingleBlockchainCall() external view returns (bool);
}

CrosschainFunctionCallReturnInterface

Crosschain Function Call Interface allows applications to call functions on other blockchains. The calls defined in this file return values.

D1: Atomic Function Call implementations that allow values to be returned SHOULD support the CrosschainFunctionCallReturnInterface interface.


interface CrosschainFunctionCallReturnInterface is
    CrosschainFunctionCallInterface
{
    /**
     * Call a function on another blockchain that returns a uint256 value. Function call implementations
     * may implement this function. Implementations that do not support this functionality should revert
     * with the message, "NOT SUPPORTED: crossBlockchainCallReturnsUint256".
     *
     * @param _bcId Blockchain identifier of blockchain to be called.
     * @param _contract The address of the contract to be called.
     * @param _functionCallData The function selector and parameter data encoded using ABI encoding rules.
     */
    function crossBlockchainCallReturnsUint256(
        uint256 _bcId,
        address _contract,
        bytes calldata _functionCallData
    ) external returns (uint256);
}

LockableStorageInterface

Lockable storage interface defines the API between the function call layer and the application layer to allow the function call layer to indicate to the application layer that locked values should be committed or discarded. Lockable storage implementations need to implement this interface.

R4: Atomic Function Call implementations MUST support the LockableStorageInterface interface.


interface LockableStorageInterface {
    /**
     * Called by the crosschain control contract when the call has been completed.
     *
     * @param _commit True if the provisional updates should be committed. False indicates the
     *         provisional updates should be discarded.
     * @param _crossRootTxId a value that indicates the transaction that has been completed.
     *        The value is the keccak256 message digest of the Root Blockchain Id and the
     *        Crosschain Transaction Id.
     */
    function finalise(bool _commit, bytes32 _crossRootTxId) external;
}

Helper Functions: Application Authentication Parameters

Crosschain function call components need to determine the root blockchain, source blockchain and contract address on the source blockchain that called the function. Functions in contracts on destination blockchains use this information to determine if the caller is authorised to execute the functionality in the function. To prevent possible attacks, these authentication parameters are provided as hidden parameters that exist outside the scope of a functions declared parameters. The parameters are appended to the call data of a function call by the function call component and extracted by the application.

R5: Atomic Function Call implementations MUST encode the hidden authentication parameters using the encodeAtomicAuthParams function described below.

O2: Atomic Function Call Applications MAY decode the parameters using the decodeAtomicAuthParams function to determine which contract on which blockchain called the function being executed.

Conforming implementations should encode the hidden authentication parameters using the encodeAtomicAuthParams function described below. Applications should decode the parameters using the decodeAtomicAuthParams function.


/**
 * Add authentication parameters to the end of an existing function call.
 *
 * @param _functionCall       Function selector and an arbitrary list of parameters.
 * @param _rootBlockchainId   Blockchain identifier of the root blockchain of the call execution tree.
 * @param _sourceBlockchainId Blockchain identifier of the blockchain that is calling the function.
 * @param _sourceContract     The address of the contract that is calling the function.
 */
function encodeAtomicAuthParams(
  bytes memory _functionCall,
  uint256 _rootBlockchainId,
  uint256 _sourceBlockchainId,
  address _sourceContract
) internal pure returns (bytes memory) {
  return
    bytes.concat(
      _functionCall,
      abi.encodePacked(
        _rootBlockchainId,
        _sourceBlockchainId,
        _sourceContract
      )
    );
}
   
/**
 * Extract authentication values from the end of the call data. The parameters are expected to have been
 * added to the end of the function call using encodeNonAtomicAuthParams.
 *
 * @return _rootBlockchainId   Blockchain identifier of the root blockchain of the call execution tree.
 * @return _sourceBlockchainId Blockchain identifier of the blockchain that is calling the function.
 * @return _sourceContract     The address of the contract that is calling the function.
 */
function decodeAtomicAuthParams()
 internal
 pure
 returns (
   uint256 _rootBlockchainId,
   uint256 _sourceBlockchainId,
   address _sourceContract
 ) {
  bytes calldata allParams = msg.data;
  uint256 len = allParams.length;
   
  assembly {
    calldatacopy(0x0, sub(len, 84), 32)
    _rootBlockchainId := mload(0)
    calldatacopy(0x0, sub(len, 52), 32)
    _sourceBlockchainId := mload(0)
    calldatacopy(12, sub(len, 20), 20)
    _sourceContract := mload(0)
  }
}

Non-Atomic Function Call Protocols

This section defines requirements specific to each supported non-atomic function call protocol.

Simple Function Call Protocol

The description of APIs and processing for the protocol will be finalised after work on GPACT has been completed.

Atomic Function Call Protocols

This section defines requirements specific to each supported atomic function call protocol.

General Purpose Atomic Crosschain Transaction Protocol

The General Purpose Atomic Crosschain Transaction (GPACT) protocol is an atomic crosschain transaction protocol. The protocol is similar to a two-phase commitment protocol. A call execution tree is committed to, then parts of the call execution tree are executed on each blockchain, resulting in provisional updates. Finally, provisional updates are committed if all parts of the execution are successful, and discarded otherwise.

The diagram at this link shows an example flow for the protocol. In the example, a function, doStuffSource in contract AppSourceChain.sol on Chain A calls doStuffTarget in contract AppSourceTarget.sol on Chain B. The execution of either or both functions could result in updates to storage values. The function doStuffTarget could return a value to doStuffSource. It should be noted that this is a simplistic example. The protocol allows for arbitrary call execution. That is, one function may call multiple functions on other blockchains. Those functions may in turn call other functions on other blockchains.

The example has an applications that uses GPACT for the Crosschain Function Call Layer implementation and Event Attestation for the Crosschain Messaging Layer implementation.

Walking through the sequence diagram:

  1. The Call Execution Tree is created by simulating the function calls.
  2. The application requests the SDK manage the exeuction of the Call Execution Tree.
  3. The SDK submits the encoded call execution tree to Crosschain Control Contract on Chain A (the Root blockchain) by calling the start function. The start function emits a Start Event. The Start Event contains the encoded call execution tree, thus locking in the call tree that will be executed.
  4. The SDK communicates with Relayer / Attestor nodes for Chain A to fetch the multiply signed event. For block header transfer mechanisms, the Relayer / Attestor nodes would have forward the block header to the destination chain and would return a Merkle proof showing that the event was part of a transaction receipt that was part of the block related to the transferred block header.
  5. The SDK submits the multiply signed Start Event and call path for the segment that is to be executed on Chain B, by calling the Crosschain Control Contract on Chain B's segment function.
  6. The Crosschain Control Contract checks that it can trust the event by calling to the Crosschain Messaging Layer contract. It then executes the application function doStuffTarget, and emits a Segment Event indicating the contracts that contain locked storage locations, and the return value from the function.
  7. The SDK communicates with Relayer / Attestor nodes for Chain B to fetch the multiply signed event.
  8. The SDK submits the multiply signed Start Event and Segment Event to the Crosschain Control Contract on Chain A's root function. This requests that the entry point function for the call tree be executed.
  9. The Crosschain Control Contract checks that it can trust the events by calling to the Crosschain Messaging Layer contract(s) that are used to verify information from Chain A and Chain B (for the Start and Segment Events respectively). It then executes the application function doStuffSource, and emits a Root Event indicating that the overall crosschain function call has been successful (or not).
  10. The SDK communicates with Relayer / Attestor nodes for chain A to fetch the multiply signed Root Event.
  11. The SDK submits the multiply signed Root Event and Segment Event to the Crosschain Control Contract on Chain B's signalling function. This requests that the contracts listed in the Segment Event have the provisional updates that relate to this crosschain transaction committed or discarded, based on the information in the Root Event.
  12. The Crosschain Control Contract checks that it can trust the events by calling to the Crosschain Messaging Layer contract(s) that are used to verify information from Chain A and Chain B (for the Root and Segment Events respectively). It then calls the finalise function on each of the contracts indicated in the Segment Event to commit or discard the provisional updates. For this example, the contract is the AppTargetChain.sol.

Start

The start function is used to register a crosschain function call with the GPACT protocol. It is the first function call of the protocol. It is called on the root blockchain of the call tree.

R6: GPACT implementations MUST implement the start function described below.

R7: GPACT implementations start functions MUST emit a start event as described below.


function start(
  uint256 _crossBlockchainTransactionId,
  uint256 _timeout,
  bytes calldata _callTree
)

Where:

  • _crossBlockchainTransactionId: An identifier that must be unique for transactions initiated from this blockchain.
  • _timeout: Period time in seconds after which this crosschain transaction will be deemed to have timed-out.
  • _callTree: Encoded arbitrary call tree. See below for the details of this encoding.

Call Trees are encoded data structures that represent the entry-point function calls to each blockchain that are expected to be called in a crosschain function call. The format of Call Trees is described below.

The encoding uses as a base type an EncodedFunction. The definition of this type is:


abi.encode(struct {
  uint256 blockchainId;
  uint160 contractAddress;
  bytes callData;
}) EncodedFunction

Where:

  • abi.encode
  • : Indicates the structure should be converted to an array of bytes using standard Application Binary Interface (ABI) encoding rules.
  • blockchainId
  • : The blockchain identifier for the blockchain that the function should be executed on.
  • contractAddress
  • : The address of contract that the function should be called on.
  • callData
  • : The standard ABI encoding for the function call. That is, a four byte Function Selector plus encoded parameters.

The encoding of the a call tree is:


struct {
  uint8 numCalledFunctions: (0 == Leaf Function, 1..255: Non-Leaf Function)
  IF (numCalledFunctions == Leaf Function) {
    EncodedFunction leafFunction
  }
  else {
    uint32[numCalledFunctions+1] startOffets
    EncodedFunction callingFunction
    CallTree[numCalledFunctions] calledFunctions
  }
}) CallTree

Where:

  • numCalledFunctions: The number of functions the function represented at this level of the call tree calls. If the function is a leaf function, it calls not other functions. In this case, numCalledFunctions will be zero.
  • leafFunction: The encoding of the function to be called.
  • startOffsets: provides start offsets of the callingFunction and calledFunctions relative to the start of the CallTree object.
  • callingFunction: The function that is calling other functions.
  • calledFunctions: An array of CallTree objects.

This structure has been used to allow EncodedFunction objects to be efficiently extracted from multi-level call trees.

NOTE: The maximum number of functions called by a calling function at any level of the call tree is 255.

The encoding of the a versioned call tree, the _callTree parameter from the function above is:


        struct {
                uint16  type = 0x0001;
                CallTree callTree;
        } VersionedCallTree

Where:

  • type: Always 0x0001 for this format of call tree.
  • callTree: The call tree to be executed.

The start event is defined as:


event Start(
  uint256 _crossBlockchainTransactionId,
  address _caller,
  uint256 _timeout,
  bytes _callTree
);

Where:

  • _crossBlockchainTransactionId: The parameter of the same name from the start call.
  • _caller: The externally owned account that called the start function.
  • _timeout: The parameter of the same name from the start call.
  • _callTree: The parameter of the same name from the start call.

Segment

The segment function call is used to execute a part of the call tree. Call trees are executed from leaf function to root, thus allowing the results of one segment to feed into the segment closer to the root call, and ultimately to the root call.

R7: GPACT implementations MUST implement the segment function described below.


function segment(
  uint256[] calldata _blockchainIds,
  address[] calldata _cbcAddresses,
  bytes32[] calldata _eventFunctionSignatures,
  bytes[] calldata _eventData,
  bytes[] calldata _signaturesOrProofs,
  uint256[] calldata _callPath
)

The segment function takes arrays of blockchain identifiers, crosschain control contract addresses, event signatures, event data, and proofs or signatures. These arrays correspond to events that were emitted on a certain blockchain by a certain crosschain control contract with a certain event signature and event data. The signatures or proofs are the information that will allow the event to be trusted on the blockchain the segment is executing on.

The first event is a start event. Subsequent events are the segment events matching the segments called from the function being executed, in execution order.

Where:

  • _blockchainIds: Array of blockchain idenfiers that events were emitted on.
  • _cbcAddresses: Array of addresses of crosschain control contracts that emitted events.
  • _eventFunctionSignatures: Array of event function signatures for emitted events.
  • _eventData: ABI encoded parameter information of the emitted event.
  • _signaturesOfProofs: Signatures or proofs encoded based on the Crosschain Messaging Protocol used to prove the validity of the emitted event.
  • _eventData: ABI encoded parameter information of the emitted event.
  • _callPath: An indication of the part of the call tree to be executed. The format of this object is defined below.

Call Paths are used to identify function calls within a call tree. They are used to indicate to the Cross Blockchain Control contract which function should be being executed. Only functions that are entry point functions for a blockchain are counted in the Call Path.

Call Paths are arrays of unsigned integers. The size of the array indicates how deep the call is in the call tree. If the final element of the array is zero, it indicates that the function calls other functions via crosschain calls. Otherwise, it indicates that the function does not execute crosschain calls.

This means that the root function call for a call tree has a path encoding of {0} indicating that it is a function that calls other functions on other blockchains via crosschain calls.

The diagram below shows functions in contracts on blockchains that call other contracts. For example, function a1a on Blockchain A in Contract A1 calls function function b1a on Blockchain B in Contract B1. This function call could be written: function a1a -> function b1a.


Blockchain A {
  Contract A1 {
    function a1a() {
      calls B.b1.b1a()
    }
    function a1b() {
      calls B.b2.b2a()
      calls C.c1.c1a()
      calls B.b2.b2b()
    }
  }
  Contract A2 {
    function a2a() {
      calls C.c2.c2a()
    }
  }
}
        
Blockchain B {
  Contract B1 {
    function b1a() {}
  }
  Contract B2 {
    function b2a() {}
    function b2b() {
      calls C.c1.c1a()
      calls C.c2.c2a()
      calls A.a2.a2a()
    }
  }
}
        
Blockchain C {
  Contract C1 {
    function c1a() {}
  }
  Contract C2 {
    function c2a() {}
  }
}

Assuming that the root function is A.a1.a1a() and that all functions in the call tree are called, then the call paths are shown in the table below.

Function Call Path Encoded Call Path
A.a1.a1a() A.a1.a1a() {0}
B.b1.b1a() A.a1.a1a() -> B.b1.b1a() {1}

Assuming that the root function is A.a1.a1b() and that all functions in the call tree are called, then the call paths are shown in the table below.

Function Call Path Encoded Call Path
A.a1.a1b() A.a1.a1b() {0}
B.b2.b2a() A.a1.a1b() -> B.b2.b2a() {1}
C.c1.c1a() A.a1.a1b() -> C.c1.c1a() {2}
B.b2.b2b() A.a1.a1b() -> B.b2.b2b() {3, 0}
C.c1.c1a() A.a1.a1b() -> B.b2.b2b() -> C.c1.c1a() {3, 1}
C.c2.c2a() A.a1.a1b() -> B.b2.b2b() -> C.c2.c2a() {3, 2}
A.a2.a2a() A.a1.a1b() -> B.b2.b2b() -> A.a2.a2a() {3, 3, 0}
C.c2.c2a() A.a1.a1b() -> B.b2.b2b() -> A.a2.a2a() -> C.c2.c2a() {3, 3, 1}

The segment event is defined as:


event Segment(
  uint256 _crossBlockchainTransactionId,
  bytes32 _hashOfCallTree,
  uint256[] _callPath,
  address[] _lockedContracts,
  bool _success,
  bytes _returnValue
);

Where:

  • _crossBlockchainTransactionId: The crosschain transaction identifier.
  • _hashOfCallTree: Keccak256 message digest of the call tree.
  • _callPath: The part of the call tree this segment pertains to.
  • _lockedContracts: Array of addresses of contracts that have one or more storage locations locked.
  • _success: true if this segment executed successfully.
  • _returnValue: ABI encoded function return result.

Root

The root function call is used to execute the root of the call tree. This function is either called after all other segments functions have been successfully called, after a segment has failed, or after the crosschain transaction has timed-out.

R7: GPACT implementations MUST implement the root function described below.


function root(
  uint256[] calldata _blockchainIds,
  address[] calldata _cbcAddresses,
  bytes32[] calldata _eventFunctionSignatures,
  bytes[] calldata _eventData,
  bytes[] calldata _signaturesOrProofs
)

Similar to the segment function, the root function takes arrays of blockchain identifiers, crosschain control contract addresses, event signatures, event data, and proofs or signatures. These arrays correspond to events that were emitted on a certain blockchain by a certain crosschain control contract with a certain event signature and event data. The signatures or proofs are the information that will allow the event to be trusted on the blockchain the segment is executing on.

The first event is a start event. Subsequent events are the segment events matching the segments called from the function being executed, in execution order.

Where:

  • _blockchainIds: Array of blockchain idenfiers that events were emitted on.
  • _cbcAddresses: Array of addresses of crosschain control contracts that emitted events.
  • _eventFunctionSignatures: Array of event function signatures for emitted events.
  • _eventData: ABI encoded parameter information of the emitted event.
  • _signaturesOfProofs: Signatures or proofs encoded based on the Crosschain Messaging Protocol used to prove the validity of the emitted event.
  • _eventData: ABI encoded parameter information of the emitted event.

The root event is defined as:


event Root(
  uint256 _crossBlockchainTransactionId, 
  bool _success
);

Where:

  • _crossBlockchainTransactionId: The crosschain transaction identifier.
  • _success: true if the crosschain transaction has been successful and all updates on all blockchains should be committed.

Signalling

The signalling function call is used to commit or discard provisional updates on blockchains that segment functions executed on and locked storage. This function must be called after the root function has been called.

R8: GPACT implementations MUST implement the signalling function described below.


function signalling(
  uint256[] calldata _blockchainIds,
  address[] calldata _cbcAddresses,
  bytes32[] calldata _eventFunctionSignatures,
  bytes[] calldata _eventData,
  bytes[] calldata _signatures
)

Similar to the segment function, the signalling function takes arrays of blockchain identifiers, crosschain control contract addresses, event signatures, event data, and proofs or signatures. These arrays correspond to events that were emitted on a certain blockchain by a certain crosschain control contract with a certain event signature and event data. The signatures or proofs are the information that will allow the event to be trusted on the blockchain the segment is executing on.

The first event is the root event. Subsequent events are the segment events for segments executed on this blockchain that locked storage.

Where:

  • _blockchainIds: Array of blockchain idenfiers that events were emitted on.
  • _cbcAddresses: Array of addresses of crosschain control contracts that emitted events.
  • _eventFunctionSignatures: Array of event function signatures for emitted events.
  • _eventData: ABI encoded parameter information of the emitted event.
  • _signaturesOfProofs: Signatures or proofs encoded based on the Crosschain Messaging Protocol used to prove the validity of the emitted event.
  • _eventData: ABI encoded parameter information of the emitted event.

Considerations

Application Authentication

Similar to existing single blockchain applications, the type of application authentication is application specific. Applications that checked msg.sender in a single blockchain context should use the decodeNonAtomicAuthParams and decodeAtomicAuthParams to check that the source blockchain and source contract are authorised to call the function. In the case of atomic crosschain function calls, the application should also check that the root blockchain of the call execution tree is authorised. Applications should limit which blockchains can be root blockchains to those blockchains that they have access to.

Glossary

Source chain:
The blockchain in which a transaction/action is initiated to be executed on a target blockchain.
Target chain:
The blockchain in which a transaction/action is executed after being initiated from a source blockchain.
Call tree:
Represents a set of functions and the calling relationships between them within a program.
Call graph commitment scheme:
Allows to evaluate and verify that the associated call graph is executed as expected.

Typographical Conventions

Requirement Ids

A requirement is uniquely identified by a unique ID composed of its requirement level followed by a requirement number, as per convention [RequirementLevelRequirementNumber]. There are four requirement levels that are coded in requirement ids as per below convention:

Note that requirements are uniquely numbered in ascending order within each requirement level.

Example : It should be read that [R1] is an absolute requirement of the specification whereas [D1] is a recommendation and [O1] is truly optional.

Conditional Requirements

Conditional requirements are expressed as per convention [ConditionalRequirementID] < [ControllingRequirementID]. A conditional requirement becomes required if and only if its controlling requirement is implemented.

For instance [CR1] < [D3] means that if recommended requirement [D3] is implemented then it is required to also implement requirement [CR1].

Appendix

Related work

[eeaciw-crosschainspec-v1.0] EEA CIW - osschain Interoperability Specification Draft Version 1.0. Edited by Weijia Zhang, Peter Robinson and Aiman Baharna. 28 February 2022. EEA CIW. https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec.html . Latest stage: https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec.html .

[eeaciw-crosschainidentification-v1.0] EEA CIW - Crosschain Identification Specification Version 1.0. Edited by Weijia Zhang and Peter Robinson. 14 December 2020. EEA CIW. https://entethalliance.github.io/crosschain-interoperability/crosschainid.html . Latest stage: https://entethalliance.github.io/crosschain-interoperability/crosschainid.html .

[eeaciw-messaging-v1.0] EEA CIW - Technical Specification Messaging Interface Draft Version 1.0. Edited by Weijia Zhang, Peter Robinson and Aiman Baharna. 28 February 2022. EEA CIW. https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec_messaging.html . Latest stage: https://entethalliance.github.io/crosschain-interoperability/draft_crosschain_techspec_messaging.html .

Acknowledgments

The EEA acknowledges and thanks the many people who contributed to the development of this draft version of the specification.

Enterprise Ethereum is built on top of Ethereum, and we grateful to the entire community who develops Ethereum, for their work and their ongoing collaboration to helps us maintain as much compatibility as possible with the Ethereum ecosystem.