Cross-chain Transaction
Cross-chain Transaction is a distributed transaction executed between chains connected by IBC channel.
Cross Framework supports multiple atomic commit protocols and provides a state store that supports state commit, rollback, and concurrency control.
A chain that receives a request from a user verifies the contents of the request and sends a packet containing a contract invocation request to the specified chain to initiate a transaction. The chain that receives the user's request to initiate a transaction is called the initiator chain. Once the initiator chain receives a request, it processes the approval by each Account and then executes the Atomic commit flow according to the specified format.
For example, the initiator chain acts as a coordinator when executing Two-phase commit. First, the coordinator requests each participant chain to execute the contract function. Next, the coordinator gets the result of each call and decides whether or not to commit. After receiving the final decision, each participant chain commits or aborts the change.
Account
An account is an entity that can send transactions to a blockchain. Typically, they are required to be uniquely identified within a given blockchain. Also, accounts in one chain are generally not interoperable with accounts in another chain because each blockchain has a different concept of account and a different representation scheme.
Cross-chain contract authentication can support a variety of authentication methods by allowing accounts on any blockchain to be used. In Cross Framework, an account consists of an ID
, which is an identifier of a user on each blockchain, and authentication information called AuthType
. Thus, it is possible to identify accounts on different chains.
See here for information on the authentication methods supported by Cross Framework.
message Account {
bytes id = 1;
AuthType auth_type = 2;
}
message AuthType {
AuthMode mode = 1;
google.protobuf.Any option = 2;
}
enum AuthMode {
AUTH_MODE_UNSPECIFIED = 0;
AUTH_MODE_LOCAL = 1;
AUTH_MODE_CHANNEL = 2;
AUTH_MODE_EXTENSION = 3;
}
AuthMode
is an identifier that refers to the authentication method, and option
is the authentication information defined for each AuthMode
. For AUTH_MODE_CHANNEL
, the option
contains the Channel information, and for AUTH_MODE_EXTENSION
, the definition of the Extension protobuf.Any. Details of transaction authentication are described in Authentication.
Initiate Transaction
A user creates a transaction defined as MsgInitiateTx
below and submits it to a chain to initiate a transaction. The chain to which MsgInitiateTx
is submitted is called the initiator chain.
message MsgInitiateTx {
string chain_id = 1;
uint64 nonce = 2;
cross.core.tx.CommitProtocol commit_protocol = 3;
repeated cross.core.initiator.ContractTransaction contract_transactions = 4;
repeated cross.core.auth.Account signers = 5;
ibc.core.client.v1.Height timeout_height = 6;
uint64 timeout_timestamp = 7;
}
message ContractTransaction {
google.protobuf.Any cross_chain_channel = 1;
repeated cross.core.auth.Account signers = 2;
bytes call_info = 3;
cross.core.tx.ReturnValue return_value = 4;
repeated Link links = 5;
}
MsgInitiateTx
consists mainly of the following elements:
contract_transactions
: an array of Contract Transactions that execute Contract Module on each chaincommit_protocol
: The commit protocol for the transactiontimeout_height
,timeout_timestamp
: Specify the timeout for the transaction. The transaction will not be executed if the timeout is exceeded
A Contract Transaction consists of the following elements:
cross_chain_channel
: The IBC channel between the initiator chain and the chain where the contract to be executed existssigners
: An array ofAccounts
that need to be authenticatedcallInfo
: Call information including contract identifier, function name, and arguments. The format is Contract Module specificationreturn_value
: The return value expected from the execution of this contract (optional)links
: Optional results of other contract calls that will be referenced when this contract is executed. See the Link section for details
When a MsgInitiateTx
is submitted, it is processed by the Tx Initiator. The Tx Initiator then does the following:
- Generate a TxID from the
MsgInitiateTx
, verifies that it has not been submitted, and saves the TxID and theMsgInitiateTx
- Check if
commit_protocol
is supported by the initiator chain. - Ensure that
timeout_height
andtimeout_timestamp
have not passed
After these processes, Link processing is performed.
Link
Link is functionality to associate contract transactions that make cross-chain calls. The initiator chain resolves each link to the corresponding result of the call using Linker when the MsgInitiateTx
is submitted.
The following points should be considered when calling cross-chain contract functions:
- Each contract function may be executed in parallel on each chain
- The execution of an external contract function must be atomic to the execution of its caller function
- the calling function can reference the return value from the execution of the external contract function
Point 1. is guaranteed to be serializable by the locking mechanism in State store, and point 2. is guaranteed by Atomic commit protocol. Link is a functionality to realize point 3. and the submitter of a transaction can associate it by specifying the chain to be referred to as links
in a ContractTransaction
that performs a cross-chain call. Note that Link is represented as the index of the referenced ContractTransaction
in contract_transactions
.
The Contract Transaction (calleeTx) pointed to by Link and the Contract Transaction (callerTx) referring to Link are processed as follows:
- The Linker generates a
CallResult
whose key is composed ofcall_info
andsigners
of the calleeTx and whose value isreturn_value
- The Linker resolves the
cross_chain_channel
of the calleeTx to an IBC channel available to the caller. Then, it sets the resolved to theCallResult
- The TxInitiator generates a
ResolvedContractTransaction
from the callerTx'sContractTransaction
andCallResult
. The definition ofResolvedContractTransaction
is as follows
message ResolvedContractTransaction {
google.protobuf.Any cross_chain_channel = 1;
repeated cross.core.auth.Account signers = 2;
bytes call_info = 3;
ReturnValue return_value = 4;
repeated google.protobuf.Any call_results = 5; // List of CallResult
}
After resolving the link, the TxInitiator performs the authentication process of the Transaction.
Authentication
Transaction authentication is performed by the Authenticator. The Authenticator provides authentication methods for the initiator chain and other chains connected by the IBC channel.
Authentication of a transaction is performed by the accounts specified in signers
of each contract transaction in contract_transactions
. The execution is blocked until the authentication is completed.
The authentication must satisfy each account's method specified in AuthType
. A corresponding Msg, where the target TxID is set, is defined for each authentication method, and authorization is possible by satisfying the specified one.
Currently, SignTx
, IBCSignTx
, and ExtSignTx
are supported as authentication methods. The definitions of each method and their corresponding Msg are described below.
SignTx
SignTx is a method that uses the authentication method of the chain in which the transaction is submitted. It can authenticate accounts with AuthMode
specified as AUTH_MODE_LOCAL
.
message MsgSignTx {
bytes txID = 1;
repeated bytes signers = 2; // List of Account IDs
}
IBCSignTx
IBCSignTx is a method that uses the authentication method of the chain connected by the IBC channel to the chain where the transaction was submitted. It can authenticate accounts whose AuthMode
are specified by AUTH_MODE_CHANNEL
. Note that the accounts should have the information of the IBC channel to allow authentication as option
.
message MsgIBCSignTx {
google.protobuf.Any cross_chain_channel = 1;
bytes txID = 2;
repeated bytes signers = 3; // List of Account IDs
ibc.core.client.v1.Height timeout_height = 4;
uint64 timeout_timestamp = 5;
}
ExtSignTx
ExtSignTx is a method that performs authentication according to a developer-defined authentication formula. It can authenticate accounts whose AuthMode
are specified as AUTH_MODE_EXTENSION
.
The corresponding account has to hold proto.Message that implements AuthExtensionVerifier as option
.
message MsgExtSignTx {
bytes txID = 1;
repeated Account signers = 2;
}
type AuthExtensionVerifier interface {
proto.Message
Verify(ctx sdk.Context, signer Account, signature signing.SignatureV2, tx sdk.Tx) error
}
See here for an example of such an extended authentication implementation.
Transaction Execution
After all authentication of the transaction is completed, Tx Runner
starts the flow of Atomic Commit according to the commit_protocol
. Each step of the flow sends a packet including the ResolvedContractTransaction
corresponding to each chain; For more information on the different types of commit flows and the details of each, see the Atomic commit protocol chapter.
On each chain, a contract is processed as follows:
- Process a
ResolvedContractTransaction
and returns it to Contract Module - If the contract contains cross-chain calls, verify that the arguments
ChannelInfo
andContractCallInfo
of theCall
match the values ofCallResult
of the correspondingResolvedContractTransaction
- After the contract is executed, call the Contract Manager's Precommit or CommitImmediately depending on the commit flow to save the status
Regardless of the type of Commit flow, it is guaranteed that the update will only be committed if all Contract Transactions included in MsgInitiateTx
are successfully executed, and if any of them fail, all Contract Transactions will be aborted.