Rust跨链桥接库pallet-bridge-parachains的使用:实现波卡生态平行链间资产与消息的安全跨链传输

Rust跨链桥接库pallet-bridge-parachains的使用:实现波卡生态平行链间资产与消息的安全跨链传输

Bridge Parachains Pallet

bridge parachains pallet 是一个或多个桥接中继链平行链的轻客户端。它作为已最终化的平行链头的来源,当您需要与平行链建立桥接时使用。

该pallet需要在同一链上部署bridge GRANDPA pallet - 它用于验证在桥接中继链上生成的存储证明。

平行链最终性简介

关键点是平行链自行生成区块,但如果没有其relay chain的帮助,它无法实现最终性。相反,平行链收集者创建一个区块并将其交给relay chain验证者。验证者验证该区块并在relay chain上部署的paras pallet的Heads映射中注册新的平行链头。

而bridge parachains pallet所做的,就是简单地验证该Heads映射中的平行链头的存储证明。它使用之前由bridge GRANDPA pallet导入的relay chain头来完成验证。一旦证明被验证,pallet就知道给定的平行链头已被relay chain最终化。然后可以使用平行链头字段来验证来自平行链的存储证明。这使得pallet可以用作例如消息pallet的最终性来源。

Pallet操作

pallet的主要入口点是submit_parachain_heads调用。它有三个参数:

  1. 来自Heads映射的平行链头的存储证明;
  2. 存储证明中的平行链标识符及其头的哈希;
  3. 生成存储证明时的relay block。

pallet可以跟踪多个平行链。并且平行链可能使用不同的原语 - 一个可能使用128位块号,另一个使用32位。为了避免额外的解码操作,pallet使用relay chain块号来排序平行链头。

如果pallet已经知道更好(或相同)的头,它可能会拒绝平行链头。此外,pallet拒绝未被跟踪的平行链的头。

pallet不跟踪平行链头后面的任何内容。因此它不需要初始化 - 部署后立即准备接受头。

非必要功能

在部署bridge parachains模块的每个运行时中可能有一个特殊账户。这个名为"模块所有者"的账户,就像一个模块级的sudo账户 - 他能够在不要求运行时升级的情况下暂停和恢复所有模块操作。与此账户相关的调用有:

  1. fn set_owner(): 当前模块所有者可以调用它将"所有权"转移到另一个账户;
  2. fn set_operating_mode(): 模块所有者(或sudo账户)可以调用此函数停止所有模块操作。

如果未定义pallet所有者,则可以使用治理来进行这些调用。

拒绝过时头的签名扩展

对于任何人(对于链和提交者)来说,拒绝所有向pallet提交已经知道的平行链头的交易会更好。这样,我们把块空间留给其他有用的交易,并且我们不会为并发提交者的诚实行为收费。

然而,签名扩展有点有限 - 它只适用于提供单个平行链头的交易。因此它不适用于多个平行链头交易。

平行链最终性中继

我们有一个链下参与者,他正在监视新的平行链头并将它们提交到桥接链。它是平行链中继。

示例代码

// 示例代码演示如何使用pallet-bridge-parachains实现跨链传输

use frame_support::{decl_module, decl_storage, dispatch::DispatchResult};
use sp_std::prelude::*;

// 1. 定义Runtime Trait
pub trait Trait: frame_system::Trait {
    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
}

// 2. 定义存储
decl_storage! {
    trait Store for Module<T: Trait> as ParachainBridge {
        // 存储已接收的平行链头
        ReceivedHeaders get(fn received_headers): map hasher(blake2_128_concat) T::Hash => bool;
    }
}

// 3. 定义模块
decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        type Error = Error<T>;

        // 事件定义
        fn deposit_event() = default;

        // 提交平行链头的函数
        #[weight = 10_000]
        pub fn submit_parachain_header(
            origin,
            header_hash: T::Hash,
            storage_proof: Vec<u8>,
            relay_block_number: T::BlockNumber,
        ) -> DispatchResult {
            // 验证签名
            let _sender = ensure_signed(origin)?;
            
            // 验证存储证明 (简化示例)
            let is_valid = verify_storage_proof(&storage_proof);
            ensure!(is_valid, Error::<T>::InvalidStorageProof);
            
            // 检查是否已接收
            ensure!(!ReceivedHeaders::contains_key(&header_hash), Error::<T>::AlreadyReceived);
            
            // 存储头
            ReceivedHeaders::insert(&header_hash, true);
            
            // 发出事件
            Self::deposit_event(Event::HeaderReceived(header_hash, relay_block_number));
            
            Ok(())
        }
    }
}

