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 Messaging interfaces that can be used to provide the underlying trust needed for Crosschain Function Call protocols and 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-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 .
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 Function Call layer can use to verify information from other blockchains.
Crosschain messaging ensures participants of a target blockchain can trust that information from a source blockchain did in fact come from the source blokchain. For example, crosschain messaging mechanisms could rely on transactions on one blockchain emitting events, and the events being trusted on a target blockchain.
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.
Setup | Mechanism | Security | Decentralization | Ease of use | Computation | Scalability | |
---|---|---|---|---|---|---|---|
Multisign | Governance | Aggregation of Signatures | High. Admin addresses safeguarding | Depending on admin nodes. | Easy | Light | High |
MPC | DKG | Schnorr Signature | Group address safeguarding | Depending on validator nodes. | Easy | Light | High |
ZKP Snark | Trusted Ceremony etc | Setup dependent proof key and verfication key | Dependent on secure setup | Medium. More centralized proofer | Difficult | Heavy | Low |
ZKP Stark | No trusted setup needed | Proof and verification independent of external parameter | High security | Medium. More centralized proofer | Difficult | Heavy | Low |
Oracle | Collaboration | Smart Contract callback | Trusted Oracle nodes | Medium | Easy | Medium | High |
Light Client | Weak subjectivity | Header and state verification | High security | No additional trusted actors needed | Medium to Difficult | Medium | High |
Hybrid method | Dual Channel | Cross checking | extra security | High | Medium | Medium | Medium |
Crosschain Messaging is represented as one of the following.
Note that a message represented as event is stored in a transaction receipt where as one represented as state is stored in the state trie.
[R1]Crosschain Messaging components MUST support the Solidity interface shown below.
pragma solidity >=0.8;
interface CrosschainVerifier {
function decodeAndVerifyEvent(uint256 _blockchainId, bytes32 _eventSig,
bytes calldata _encodedInfo, bytes calldata _signatureOrProof)
external view;
}
Function decodeAndVerifyEvent
: Decode and verify event information.
Use require
to fail the transaction if any of the information is invalid.
For Ethereum Virtual Machine (EVM) based source blockchains, the event information
will be an Ethereum event.
Parameters:
_blockchainId
: The blockchain that emitted the event. This could be
used to determine which sets of signing keys should be used to verify the
signature
parameter. The _blockchainId
must be in EIP 3220 format._eventSig
: The event function-signature hash. This value is
emitted as part of an event. It identifies which event was emitted._encodedInfo
: The abi.encodePacked of the blockchain identifier
(_blockchainId
), the Crosschain Control contract's address, the
event function signature
(_eventSig
), and the event data._signatureOrProof
: Signatures or proof information that an
implementation
can use to check that _encodedInfo
is valid.One can use a similar definition to support state-based messaging and verification.
Similarly, we can define function decodeAndVerifyCommitment
with argument of _encodedInfo
to include state data instead of event data.
For example, _encodedInfo
can be a StorageRoot to represent the entire key-value state.
In decodeAndVerifyCommitment
, _signatureOrProof
is used for the proof of state representation of _encodedInfo
.
(Note that _eventSig
is not a required field in the state-based messaging.)
Signature-based verification can be applied for state-based messaging exactly as in event-based attestation.
Alternatively we can also rely on a light client verification as well.
In the latter setting, _signatureOrProof
needs to contain information necessary for header verification such as aggregated validators' signatures.
When setting StorageRoot as The sections below detail the format of signatures and proofs supported by this standard.
[R2] Complying implementations MUST support at least one of the formats
described below.
The Where: Note: The Where: Note: The Where: The Where: Signature-based verification can be used for state-based messaging as in Event Attestation. Alternatively we can also rely on a light client verification as well. In the latter setting, _encodedInfo
in decodeAndVerifyCommitment
, we need a mechanism to verify the state using StorageRoot.
For example, one can define verifyMembership(_stateInfo, _proof)
to verify the encoded state (_stateInfo
) using encoded merkle proof (_proof
) with _encodeInfo
as StorageRoot.
Unlike events in transaction receipts, the current header includes states in the past. This also contributes to reduce crosschain header transfer.
We can find a similar specification in ICS.
Format of Signatures or Proofs
Multiple ECDSA Signatures
_signatureOrProof
value for a scenario requiring one or more ECDSA signatures has the format described in this section.
It contains the abi-encoded Signatures
struct as defined below.
pragma solidity >=0.8;
struct Signature {
uint256 by;
uint256 sigR;
uint256 sigS;
uint256 sigV;
bytes meta;
}
struct Signatures {
uint256 typ;
bytes proof;
Signature[] signatures;
}
by
: The 160-bit Ethereum address derived from the 257-bit ECDSA public key of the signer.sigR
: The ECDSA signature's R value.sigS
: The ECDSA signature's S value.sigV
: The ECDSA signature's V value.meta
: The ECDSA signature's metadata containing optional information on the platform, curve and hash function that was used to create the signature.typ
: The type of signature or proof. For multiple ECDSA signatures, this is always 0x0001
.proof
: Not applicable for this scheme.signatures
: An array of signatures.
signatures
array should only contain signatures for unique by
values.
Multiple EDDSA Signatures
_signatureOrProof
value for a scenario requiring one or more EDDSA signatures has the format described in this section.
It contains the abi-encoded Signatures
struct as defined below.
pragma solidity >=0.8;
struct Signature {
uint256 by;
uint256 sigR;
uint256 sigS;
uint256 sigV;
bytes meta;
}
struct Signatures {
uint256 typ;
bytes proof;
Signature[] signatures;
}
by
: The 256-bit EDDSA public key of the signer.sigR
: The EDDSA signature's R value.sigS
: The EDDSA signature's S value.sigV
: Not applicable for EDDSA signatures.meta
: The EDDSA signature's metadata containing optional information on the platform, curve and hash function that was used to create the signature.typ
: The type of signature or proof. For multiple EDDSA signatures, this is always 0x0003
.proof
: Not applicable for this scheme.signatures
: An array of signatures.
signatures
array should only contain signatures for unique by
values.
Ethereum Block Header Proofs
_signatureOrProof
value for a scenario, requiring a Merkle Patricia proof and one or more validator
signatures, has the format described in this section. It contains the abi-encoded Signatures
struct as defined below.
pragma solidity >=0.8;
struct ProofData {
bytes witnesses;
bytes32 root;
bytes32 blockHash;
bytes blockHeaderMeta;
}
struct Signature {
uint256 by;
uint256 sigR;
uint256 sigS;
uint256 sigV;
bytes meta;
}
struct Signatures {
uint256 typ;
bytes proof;
Signature[] signatures;
}
witnesses
: The rlp-encoded sibling nodes as witnesses.root
: The block receipt, transaction or state root.blockHash
: The block hash.blockHeaderMeta
: The rlp-encoded block header metadata.by
: The 160-bit Ethereum address of the signer.sigR
: The ECDSA signature's R value.sigS
: The ECDSA signature's S value.sigV
: The ECDSA signature's V value.meta
: The ECDSA signature's metadata containing optional information on the platform, curve and hashing function that was used to create the signature.typ
: The type of proof as integer code representing Ethereum block header proofs. This is always 0x0005
.proof
: The data contained in the proof, e.g. sibling nodes, receipt root, block hash and block headers.signatures
: The array of Ethereum validator signatures.Corda Proofs
_signatureOrProof
value for a scenario, requiring a multivalued Merkle proof and one or more heterogeneous
participant signatures, has the format described in this section. It contains the abi-encoded Signatures
struct as defined below.
pragma solidity >=0.8;
struct ProofData {
bytes32 root;
bytes32[] witnesses;
uint8[] flags;
bytes32[] values;
}
struct Signature {
uint256 by;
uint256 sigR;
uint256 sigS;
uint256 sigV;
bytes meta;
}
struct Signatures {
uint256 typ;
bytes proof;
Signature[] signatures;
}
root
: The Merkle tree root.witnesses
: The Merkle multivalued proof's witnesses.flags
: The Merkle multivalued proof's flags.values
: The multivalued Merkle proof's leaves.by
: The 256-bit ECDSA public key coordinate or the 256-bit ED25519 public key of the signer.sigR
: The ECDSA/EDDSA signature's R value.sigS
: The ECDSA/EDDSA signature's S value.sigV
: The ECDSA signature's V value.meta
: The ECDSA/EDDSA signature's metadata, containing optional information on the platform, curve and hashing function that was used to create the signature.typ
: The type of proof as integer code representing Corda signature-based proofs. This is always 0x0007
.proof
: The data contained in the proof, e.g. witnesses, flags, values and/or just a root when used for trade verification.signatures
: The array of Corda participant signatures.Alternative implementation direction for state-based messaging
_signatureOrProof
needs to contain information necessary for header verification and state verification such as Merkle proof for a given state in the storage trie.
The Crosschain Messaging process is used to ensure events emitted on a source blockchain are trusted on one or more target blockchains. Cross Function Call protocols may allow for calls across multiple blockchains. In this case, multiple instantiations of the messaging protocol described below are needed to ensure all of the events emitted on various blockchains are trusted on the blockchains on which the events will be consumed.
The general flow for Crosschain Messaging processing is shown below. The processing required for specific protocols is described later in this standard.
decodeAndVerifyEvent
. This call
verifies that the event information did come from the source blockchain and can
be trusted. The sections below detail the protocol specific processing supported by this standard. [R2] Complying implementations MUST support at least one of the protocols described below.
The processing for the Event Attestation Crosschain Messaging Protocol is:
decodeAndVerifyEvent
. This call
verifies that the event information did come from the source blockchain
and can be trusted. Crosschain Messaging implementations should only sign or verify events that were created as a result of transactions that have been included in blocks that are probably final.
It may be desirable to have more than one level of finality within a system. For example, the degree of finality required for low value transaction may be different to that of a high value transaction. The low value transactions might use "fast finality" whereas the high value transactions might use "secure finality". Precise definitions of "fast finality" and "secure finality" are blockchain dependant. Additionally, for PoW blockchains, for the same blockchain, the number of blockchain confirmations that provide a certain amount of security will change over time as the network hashing power changes and the amount of hashing power that can be rented changes.
For Ethereum MainNet, fewer than eight block confirmations should be deemed "fast finality" and 12 block confirmations or more should be deemed "secure finality" (see The merits of using Ethereum MainNet as a Coordination Blockchain for Ethereum Private Sidechains.). Note that block confirmation numbers will change for Ethereum MainNet in 2022 when the Ethereum Beacon Chain is merged with the existing Ethereum MainNet Execution Chain. At this point, the historic blocks will be final at checkpoint blocks, and will have probabalistic finality between checkpoint blocks (see The Beacon Chain Ethereum 2.0 explainer you need to read first).
It is expected that different levels finality will be supported by different Crosschain Messaging components or differently configured Crosschain Messaging components.
Some crosschain messaging techniques use signatures to check the validity of information from source blockchains. Typically, these techniques have registration contracts that store the public keys of authorised signers. These registration contracts may also use the public keys as a way of verifying transactions that vote for adding or removing other authorised signers.
For ECDSA signatures, registration contracts use Ethereum Addresses as a proxy for public keys when verifying signatures. Prior to an entity registering a public key, or an Ethereum Address, it needs to be certain of the validity of the address. It needs to be certain that it has the private key associated with the address. This is particularly important if the address is also used for voting. If the address is invalid or does not match the entities private key, then the entity will be unable to vote. Depending on the voting algorithm, this could make it impossible for the incorrect address to be removed and a new address added.
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:
R
is to be interpreted as MUST as described
in RFC2119.D
is to be interpreted as SHOULD as described in
RFC2119.
O
is to be interpreted as MAY as described in RFC2119.
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 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].
[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-crosschainfunctioncall-v1.0] EEA CIW - Crosschain Function Call Interfaces Version 1.0. Edited by Weijia Zhang and Peter Robinson. 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 .
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.