Expand description
§Partner Chain Token Bridge
This crate defines common primitive types, the inherent data provider and data source API for the token bridge feature of Partner Chains Toolkit.
§Overview
The bridge feature of the Partner Chains Toolkit allows sending the native token from Cardano to its Partner Chain in a trustless manner, making use of direct observation by the Partner Chain nodes of the Cardano ledger.
Each token transfer is made by creating a UTXO on a specific illiquid circulating supply (ICS) address in which the tokens are locked so they can be released on the Partner Chain. The feature distinguishes two types of a transfer:
- User transfers, which are sent by ordinary users and addressed to a recipient that is indicated in the datum attached to the transfer’s UTXO.
- Reserve transfers, which are sent as part of the Partner Chain’s operation, and allow the chain to gradually move its token reserve (ie. the reserve of tokens used to pay block producer rewards) from Cardano to its own ledger.
Newly made transfers are picked up by the observability layer once their blocks become stable, and are made available to the runtime as inherent data. The bridge pallet in turn makes this data available to the Partner Chains ledger by passing it to the transfer handler, which is left for each Partner Chain’s builders to implement according to their particular requirements.
§Usage
§Prerequisites
§Pallet and runtime API
Consult the documentation of pallet_partner_chains_bridge
for instructions on how to add
the bridge pallet to the runtime and implement runtime APIs. The inherent data provider
defined in this crate requires TokenBridgeIDPRuntimeApi to be implemented in the runtime.
§Data source
A data source implementing TokenBridgeDataSource is required to be present in the node.
The partner_chains_db_sync_data_sources
crate provides a production ready Db-Sync-based
implementation, and a mocked implementation is provided by partner-chains-mock-data-sources
.
See the documentation of those crates for instructions on how to add these data sources to
your node.
§Recipient type
All user transfers sent through the bridge are addressed to some recipient identified by a chain-specific type, usually an address or public key. Because the toolkit makes no assumptions about the ledger structure, this type must be provided in various places as a type parameter. This type can be arbitrary, as long as it conforms to the trait bounds required by the inherent data provider, data source and the pallet. For simple Substrate chains, the account ID type used by their ledgers is a good choice.
§Adding the inherent data provider
Include TokenBridgeInherentDataProvider in the list of InherentDataProviders
of your
implementation of [CreateInherentDataProviders]:
use sp_partner_chains_bridge::TokenBridgeInherentDataProvider;
struct AccountId;
type InherentDataProviders = (
// sp_timestamp::InherentDataProvider,
// ...
TokenBridgeInherentDataProvider<AccountId>,
);
The IDP is created the same way when proposing and validating a block:
type InherentDataProviders = ( /* other IDPs */ TokenBridgeInherentDataProvider<AccountId>);
async fn create_inherent_data_providers<T, Block>(
client: &T,
bridge_data_source: &(impl TokenBridgeDataSource<AccountId> + Send + Sync),
parent_hash: Block::Hash,
) -> Result<InherentDataProviders, Box<dyn std::error::Error + Send + Sync>>
where
Block: sp_runtime::traits::Block,
T: sp_api::ProvideRuntimeApi<Block> + Send + Sync,
T::Api: TokenBridgeIDPRuntimeApi<Block> + Send + Sync
{
/*
Create other IDPs
*/
let mc_hash: McBlockHash = todo!("provided by the MC Hash IDP from `sidechain_mc_hash` crate");
let bridge = TokenBridgeInherentDataProvider::new(
client,
parent_hash,
mc_hash,
bridge_data_source,
)
.await?;
Ok((/* other IDPs */ bridge))
}
§Adding to a running chain
TokenBridgeInherentDataProvider is version-aware and will stay inactive until the pallet is added and fully configured along with TokenBridgeIDPRuntimeApi. Thus, the correct order of steps when adding the feature to an already running chain will be:
- Initialize the bridge smart contracts on Cardano using the offchain provided by the
partner-chains-cardano-offchain
crate. This step can be performed independently from the order of other steps. - Release a new version of the chain’s node, with added data source and inhrent data provider.
- Distribute the new version and wait until most of the network’s nodes have been updated.
- Perform a runtime upgrade to a runtime version containing the pallet.
- Complete the configuration of the pallet by setting the correct main chain script and data checkpoint via an extrinsic. This step requires the governance authority to know the main chain script values, which it should obtain using the offchain.
Structs§
- Main
Chain Scripts - Smart contract hashes and addresses used by the token bridge on Cardano.
- Token
Bridge Transfers V1 - Structure representing all token bridge transfers incoming from Cardano that are to be handled in one Partner Chain block.
Enums§
- Bridge
Data Checkpoint - Value specifying the point in time up to which bridge transfers have been processed
- Bridge
Transfer V1 - Type containing all information needed to process a single transfer incoming from main chain, corresponding to a single UTXO on Cardano
- Inherent
Data Creation Error - Error type returned when creating TokenBridgeInherentDataProvider fails
- Inherent
Error - Error type returned by failing calls of the bridge inherent
- Token
Bridge Inherent Data Provider - Inherent data provider that provides data on token bridge transfers and special token transfers
Constants§
- INHERENT_
IDENTIFIER - Inherent identifier used by the Partner Chains token bridge
Traits§
- Token
Bridge Data Source - Interface for data sources that can be used by TokenBridgeInherentDataProvider
- Token
BridgeIDP Runtime Api - Runtime API used by TokenBridgeInherentDataProvider