// 4. 错误和事件定义
pub enum Error<T> {
    InvalidStorageProof,
    AlreadyReceived,
}

pub enum Event<T> where <T as frame_system::Trait>::Hash {
    HeaderReceived(T::Hash, T::BlockNumber),
}

// 5. 存储证明验证函数 (简化)
fn verify_storage_proof(proof: &[u8]) -> bool {
    // 实际实现需要验证来自relay chain的证明
    !proof.is_empty()
}

// 6. 测试模块
#[cfg(test)]
mod tests {
    use super::*;
    use frame_support::{assert_ok, assert_err};
    use sp_core::H256;
    use sp_runtime::testing::Test;
    
    type TestParachain Bridge = Module<Test>;
    
    #[test]
    fn test_submit_header() {
        let t = frame_support::GenesisConfig::default()
            .build_storage::<Test>()
            .unwrap();
        
        let mut ext = sp_io::TestExternalities::new(t);
        
        ext.execute_with(|| {
            // 第一次提交应该成功
            assert_ok!(TestParachainBridge::submit_parachain_header(
                Origin::signed(1),
                H256::random(),
                vec![1, 2, 3],
                1
            ));
            
            // 第二次提交相同头应该失败
            let header_hash = H256::random();
            assert_ok!(TestParachainBridge::submit_parachain_header(
                Origin::signed(1),
                header_hash,
                vec![1, 2, 3],
                1
            ));
            
            assert_err!(
                TestParachainBridge::submit_parachain_header(
                    Origin::signed(1),
                    header_hash,
                    vec![1, 2, 3],
                    1
                ),
                Error::<Test>::AlreadyReceived
            );
            
            // 无效存储证明应该失败
            assert_err!(
                TestParachainBridge::submit_parachain_header(
                    Origin::signed(1),
                    H256::random(),
                vec![],
                1
                ),
                Error::<Test>::InvalidStorageProof
            );
        });
    }
}

完整示例代码

// 完整示例代码演示如何使用pallet-bridge-parachains实现跨链资产和消息传输

use frame_support::{
    decl_module, decl_storage, dispatch::DispatchResult, ensure,
    traits::{Currency, Get},
    weights::{DispatchClass, Pays, Weight},
};
use frame_system::{self as system, ensure_signed};
use sp_runtime::traits::{CheckedAdd, Hash, Header as HeaderT, Zero};
use sp_std::prelude::*;

// 1. 定义Runtime Trait
pub trait Trait: frame_system::Trait {
    /// 事件类型
    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
    
    /// 使用的货币类型
    type Currency: Currency<Self::AccountId>;
    
    /// 最大消息长度
    type MaxMessageLength: Get<u32>;
    
    /// 桥接费用
    type BridgeFee: Get<BalanceOf<Self>>;
}

// 余额类型别名
type BalanceOf<T> =
    <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;

// 2. 定义存储
decl_storage! {
    trait Store for Module<T: Trait> as ParachainBridge {
        /// 存储已接收的平行链头
        ReceivedHeaders get(fn received_headers): map hasher(blake2_128_concat) T::Hash => bool;
        
        /// 存储跨链消息
        Messages get(fn messages): map hasher(blake2_128_concat) (T::Hash, u64) => Vec<u8>;
        
        /// 存储跨链资产
        Assets get(fn assets): map hasher(blake2_128_concat) (T::Hash, T::AccountId) => BalanceOf<T>;
        
        /// 下一个消息ID
        NextMessageId get(fn next_message_id): u64;
        
        /// 模块所有者
        pub Owner get(fn owner): Option<T::AccountId>;
        
        /// 模块运行模式
        pub OperatingMode get(fn operating_mode): OperatingMode;
    }
    
    add_extra_genesis {
        config(owner): Option<T::AccountId>;
        config(operating_mode): OperatingMode;
        
        build(|config| {
            if let Some(ref owner) = config.owner {
                <Owner<T>>::put(owner);
            }
            <OperatingMode>::put(config.operating_mode);
        });
    }
}

