资讯动态

Linera 处理资产的应用:基于临时链实现原子交换与资产安全回收

发布时间:2026/9/10 23:25:25 来源:尧图企业网站定制
Linera 处理资产的应用基于临时链实现原子交换与资产安全回收【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol导读在 Linera 的多链架构中把 Token 发送到由他人拥有的链上往往意味着把资产托管给对方如果对方不处理你的消息你就无法取回资产。本文基于 docs/developers/advanced_topics/assets.md 的核心思路讲解如何利用临时链temporary chains、所有权变更与应用权限收窄构造一个只能进、必须出的托管环境并深入剖析 matching-engine 示例 如何通过close_chain机制在关闭链时自动返还全部资产最终实现无需信任第三方的原子交换。读完本文你将掌握linera change-ownership、linera change-application-permissions两个系统命令的组合用法以及应用侧close_chain的标准实现模式。问题背景跨链资产托管中的可用性风险在 Linera 上资产例如fungible应用的 Token可以跨链转移。但这里有一个容易被忽视的信任假设如果你把 Token 发送到一条由他人拥有的链上你就依赖对方来保证资产可用。如果对方不处理你的消息例如拒绝出块、不执行你的取回请求你就无法访问自己的 Token。也就是说单纯把资金放到别人的链上并不是一个安全的行为。资产在到达目的地后能否被取回完全取决于该链的所有者是否配合。这一点正是所有先托管、后结算类 DeFi 交互例如订单簿撮合、原子交换必须解决的核心问题。解决方案用临时链构建强制回收的托管环境Linera 为此提供了一套基于临时链的解决方案。它的适用前提是参与方的数量有限且在交互开始前就已知。满足这个前提后我们可以按以下三个步骤改造一条链第一步让所有参与方都成为链的所有者使用linera change-ownership命令把参与交换的所有方都设置为该链的 ownerlinera --wait-for-outgoing-messages change-ownership \ --owners {\$OWNER_1\:100,\$OWNER_2\:100}--owners参数是一个 JSON 对象键为 owner账户地址值为权重。所有权变更后每位参与方都拥有在该链上提出区块propose block的权利因此任何一方都不再能够单方面阻止他人触碰这条链上的资产。从源码结构看ChangeOwnership是 Linera 的系统操作之一其元数据在 linera-chain/src/data_types/metadata.rs 中定义为包含super_owners、ownersowner 与 weight 的键值对、first_leader、multi_leader_rounds、open_multi_leader_rounds和timeout_config的结构。权重weight决定了该 owner 成为轮次领导者round leader的频率。第二步只允许一个应用的 Operation 在链上执行使用linera change-application-permissions命令把链上的应用执行权限收窄到唯一的应用linera --wait-for-outgoing-messages change-application-permissions \ --execute-operations [\$MATCHING_ENGINE\] \ --manage-chain [\$MATCHING_ENGINE\]这里有两个关键参数参数含义--execute-operations允许在该链上执行 operation 的应用白名单。只放行撮合引擎应用后其他应用无法再往链上塞操作。--manage-chain允许管理该链例如关闭链、变更所有权、变更权限的应用白名单。也就是说这条临时链此后只接受两类动作matching-engine 应用的 operation以及 matching-engine 应用发起的链管理操作。从 linera-sdk/src/contract/runtime.rs 可以看到应用侧也暴露了对应的change_application_permissions方法运行时的ApplicationPermissions::new_single(app_id)这种单一应用权限构造方式见下文测试代码正是这条命令的底层模型。第三步只允许关闭链这一个出口当链被收窄为单一应用可操作之后关闭链的操作也必须由该应用独占。这正是--manage-chain只填入$MATCHING_ENGINE的原因除了撮合引擎自身没有其他任何一方能够关闭这条链。这样整条临时链的语义就变成了资金只能通过撮合引擎的 operation 流入资金只能通过撮合引擎的 operation 流出链的终结关闭也由撮合引擎全权控制。源码纵深matching-engine 如何实现关闭即清退docs/developers/advanced_topics/assets.md明确指出处理资产的应用应当设计一个专门用于关闭链的 operation 或 message——当该操作被执行时它应当把链上剩余的全部资产发还出去并调用运行时的close_chain方法。examples/matching-engine/src/contract.rs 给出了完整实现。应用定义了Operation::CloseChain变体见 examples/matching-engine/src/lib.rs在execute_operation中处理async fn execute_operation(mut self, operation: Operation) - Self::Response { match operation { // ... Operation::CloseChain { for order_id in self.state.orders.indices().await.unwrap() { match self.modify_order(order_id, ModifyAmount::All).await { Some(transfer) self.send_to(transfer), // Orders with amount zero may have been cleared in an earlier iteration. None continue, } } self.runtime .close_chain() .expect(The application does not have permissions to close the chain.); } } }该实现的逻辑分两步清退全部在册订单遍历状态中所有订单的索引self.state.orders.indices()对每个订单调用modify_order(order_id, ModifyAmount::All)即把订单对应的全部代币无论是已挂出的买单还是卖单按Transfer记录通过send_to发还到各自的 owner 账户。注释专门解释了为什么可能返回None数量已清零的订单可能在更早的迭代中被清理过此时直接continue跳过。关闭链调用self.runtime.close_chain()。close_chain是 linera-sdk/src/contract/runtime.rs 提供的运行时方法/// Closes the current chain. Returns an error if the application doesnt have /// permission to do so. pub fn close_chain(mut self) - Result(), ManageChainError { contract_wit::close_chain().map_err(|error| error.into()) }注意方法签名返回Result(), ManageChainError如果应用没有--manage-chain授予的权限调用会直接失败。因此示例代码里用.expect(...)显式暴露没有权限关闭链这一失败路径。从源码结构看这一关闭即清退模式并非 matching-engine 独有同样处理Operation::CloseChain的还有 examples/amm/src/contract.rs并在 第 611 行 明确拒绝了在远端链上执行关闭操作。这可以推断关闭链的操作只能在应用所在的主链上执行跨链消息形式关闭会被拒绝。链关闭之后在途资产依然可以返回一个容易被忽略的关键设计是——关闭链并不会立刻阻止所有消息一旦链被关闭owner 仍然可以创建区块来拒绝reject消息。这样一来即使是传输中的in-flight资产也可以被退回到发送方。这一点保证了安全性闭环关闭操作是在册资产清退 封链而关闭之后新到达的跨链消息例如某笔转账还在路上可以通过拒绝消息的方式原路退回而不是永久卡在一条已经关闭的链上。因此无论资产是已在链上还是正在路上最终都有确定的回收路径。实战演练用临时链完成原子交换下面的完整流程来自 examples/matching-engine/README.md它把上文的三步改造落到了真实的 CLI 与 GraphiQL 操作上可以直接复现一次原子交换。环境准备在仓库根目录构建好linera*工具链并启动本地网络也可连接 testnetexport PATH$PWD/target/debug:$PATH source /dev/stdin $(linera net helper 2/dev/null) FAUCET_PORT8079 FAUCET_URLhttp://localhost:$FAUCET_PORT linera_spawn linera net up --with-faucet --faucet-port $FAUCET_PORT初始化钱包并申请三条链对应三个 ownerexport LINERA_WALLET$LINERA_TMP_DIR/wallet.json export LINERA_KEYSTORE$LINERA_TMP_DIR/keystore.json export LINERA_STORAGErocksdb:$LINERA_TMP_DIR/client.db linera wallet init --faucet $FAUCET_URL INFO_1($(linera wallet request-chain --faucet $FAUCET_URL)) INFO_2($(linera wallet request-chain --faucet $FAUCET_URL)) INFO_3($(linera wallet request-chain --faucet $FAUCET_URL)) CHAIN_1${INFO_1[0]} CHAIN_2${INFO_2[0]} CHAIN_3${INFO_3[0]} OWNER_1${INFO_1[1]} OWNER_2${INFO_2[1]} OWNER_3${INFO_3[1]}发布两个fungible应用作为被交换的两种 Token再发布 matching-engine 应用并传入两个 Token 的应用 IDFUN1_APP_ID$(linera --wait-for-outgoing-messages \ project publish-and-create examples/fungible \ --json-argument { \accounts\: { \$OWNER_1\: \100.\, \$OWNER_2\: \150.\ } } \ --json-parameters { \ticker_symbol\: \FUN1\ } \ ) FUN2_APP_ID$(linera --wait-for-outgoing-messages \ project publish-and-create examples/fungible \ --json-argument { \accounts\: { \$OWNER_1\: \100.\, \$OWNER_2\: \150.\ } } \ --json-parameters { \ticker_symbol\: \FUN2\ } \ ) MATCHING_ENGINE$(linera --wait-for-outgoing-messages \ project publish-and-create examples/matching-engine \ --json-parameters {\tokens\:[\$FUN1_APP_ID\,\$FUN2_APP_ID\], \price_decimals\: 2} \ --required-application-ids $FUN1_APP_ID $FUN2_APP_ID)--wait-for-outgoing-messages会等待法定数量的验证者确认所有已发出的跨链消息均已送达。将链 1 改造成临时托管链kill %% sleep 1 # 先停掉 service以便用 CLI 操作链 1 linera --wait-for-outgoing-messages change-ownership \ --owners {\$OWNER_1\:100,\$OWNER_2\:100} linera --wait-for-outgoing-messages change-application-permissions \ --execute-operations [\$MATCHING_ENGINE\] \ --manage-chain [\$MATCHING_ENGINE\] linera service --port $PORT 这三条命令完成后链 1 就变成了一条只有 owner 1、owner 2 可以出块且只能由 matching-engine 应用执行操作和关闭链的临时链。执行原子交换启动 GraphiQL 服务后linera service --port 8080按以下步骤操作Owner 2 先把自己的资产从链 1 领取到自己的链上分别在 FUN1、FUN2 两个应用的 GraphiQL 页面执行claim将链 1 上属于自己的 100 FUN1 与 150 FUN2 领到$CHAIN_2。Owner 1 挂单在链 1 的 matching-engine 页面提交一个 Bid用 1 FUN1 买 5 FUN2mutation { executeOrder( order: { Insert : { owner: $OWNER_1, quantity: 1, nature: Bid, price: { price: 500 } } } ) }Owner 2 挂单成交Owner 2 提交一个 Ask卖 2 FUN1 换 10 FUN2。该订单会与 owner 1 的 Bid 部分撮合owner 2 以 5 FUN2 的价格卖出 1 FUN1剩余 5 FUN2 留在链 1 上。关闭链并自动清退此时链 1 上还锁着 owner 2 的 5 FUN2唯一的取回方式就是由 matching-engine 关闭链mutation { closeChain }closeChain会触发上文分析的Operation::CloseChain逻辑撮合引擎遍历链上所有订单把尚未成交的代币全部发还给对应 owner然后调用close_chain。验证余额即可确认owner 2 应拿回全部资金最终在链 2 上拥有 145 FUN2。这就是原子交换的核心保证你在任何时候都可以拿回自己投入的资产——要么是还挂着的订单代币通过关闭链要么是已经成交换回的代币通过成交结算。由于链的关闭权被收窄到了撮合引擎应用任何一方都无法用拒绝出块来永久扣押资金。测试佐证关闭链后的余额断言该流程在仓库测试中有直接对应的验证。examples/matching-engine/tests/transaction.rs 展示了完整的关闭链收尾测试let permissions ApplicationPermissions::new_single(matching_id.forget_abi()); matching_chain .add_block(|block| { block.with_change_application_permissions(permissions); }) .await; matching_chain .add_block(|block| { block.with_operation(matching_id, Operation::CloseChain); }) .await; user_chain_a.handle_received_messages().await; user_chain_b.handle_received_messages().await; // Check owner balances for (owner, user_chain, amount) in [ (owner_a, matching_chain, None), (owner_b, matching_chain, None), (owner_a, user_chain_a, Some(Amount::from_tokens(4))), (owner_b, user_chain_b, Some(Amount::from_tokens(6))), ] { assert_eq!(user_chain.query_account(token_id_a, owner).await, amount); }注意测试中的两个细节ApplicationPermissions::new_single(matching_id)与 CLI 的--manage-chain [\$MATCHING_ENGINE\]等价即把链的管理权限收敛到唯一应用断言撮合链上余额为None关闭链后撮合引擎自己不再持有任何 token_a / token_b所有资产都回到了 owner 的各自链上——这正是关闭即清退语义的自动化验证。总结与适用边界维度结论核心问题把资产发送到他人拥有的链上资产可用性依赖对方是否处理消息解决前提参与方数量有限、事先已知临时链模式三个改造步骤change-ownership让各方共持change-application-permissions收窄到单一应用应用内实现CloseChain操作资产回收机制关闭链时应用遍历并清退全部在册资产 调用close_chain关闭后 owner 仍可拒绝在途消息使其退回典型应用订单簿撮合examples/matching-engine、AMMexamples/amm中的原子交换与强制结算需要强调的是这套方案并不试图解决任意数量参与方的通用托管问题一旦参与方集合是开放的、动态的临时链的所有权改造就不适用。但对于双方或多方之间的一次性资产交换它是 Linera 上一种安全、可验证、可完全由应用代码控制清算过程的模式——关闭链的时机、顺序、清退范围都写在应用自己的execute_operation里任何一方都无权绕过。【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价