English | 中文
This article mainly introduces how to import, set up and employ the available modules in your cosmos application, including how to initialize different keepers of different modules and configure existing asset or non-existing asset in order to carry out cross chain operations through Poly chain Poly chain.
Firstly, add these created module keepers to your decentralized application.
// make sure crosschain keepr has the permission to change supply
var (
maccPerms = map[string][]string{
auth.FeeCollectorName: nil,
distr.ModuleName: nil,
mint.ModuleName: {supply.Minter},
staking.BondedPoolName: {supply.Burner, supply.Staking},
staking.NotBondedPoolName: {supply.Burner, supply.Staking},
gov.ModuleName: {supply.Burner},
btcx.ModuleName: {supply.Burner, supply.Minter},
ft.ModuleName: {supply.Burner, supply.Minter},
lockproxy.ModuleName: {supply.Minter},
}
)
// create store key of the correlated module
keys := sdk.NewKVStoreKeys(
bam.MainStoreKey, auth.StoreKey, staking.StoreKey,
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey,
gov.StoreKey, params.StoreKey,
headersync.StoreKey, ccm.StoreKey,
btcx.StoreKey, ft.StoreKey, lockproxy.StoreKey,
)
// allocate subspace used for crosschain keeper
app.subspaces[ccm.ModuleName] = app.ParamsKeeper.Subspace(ccm.DefaultParamspace)
// create the necessary account keeper
app.accountKeeper = auth.NewAccountKeeper(app.cdc, keys[auth.StoreKey], authSubspace, auth.ProtoBaseAccount)
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace, app.ModuleAccountAddrs())
app.supplyKeeper = supply.NewKeeper(app.cdc, keys[supply.StoreKey], app.accountKeeper, app.bankKeeper, maccPerms)
// create the crosschain keeper
// for syncing poly chain vital block header into this cosmos chain
app.HeaderSyncKeeper = headersync.NewKeeper(app.cdc, keys[headersync.StoreKey])
// for processing crosschain msg from both cosmos chain and poly chain
app.CcmKeeper = ccm.NewKeeper(app.cdc, keys[ccm.StoreKey], app.subspaces[ccm.ModuleName], app.HeaderSyncKeeper, app.SupplyKeeper)
// for non-virtual machine blockchain asset to be able to be crossed into current cosmos chain
app.BtcxKeeper = btcx.NewKeeper(app.cdc, keys[btcx.StoreKey], app.AccountKeeper, app.BankKeeper, app.SupplyKeeper, app.CcmKeeper)
// for some organizations to be able to provide proxy service for some assets
app.LockProxyKeeper = lockproxy.NewKeeper(app.cdc, keys[lockproxy.StoreKey], app.AccountKeeper, app.SupplyKeeper, app.CcmKeeper)
// for creating fungible token to be crossed into/from another chain
app.FtKeeper = ft.NewKeeper(app.cdc, keys[ft.StoreKey], app.AccountKeeper, app.BankKeeper, app.SupplyKeeper, app.CcmKeeper)
// mount btcxKeeper, ftKeeper and lockproxyKeeper into ccm (cross chain manager) module
app.CcmKeeper.MountUnlockKeeperMap(map[string]ccm.UnlockKeeper{
btcx.StoreKey: app.BtcxKeeper,
ft.StoreKey: app.FtKeeper,
lockproxy.StoreKey: app.LockProxyKeeper,
})
// Msg for syncing poly chain genesis header into current cosmos chain
type MsgSyncGenesisParam struct {
Syncer sdk.AccAddress // submitter of poly chain header
GenesisHeader []byte // header bytes of poly genesis header, encoding role is the same as poly chain Header.Serialization() method
}
// Msg for syncing poly chain header into current cosmos chain
type MsgSyncHeadersParam struct {
Syncer sdk.AccAddress // submitter address
Headers [][]byte // multiple headers of poly chain block header
}
Here, ccm
means "cross chain manager" or "cross chain management". It contains two functions:
-
- It provides interface for Cosmos relayer to submit cross chain transaction coming from Poly chain. While Cosmos relayer monitoring the poly chain, once it detects a Poly chain native event aiming for current Cosmos subchain, it will get the proof from ledger store of Poly chain and construct a
MsgProcessCrossChainTx
to request for the completion of cross chain transaction on the Cosmos subchain side. Withinccm
module, the submitted header will be verified first. TheCrossStateRoot
within verified Poly chain header will be used to verify the proof. Then the actual cross chain message or transaction can be obtained. Theccm
module then checks which module should be responsible for processing the cross chain message and execute the "unlock" logic. Currently, there are three modules can process "unlock" logic, includinglockproxy
,btcx
andft
, which will be introduced later.
- It provides interface for Cosmos relayer to submit cross chain transaction coming from Poly chain. While Cosmos relayer monitoring the poly chain, once it detects a Poly chain native event aiming for current Cosmos subchain, it will get the proof from ledger store of Poly chain and construct a
-
- It provides the
CreateCrossChainTx
interface forlockproxy
,btcx
andft
modules to create cross chain transaction from current Cosmos subchain to another public chains, say, Ethereum, BTCX, Ontology, or NEO. Within this interface, there will be a unique key and immutable value consisted of current cross chain transaction stored in the ledger to represent the cross chain transaction existing in Cosmos subchain side are completed successfully.
- It provides the
Now we can easily see, MsgProcessCrossChainTx
is for Cosmos relayer to relay cross chain tx to Cosmos subchain. And CreateCrossChainTx
function is for other modules to construct cross chain tx from Cosmos subchain.
// Msg for processing cross chain msg from poly chain to current cosmos chain
// this message is designed for the cosmos-relayer to invoke
type MsgProcessCrossChainTx struct {
Submitter sdk.AccAddress // cosmos-relayer account address
FromChainId uint64 // which chain id this cross chain msg comes from
Height uint32 // which height the proof is generated at poly chain
Proof string // the proof of cross chain msg coming from poly chain for current cosmos chain to obtain the actual cross chain msg
Header []byte // the block header of poly chain containing the CrossStateRoot to verify the provided proof
}
This module supports a specific group of asset like BTC, this group of asset usually exist in a POW pulic chain without virtual machine and smart contract. When the asset crossed from its original public chain to Cosmos subchain, the native asset like BTC is usually locked within a multi-signature account in the original public chain. The asset is managed through multiple signature, and the hash of redeem script (called redeem key or redeem hash) can be interpreted as the contract hash. The amount of asset like BTC locked through this specific redeem key is that crossed through the specific multi-signed account address.
// Msg for some organizations or service provider to create btc asset contract for cross chain usage.
// `Createor` creates a kind of coin with name of `Denom` and redeem script of `RedeemScript`
// The initial supply if zero, make sure the coin with name of `Denom` has never been created before, otherwise, tx will fail
type MsgCreateCoin struct {
Creator sdk.AccAddress // the btc asset contract creator
Denom string // the name of the btc asset contract
RedeemScript string // the redeem script comes from the btc blockchain redeemscript of multiple accounts in order to
// process the cross chain transaction back to btc and ideneity the unique btc asset contract in cosmos chain
}
// this interface is designed for the denom creator to bind asset of `sourceAssetDenom` with another asset contract with hash of `ToAssetHash` in another blockchain with chain id `ToChainId`
// only the `SourceAssetDenom` creator can make the transaction successfully
type MsgBindAssetHash struct {
Creator sdk.AccAddress // this parameter should be the same as `Creator` in `MsgCreateCoin` struct, indicates that only the creator can make bind asset hash transaction successfully
SourceAssetDenom string // this parameter indicates which denom in current cosmos chain will be bonded
ToChainId uint64 // this parameter indicates the `SourceAssetDenom` will be bonded with another asset hash in which blockchain
ToAssetHash []byte // this parameter indicates the `SourceAssetDenom` will be bonded with which asset hash in `ToChainId` blockchain
}
// this interface is designed for the user to do "lock" operation, meaning user (`FromAddress`) will lock `Value` amount of `SourceAssetDenom` coins into btcx module,
// so that the address `ToAddressBs` in another blockchain with chainId (`ToChainId`) can receive the same amount of the same asset (yet in different chain).
// before user invokes this method, he/she should make sure the service provider/organization is reliable in terms of their reputation,
// correctness of paramters (say, `ToChainId` and the related `ToAssetHash` in previous message)
type MsgLock struct {
FromAddress sdk.AccAddress // the user (locker/sender) who wants to do cross chain transaction from current cosmos chain to another blockchain
SourceAssetDenom string // the kind of denom (coin) the user wants to send `Value` amount of `SourceAssetDenom` to "btcx" module
ToChainId uint64 // into which chainId, the user wants to do cross chain transaction form current cosmos chain
ToAddressBs []byte // in `ToChainId`, the receiver address is `ToAddressBs` in bytes format
Value *sdk.Int // the amount of `SourceAssetDenom` the user intends to lock
// (cross from current cosmos chain to another chain with `ToChainId`)
}
Here, ft
denotes the fungible token
, like the asset follows OEP4 protocol or ERC20 protocol. This module contains many interfaces, which can be used by the cross chain service providers, users or some project dev team wishing issuing new tokens.
As cross chain service provider, the process to use ft
module is as follow.
-
Create zero initial supply through
MsgCreateDenom
interface, such that the created token can bypasslockproxy
module to realize cross chain functionality. In detail,-
- The denom creator or token creator can bind current denom with another asset contract hash existing on another public chain through
MsgBindAssetHash
, the notation of each element of this struct is introduced later. To be noticed, in the target public chain, it's better to implement "lock" and "unlock" logic and "bindAssetHash" within asset contract rather than map asset hash with the Cosmos denom hash through `lockproxy' contract.
- The denom creator or token creator can bind current denom with another asset contract hash existing on another public chain through
-
- Once the mapping between current asset hash and the target asset hash is established on both Cosmos subchain and other chains, users can receive designated asset (denom or token) after cosmos relayer submits cross chain transaction from Poly chain to current Cosmos subchain. In addition, users can do transfer between any users within Cosmos subchain through the native module
bank
. Meanwhile, any user holding non-zero tokens can cross his or her tokens from current Cosmos subchain to any other public chains supported by Poly chain throughMsgLock
inft
module. And of course, any body can check the total supply of this token within current cosmos subchain through the nativesupply
module. Isn't it very convenient?
- Once the mapping between current asset hash and the target asset hash is established on both Cosmos subchain and other chains, users can receive designated asset (denom or token) after cosmos relayer submits cross chain transaction from Poly chain to current Cosmos subchain. In addition, users can do transfer between any users within Cosmos subchain through the native module
-
-
Besides, the new coins (tokens) issuer can create non-zero initial supply through
MsgCreateCoins
interface withinft
module, and the initial owner of these coins will be the creator. The issuer can transfer these tokens throughbank
module, or do cross chain transaction throughtlockproxy
.
// this message is for some service provider/organizations to create some fungible token with zero initial supply and is designed to
// perform cross chain transaction within `ft` module with the following two message: `MsgBindAssetHash` and `MsgLock`.
type MsgCreateDenom struct {
Creator sdk.AccAddress // `Denom` creator
Denom string // coin name being created with initial zero supply
}
// this interface is designed for the denom creator to bind asset of `sourceAssetDenom` with another asset contract with hash of `ToAssetHash` in another blockchain with chain id `ToChainId`
// only the `SourceAssetDenom` creator can make the transaction successfully
type MsgBindAssetHash struct {
Creator sdk.AccAddress // this parameter should be the same as `Creator` in the above `MsgCreateDenom` struct, indicates that only the creator can make bind asset hash transaction successfully
SourceAssetDenom string // this parameter indicates which denom in current cosmos chain will be bonded
ToChainId uint64 // this parameter indicates the `SourceAssetDenom` will be bonded with another asset hash in which blockchain
ToAssetHash []byte // this parameter indicates the `SourceAssetDenom` will be bonded with which asset hash in `ToChainId` blockchain
}
// this interface is designed for the user to do "lock" operation, meaning user (`FromAddress`) will burn `Value` amount of `SourceAssetDenom` coins to air,
// so that the address `ToAddressBs` in another blockchain with chainId (`ToChainId`) can receive the same amount of the same asset (yet in different chain).
// before user invokes this method, he/she should make sure the service provider/organization is reliable in terms of their reputation,
// correctness of paramters (say, `ToChainId` and the related `ToAssetHash` in previous message)
type MsgLock struct {
FromAddress sdk.AccAddress // the user (locker/msg sender) who wants to do cross chain transaction from current cosmos chain to another blockchain
SourceAssetDenom string // the kind of denom (coin) the user wants to burn `Value` amount of `SourceAssetDenom`
ToChainId uint64 // into which chainId, the user wants to do cross chain transaction form current cosmos chain
ToAddressBs []byte // in `ToChainId`, the receiver address is `ToAddressBs` in bytes format
Value *sdk.Int // the amount of `SourceAssetDenom` the user intends to do cross chain
// (from current cosmos chain to another chain with `ToChainId`)
}
// this interface is designed for everyone to create multiple coins, which are available for both `bank` and `supply` modules in cosmos-sdk. The coins should have valid format
// in terms of coin.Denom and coin.Amount. All the initialized coins are distributed to the `Creator`.
type MsgCreateCoins struct {
Creator sdk.AccAddress // coins' creator
Coins string // Coins should be the format of "100000MySimpleToken,2000000MST"
}
This module contains common interface for cross chain request through lockproxy
module. There are two types of invokers separated by the roles.
As the service provider or lockproxy provider, the instruction to use lockproxy
module are the followings.
- The
lockproxy
creator (service provider) invokeMsgCreateLockProxy
to create the globally unique in current cosmos subchain and his or her own lockproxy contract. - The denom creator can invoke
MsgCreateAndDelegateCoinToProxy
to create non-zero initial supply tokens and delegate them to the reliable (or his ownlockproxy
contract created as the above step). Here "reliable" also including trusting thelockproxy
contracts in all the other public chains issued by currentlockproxy
creator and their operation of binding or mapping the asset hashes. - The
lockproxy
creator sets up the map throughMsgBindProxyHash
interface from currentlockproxy
contract hash (same as the creator address in hex format) to the correlatedlockproxy
contract hash in another public chain if it has not been set up before. - The
lockproxy
creator sets up the map throughMsgBindAssetHash
interface from current asset hash (hex format of bytes from denom) to the same asset hash deployed in another public chain. Note that the creator should also do bindAssetHash in another side of public chain. - Condition check:
- Coin creator request the reliable
lockproxy
creator to confirm theBindProxyHash
operation is completed. And anybody can check if the mapping relation betweenlockproxy
contract hash is correct through rest client. - Coin creator request the reliable
lockproxy
creator to confirm theBindAssetHash
operation is completed. And anybody can check if the mapping relation between asset contract hash is correct through rest client.
- Coin creator request the reliable
- After the configuration of cross chain environment is completed correctly, users can receive coins unlocked from
lockproxy
module account when the cosmos relayer submit the cross chain proof generated on Poly chain and Poly chain block header containing the state root of that proof. Then any user holding non-zero coins can transfer their coins to others throughbank
module within cosmos-sdk or do cross chain transaction to other public chains throughMsgLock
withinlockproxy
module.
As users employing the cross chain service, they can do cross chain transaction through lockproxy.MsgLock
directly, before which it should be noted that they should have enough coins, which can be either those transferred from other accounts or those unlocked from lockkproxy
module account due to the cross chain transaction submission by cosmos relayer.
Next we explain each part of the struct in detail.
// this message is for the cross chain service provider to invoke in order to create a new lockproxy contract.
// the lockproxy contract address is identified by the creator's account address. One account can only create one lockproxy
type MsgCreateLockProxy struct {
Creator sdk.AccAddress
}
// this message is for some service provider/organizations to create some fungible token with non-zero initial supply
// and delegate all the coins to `lockproxy` module, which will be introduced later. This coin is prepared for the target chain asset in cosmos chain.
// Actually, there is no much difference speaking of who is the coin creator since the critical part is that the `lockproxy` operator should do "BindProxyHash" and "BindAssetHash" correctly.
// for some service provider who wishes to do cross chain transaction through the `lockproxy` module below, you should invoke this transaction to create your token/coin.
type MsgCreateAndDelegateCoinToProxy struct {
Creator sdk.AccAddress // coin creator
Coin sdk.Coin // coin should have the format of "100000MySimpleToken" with supply of 100000 and name of "MySimpleToken"
}
// this message is for lockproxy creator to bind current lockproxy contract with another lockproxy contract in another chain.
type MsgBindProxyHash struct {
Operator sdk.AccAddress // `Operator` should be the lockproxy creator
ToChainId uint64 // `ToChainId` indicates another chain the current lockproxy is able to reach
ToChainProxyHash []byte // `ToChainProxyHash` indicates the lockproxy contract hash in another chain that
// can reach the current lockproxy contract.
}
// this message is for lockproxy creator to bind current asset denom `SourceAssetDenom` with the same asset
// with hash of `ToAssetHash` yet in another chain with `ToChainId`. The initial amount prepared for cross chain transaction
// is `InitialAmt`, meaning `InitialAmt` of `SourceAssetDenom` should already in `lockproxy` module account.
// Now we can see, this message should be invoked after `MsgCreateAndDelegateCoinToProxy` of `ft` module is invoked.
type MsgBindAssetHash struct {
Operator sdk.AccAddress // `Operator` should be the lockproxy creator
SourceAssetDenom string // `SourceAssetDenom` is the coin kind correlated with the asset of `ToAssetHash` in `ToChainId` blockchain
ToChainId uint64 // another chain with `ToChainId` that holds the `ToAssetHash`, and are supported by the poly chain
ToAssetHash []byte // the asset hash existing in `ToChainId` chain
InitialAmt sdk.Int // the initial amount of `SourceAssetDenom` that the `lockproxy` module account holds
}
// this interface is designed for the user to do "lock" operation, meaning user (`FromAddress`) will burn `Value` amount of `SourceAssetDenom` coins to air,
// so that the address `ToAddressBs` in another blockchain with chainId (`ToChainId`) can receive the same amount of the same asset (yet in different chain).
// before user invokes this method, he/she should make sure the service provider/organization is reliable in terms of their reputation,
// correctness of paramters (say, `ToChainId` and the related `ToAssetHash` in previous message)
type MsgLock struct {
LockProxyHash []byte // current lockproxy the FromAddress wants to use to do cross chain transaction
FromAddress sdk.AccAddress // the user (locker/msg sender) who wants to do cross chain transaction from current cosmos chain to another blockchain
SourceAssetDenom string // the kind of denom (coin) the user wants to burn `Value` amount of `SourceAssetDenom`
ToChainId uint64 // into which chainId, the user wants to do cross chain transaction form current cosmos chain
ToAddressBs []byte // in `ToChainId`, the receiver address is `ToAddressBs` in bytes format
Value *sdk.Int // the amount of `SourceAssetDenom` the user intends to do cross chain
// (from current cosmos chain to another chain with `ToChainId`)
}
Here explains the cross chain operation in detail.
About the asset cross chain interoperability, please refer to this proposal, PIP-1.
The Poly Network library is licensed under the GNU Lesser General Public License v3.0. Please refer to the LICENSE file in the root directory of the project for details.