// 3. 运行模式枚举
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum OperatingMode {
    /// 正常运行
    Normal,
    /// 暂停所有操作
    Halted,
}

// 4. 定义模块
decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        type Error = Error<T>;

        // 初始化函数
        fn deposit_event() = default;

        // 设置模块所有者
        #[weight = 10_000]
        pub fn set_owner(origin, new_owner: T::AccountId) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            let current_owner = Self::owner().ok_or(Error::<T>::NoOwner)?;
            ensure!(sender == current_owner, Error::<T>::NotOwner);
            
            <Owner<T>>::put(&new_owner);
            Self::deposit_event(Event::OwnerChanged(current_owner, new_owner));
            
            Ok(())
        }

        // 设置运行模式
        #[weight = 10_000]
        pub fn set_operating_mode(origin, mode: OperatingMode) -> DispatchResult {
            let sender = ensure_signed(origin)?;
            if let Some(owner) = Self::owner() {
                ensure!(sender == owner, Error::<T>::NotOwner);
            } else {
                ensure!(sender == <system::Module<T>>::root(), Error::<T>::NotRoot);
            }
            
            <OperatingMode>::put(mode.clone());
            Self::deposit_event(Event::OperatingModeChanged(mode));
            
            Ok(())
        }

        // 提交平行链头
        #[weight = 100_000]
        pub fn submit_parachain_header(
            origin,
            header_hash: T::Hash,
            storage_proof: Vec<u8>,
            relay_block_number: T::BlockNumber,
        ) -> DispatchResult {
            // 检查运行模式
            ensure!(Self::operating_mode() == OperatingMode::Normal, Error::<T>::BridgeHalted);
            
            let sender = ensure_signed(origin)?;
            
            // 验证存储证明 (实际实现需要更复杂的验证)
            let is_valid = verify_storage_proof(&storage_proof);
            ensure!(is_valid, Error::<T>::InvalidStorageProof);
            
            // 检查是否已接收
            ensure!(!ReceivedHeaders::contains_key(&header_hash), Error::<T>::AlreadyReceived);
            
            // 存储头
            ReceivedHeaders::insert(&header_hash, true);
            
            // 发出事件
            Self::deposit_event(Event::HeaderReceived(header_hash, relay_block_number));
            
            Ok(())
        }

        // 发送跨链消息
        #[weight = 50_000 + (T::MaxMessageLength::get() as Weight).saturating_mul(10)]
        pub fn send_message(
            origin,
            target_chain: T::Hash,
            message: Vec<u8>,
        ) -> DispatchResult {
            // 检查运行模式
            ensure!(Self::operating_mode() == OperatingMode::Normal, Error::<T>::BridgeHalted);
            
            let sender = ensure_signed(origin)?;
            
            // 支付桥接费用
            T::Currency::transfer(&sender, &Self::account_id(), T::BridgeFee::get(), ExistenceRequirement::KeepAlive)?;
            
            // 检查消息长度
            ensure!(
                message.len() <= T::MaxMessageLength::get() as usize,
                Error::<T>::MessageTooLong
            );
            
            // 获取下一个消息ID
            let message_id = Self::next_message_id();
            
            // 存储消息
            Messages::insert((target_chain, message_id), message.clone());
            
            // 递增消息ID
            <NextMessageId>::put(message_id.checked_add(1).ok_or(Error::<T>::Overflow)?);
            
            // 发出事件
            Self::deposit_event(Event::MessageSent(sender, target_chain, message_id, message));
            
            Ok(())
        }

        // 发送跨链资产
        #[weight = 60_000]
        pub fn send_assets(
            origin,
            target_chain: T::Hash,
            recipient: T::AccountId,
            amount: BalanceOf<T>,
        ) -> DispatchResult {
            // 检查运行模式
            ensure!(Self::operating_mode() == OperatingMode::Normal, Error::<T>::BridgeHalted);
            
            let sender = ensure_signed(origin)?;
            
            // 支付桥接费用
            T::Currency::transfer(&sender, &Self::account_id(), T::BridgeFee::get(), ExistenceRequirement::KeepAlive)?;
            
            // 转账资产
            T::Currency::transfer(&sender, &Self::account_id(), amount, ExistenceRequirement::KeepAlive)?;
            
            // 存储资产记录
            Assets::insert((target_chain, recipient), amount);
            
            // 发出事件
            Self::deposit_event(Event::AssetsSent(sender, target_chain, recipient, amount));
            
            Ok(())
        }

        // 接收跨链消息
        #[weight = 40_000]
        pub fn receive_message(
            origin,
            source_chain: T::Hash,
            message_id: u64,
            message: Vec<u8>,
            storage_proof: Vec<u8>,
        ) -> DispatchResult {
            // 检查运行模式
            ensure!(Self::operating_mode() == OperatingMode::Normal, Error::<T>::BridgeHalted);
            
            let _sender = ensure_signed(origin)?;
            
            // 验证存储证明 (实际实现需要更复杂的验证)
            let is_valid = verify_storage_proof(&storage_proof);
            ensure!(is_valid, Error::<T>::InvalidStorageProof);
            
            // 检查消息是否已存在
            ensure!(!Messages::contains_key((source_chain, message_id)), Error::<T>::AlreadyReceived);
            
            // 存储消息
            Messages::insert((source_chain, message_id), message.clone());
            
            // 发出事件
            Self::deposit_event(Event::MessageReceived(source_chain, message_id, message));
            
            Ok(())
        }

        // 接收跨链资产
        #[weight = 50_000]
        pub fn receive_assets(
            origin,
            source_chain: T::Hash,
            recipient: T::AccountId,
            amount: BalanceOf<T>,
            storage_proof: Vec<u8>,
        ) -> DispatchResult {
            // 检查运行模式
            ensure!(Self::operating_mode() == OperatingMode::Normal, Error::<T>::BridgeHalted);
            
            let _sender = ensure_signed(origin)?;
            
            // 验证存储证明 (实际实现需要更复杂的验证)
            let is_valid = verify_storage_proof(&storage_proof);
            ensure!(is_valid, Error::<T>::InvalidStorageProof);
            
            // 检查资产是否已存在
            ensure!(!Assets::contains_key((source_chain, recipient.clone())), Error::<T>::AlreadyReceived);
            
            // 转账资产给接收者
            T::Currency::transfer(&Self::account_id(), &recipient, amount, ExistenceRequirement::AllowDeath)?;
            
            // 发出事件
            Self::deposit_event(Event::AssetsReceived(source_chain, recipient, amount));
            
            Ok(())
        }
    }
}

// 5. 错误定义
pub enum Error<T> {
    /// 无效的存储证明
    InvalidStorageProof,
    /// 消息过长
    MessageTooLong,
    /// 头或消息已接收
    AlreadyReceived,
    /// 没有设置所有者
    NoOwner,
    /// 不是所有者
    NotOwner,
    /// 不是根账户
    NotRoot,
    /// 桥接已暂停
    BridgeHalted,
    /// 算术溢出
    Overflow,
}

// 6. 事件定义
pub enum Event<T> where
    <T as frame_system::Trait>::AccountId,
    <T as frame_system::Trait>::Hash,
    BalanceOf<T>,
{
    /// 所有者变更事件
    OwnerChanged(T::AccountId, T::AccountId),
    /// 运行模式变更事件
    OperatingModeChanged(OperatingMode),
    /// 头接收事件
    HeaderReceived(T::Hash, T::BlockNumber),
    /// 消息发送事件
    MessageSent(T::AccountId, T::Hash, u64, Vec<u8>),
    /// 资产发送事件
    AssetsSent(T::AccountId, T::Hash, T::AccountId, BalanceOf<T>),
    /// 消息接收事件
    MessageReceived(T::Hash, u64, Vec<u8>),
    /// 资产接收事件
    AssetsReceived(T::Hash, T::AccountId, BalanceOf<T>),
}

// 7. 存储证明验证函数 (简化)
fn verify_storage_proof(proof: &[u8]) -> bool {
    // 实际实现需要验证来自relay chain的证明
    !proof.is_empty()
}

// 8. 模块账户ID
impl<T: Trait> Module<T> {
    pub fn account_id() -> T::AccountId {
        T::PalletId::get().into_account()
    }
}

// 9. 测试模块
#[cfg(test)]
mod tests {
    use super::*;
    use frame_support::{
        assert_err, assert_ok,
        traits::{OnInitialize, OnFinalize},
    };
    use sp_core::H256;
    use sp_runtime::{
        testing::Header,
        traits::{BlakeTwo256, IdentityLookup},
        DispatchError,
    };
    
    type Test = frame_system::Test;
    type TestParachainBridge = Module<Test>;
    
    frame_support::construct_runtime!(
        pub enum Test where
            Block = Test,
            NodeBlock = Test,
            UncheckedExtrinsic = Test,
        {
            System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
            Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
            ParachainBridge: crate::{Pallet, Call, Storage, Event<T>},
        }
    );
    
    impl frame_system::Config for Test {
        type BaseCallFilter = frame_support::traits::Everything;
        type BlockWeights = ();
        type BlockLength = ();
        type Origin = Origin;
        type Call = Call;
        type Index = u64;
        type BlockNumber = u64;
        type Hash = H256;
        type Hashing = BlakeTwo256;
        type AccountId = u64;
        type Lookup = IdentityLookup<Self::AccountId>;
        type Header = Header;
        type Event = Event;
        type BlockHashCount = ();
        type DbWeight = ();
        type Version = ();
        type PalletInfo = PalletInfo;
        type AccountData = pallet_balances::AccountData<u64>;
        type OnNewAccount = ();
        type OnKilledAccount = ();
        type SystemWeightInfo = ();
        type SS58Prefix = ();
        type OnSetCode = ();
    }
    
    impl pallet_balances::Config for Test {
        type MaxLocks = ();
        type Balance = u64;
        type DustRemoval = ();
        type Event = Event;
        type ExistentialDeposit = ();
        type AccountStore = System;
        type WeightInfo = ();
        type MaxReserves = ();
        type ReserveIdentifier = ();
    }
    
    impl Trait for Test {
        type Event = Event;
        type Currency = Balances;
        type MaxMessageLength = frame_support::traits::ConstU32<1024>;
        type BridgeFee = frame_support::traits::ConstU64<10>;
    }
    
    pub fn new_test_ext() -> sp_io::TestExternalities {
        let mut t = frame_system::GenesisConfig::default()
            .build_storage::<Test>()
            .unwrap();
        
        pallet_balances::GenesisConfig::<Test> {
            balances: vec![(1, 1000), (2, 1000), (3, 1000)],
        }
        .assimilate_storage(&mut t)
        .unwrap();
        
        crate::GenesisConfig::<Test> {
            owner: Some(1),
            operating_mode: OperatingMode::Normal,
        }
        .assimilate_storage(&mut t)
        .unwrap();
        
        t.into()
    }
    
    #[test]
    fn test_set_owner() {
        new_test_ext().execute_with(|| {
            // 初始所有者是1
            assert_eq!(TestParachainBridge::owner(), Some(1));
            
            // 非所有者不能设置所有者
            assert_err!(
                TestParachainBridge::set_owner(Origin::signed(2), 2),
                Error::<Test>::NotOwner
            );
            
            // 所有者可以设置新所有者
            assert_ok!(TestParachainBridge::set_owner(Origin::signed(1), 2));
            assert_eq!(TestParachainBridge::owner(), Some(2));
            
            // 旧所有者不能再设置所有者
            assert_err!(
                TestParachainBridge::set_owner(Origin::signed(1), 1),
                Error::<Test>::NotOwner
            );
        });
    }
    
    #[test]
    fn test_set_operating_mode() {
        new_test_ext().execute_with(|| {
            // 初始模式是Normal
            assert_eq!(TestParachainBridge::operating_mode(), OperatingMode::Normal);
            
            // 非所有者不能设置模式
            assert_err!(
                TestParachainBridge::set_operating_mode(Origin::signed(2), OperatingMode::Halted),
                Error::<Test>::NotOwner
            );
            
            // 所有者可以设置模式
            assert_ok!(TestParachainBridge::set_operating_mode(Origin::signed(1), OperatingMode::Halted));
            assert_eq!(TestParachainBridge::operating_mode(), OperatingMode::Halted);
            
            // 根账户也可以设置模式
            assert_ok!(TestParachainBridge::set_operating_mode(Origin::root(), OperatingMode::Normal));
            assert_eq!(TestParachainBridge::operating_mode(), OperatingMode::Normal);
        });
    }
    
    #[test]
    fn test_submit_parachain_header() {
        new_test_ext().execute_with(|| {
            let header_hash = H256::random();
            
            // 正常提交
            assert_ok!(TestParachainBridge::submit_parachain_header(
                Origin::signed(1),
                header_hash,
                vec![1, 2, 3],
                1
            ));
            
            // 重复提交应该失败
            assert_err!(
                TestParachainBridge::submit_parachain_header(
                    Origin::signed(1),
                    header_hash,
                    vec![1, 2, 3],
                    1
                ),
                Error::<Test>::AlreadyReceived
            );
            
            // 无效存储证明应该失败
            assert_err!(
                TestParachainBridge::submit_parachain_header(
                    Origin::signed(1),
                    H256::random(),
                vec![],
                1
                ),
                Error::<Test>::InvalidStorageProof
            );
            
            // 桥接暂停时提交应该失败
            assert_ok!(TestParachainBridge::set_operating_mode(Origin::signed(1), OperatingMode::Halted));
            assert_err!(
                TestParachainBridge::submit_parachain_header(
                    Origin::signed(1),
                    H256::random(),
                    vec![1, 2, 3],
                    1
                ),
                Error::<Test>::BridgeHalted
            );
        });
    }
    
    #[test]
    fn test_send_and_receive_message() {
        new_test_ext().execute_with(|| {
            let target_chain = H256::random();
            let message = b"Hello, world!".to_vec();
            
            // 发送消息
            assert_ok!(TestParachainBridge::send_message(
                Origin::signed(1),
                target_chain,
                message.clone()
            ));
            
            // 检查余额变化 (支付了桥接费用)
            assert_eq!(Balances::free_balance(1), 1000 - 10);
            
            // 检查消息ID递增
            assert_eq!(TestParachainBridge::next_message_id(), 1);
            
            // 接收消息
            assert_ok!(TestParachainBridge::receive_message(
                Origin::signed(1),
                target_chain,
                0,
                message.clone(),
                vec![1, 2, 3]
            ));
            
            // 检查消息存储
            assert_eq!(TestParachainBridge::messages((target_chain, 0)), message);
        });
    }
    
    #[test]
    fn test_send_and_receive_assets() {
        new_test_ext().execute_with(|| {
            let source_chain = H256::random();
            let recipient = 2;
            let amount = 100;
            
            // 发送资产
            assert_ok!(TestParachainBridge::send_assets(
                Origin::signed(1),
                source_chain,
                recipient,
                amount
            ));
            
            // 检查余额变化 (支付了桥接费用和资产)
            assert_eq!(Balances::free_balance(1), 1000 - 10 - amount);
            assert_eq!(Balances::free_balance(TestParachainBridge::account_id()), 10 + amount);
            
            // 接收资产
            assert_ok!(TestParachainBridge::receive_assets(
                Origin::signed(1),
                source_chain,
                recipient,
                amount,
                vec![1, 2, 3]
            ));
            
            // 检查余额变化 (资产已转账给接收者)
            assert_eq!(Balances::free_balance(recipient), 1000 + amount);
            assert_eq!(Balances::free_balance(TestParachainBridge::account_id()), 10);
        });
    }
}

这个完整示例展示了如何使用pallet-bridge-parachains实现以下功能:

  1. 平行链头的验证和存储
  2. 跨链消息的发送和接收
  3. 跨链资产的转移
  4. 桥接管理和控制
  5. 错误处理和测试验证

实际部署时,您还需要:

  1. 实现更复杂的存储证明验证逻辑
  2. 部署中继服务监控链上事件并提交交易
  3. 配置适当的费用和限制参数
  4. 进行全面的安全审计

1 回复

Rust跨链桥接库pallet-bridge-parachains的使用:实现波卡生态平行链间资产与消息的安全跨链传输

介绍

pallet-bridge-parachains是Substrate框架中的一个关键模块,专门设计用于在波卡(Polkadot)生态系统中实现平行链之间的安全跨链通信。这个库提供了一套完整的工具和协议,使开发者能够构建可靠的跨链桥,实现资产和消息在不同平行链之间的传输。

该模块的核心特点包括:

  • 安全的消息验证机制
  • 高效的跨链通信协议
  • 与波卡中继链的深度集成
  • 支持资产和任意数据的跨链传输

使用方法

1. 添加依赖

首先需要在项目的Cargo.toml中添加依赖:

[dependencies]
pallet-bridge-parachains = { git = "https://github.com/paritytech/parity-bridges-common.git", branch = "master" }

2. 运行时集成

在你的Substrate运行时中集成该pallet:

impl pallet_bridge_parachains::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type WeightInfo = ();
    type Bridges = (BridgeA, BridgeB); // 你定义的桥接实例
    type ParaStoredHeaderData = bp_polkadot_core::StoredHeaderData;
}

3. 定义桥接实例

pub struct BridgeA;
impl pallet_bridge_parachains::Instance for BridgeA {
    const PARACHAIN_ID: u32 = 1000; // 目标平行链ID
    const BRIDGE_ID: bp_runtime::BridgeInstanceId = b"brdg_a";
}

4. 发送跨链消息

// 在你的业务逻辑中发送跨链消息
let message = vec![1, 2, 3, 4]; // 你的消息内容
pallet_bridge-parachains::Pallet::<Runtime, BridgeA>::send_message(
    RuntimeOrigin::signed(sender),
    message,
);

5. 接收跨链消息

// 在你的runtime中实现消息接收处理
#[pallet::hooks]
impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {
    fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
        // 处理接收到的消息
        if let Some(message) = pallet_bridge_parachains::Pallet::<T, I>::receive_message() {
            // 处理消息逻辑
        }
        Weight::zero()
    }
}

完整示例

下面是一个完整的平行链间资产转移示例:

// 定义桥接实例
pub struct AssetBridge;
impl pallet_bridge_parachains::Instance for AssetBridge {
    const PARACHAIN_ID: u32 = 2000; // 目标资产平行链ID
    const BRIDGE_ID: bp_runtime::BridgeInstanceId = b"ast_br";
}

// 发送资产转移消息
fn transfer_asset_to_parachain(
    origin: OriginFor<T>,
    recipient: AccountId,
    amount: Balance,
) -> DispatchResult {
    let sender = ensure_signed(origin)?;
    
    // 1. 本地扣减资产
    <Balances as Currency<_>>::withdraw(&sender, amount, WithdrawReasons::TRANSFER, ExistenceRequirement::KeepAlive)?;
    
    // 2. 构造跨链消息
    let message = Encode::encode(&(recipient, amount));
    
    // 3. 发送跨链消息
    pallet_bridge_parachains::Pallet::<Runtime, AssetBridge>::send_message(
        RuntimeOrigin::signed(sender),
        message,
    )?;
    
    Ok(())
}

// 接收并处理资产转移消息
fn on_message_received(message: Vec<u8>) {
    if let Ok((recipient, amount)) = <(AccountId, Balance)>::decode(&mut &message[..]) {
        // 给接收方铸造资产
        <Balances as Currency<_>>::deposit_creating(&recipient, amount);
    }
}

安全注意事项

  1. 始终验证接收消息的来源和完整性
  2. 实现适当的费用机制防止滥用
  3. 考虑消息排序和重复问题
  4. 为跨链操作设置合理的权重和限制
  5. 定期监控桥接状态和安全性

通过pallet-bridge-parachains,开发者可以构建高效、安全的跨链应用,充分利用波卡生态系统的互操作性优势。

回到顶部