作者:Cyan,imToken Labs 资深区块链工程师
本文受众:区块链开发者、对 Rollup 有所了解的区块链爱好者
本篇是 Rollup Bridge 介绍系列的第四篇。
NXTP(Noncustodial Xchain Transfer Protocol)由 Connext 研究开发而成,是一个简洁的跨链、跨 Rollup 的资产转移协议,其运作所需的资料都存在链上,秉持着去中心化的精神。
在 NXTP 之前,Connext 有开发另外一套跨链资产转移方案 Vector,但 Connext 认为 Vector 设计上有许多先天上的缺点,例如链上和链下状态同步的复杂性、依赖浏览器储存使用者资料、转账流程繁锁、资金分散导致记账上的困难等等。因此 Connext 不断地思考有没有更好的方式来进行跨链资产转移,促使 NXTP 的诞生。更多有关 NXTP 诞生的原因,以及 NXTP 如何改善 Vector 的痛点,可以参考 Connext 官方撰写的介绍文章。
本文将会聚焦在 NXTP 背后的技术实现,包含运作原理、技术细节,安全分析以及与其相似的跨链方案 cBridge 进行比较,相关资源与细节可以参考他们的文件:
https://nxtp-docs.connext.network/
运作原理
运作流程
NXTP 协议里主要有 3 种角色参与其中:User(使用者 / Sender)、Router(跨链流动性提供者)以及 Relayer(协助 User 发送跨链交易),其运作流程如下图:
NXTP transaction flow, photo from Connext
NXTP 运作分为以下三个阶段:
Step1 — Router selection
NXTP 透过 Router 相互竞标的方式,让使用者(Sender)决定要接受哪一个 Router 的报价。使用者首先会透过 NATS 讯息网络来广播跨链转账的需求,例如:从 Ethereum 上的 A 地址转账 1000 USDT 至 Arbitrum 上的 B 地址。
网络中提供跨链流动性的 Router 接收到使用者的请求后,会给出透过它进行跨链转账时的报价,例如:抽取 5% 手续费,当网络里存在多个 Router 时,就会产生多笔报价,使用者就能从多份的 Router 报价中选择对自己最有利的报价,来进行后续的流程。
Step2 — Prepare
使用者(Sender)决定接收某个 Router 的报价后,会将转账和报价的资讯一同提交给 Sender Chain 上的 NXTP 合约,合约验证资讯无误后,会将使用者指定的转账资产转移至合约上,并且发出交易准备完成的事件,来表示使用者转账的资产已经在 Sender Chain 上完成准备。
Router 会持续监控各个链上 NXTP 合约的动作,当发现自己的报价被使用者接受,并且在 Sender Chain 完成转账准备后,Router 会主动到 Receiver Chain 上的 NXTP 合约提交转账准备,收款方为使用者在 Sender Chain 转账准备时指定的 Receiver Chain 地址,转账的金额会依据 Router 报价内容扣除相关费用后,从 Router 身上转移到 NXTP 合约上,等待使用者进行拨款。
Step3 — Fulfill
使用者看到 Router 在 Receiver Chain 完成转账准备后,就能开始进行拨款的动作。使用者首先要将 Receiver Chain 拨款所需的资讯在本地端签好名,接着透过 Relayer 协助将拨款的交易发送到 Receiver Chain 上的 NXTP 合约(会有额外手续费),合约验证资讯无误后,Receiver Chain 的收款方就会收到 Router 在 Step2 代替使用者在 Receiver Chain 提交的资产。
Router 侦测到使用者完成 Receiver Chain 上的拨款后,Router 会取得使用者在 Receiver Chain 拨款交易的内容与签名,用相同的资讯对 Sender Chain 上使用者一开始在 NXTP 合约建立的转账准备进行拨款,取回 Router 在 Receiver Chain 帮使用者预付的资产,完成整个跨链转账的流程。
Relayer 的角色(有可能会由 Router 同时扮演)让使用者在 Step3 进行 Receiver Chain 上的拨款时,不需要持有 Receiver Chain 上的 gas token,取而代之的是需要支付 Relayer 额外的手续费,这个费用会在 NXTP 合约进行拨款时,从拨款的额度里扣除,因此最终 Receiver Chain 上的收款方收到的金额会是 transfer_amount — (router_fee + relayer_fee)。
使用者也可以选择不透过 Relayer,就不需要支付 Relayer 额外的手续费,但就必须准备足够的 Receiver Chain 上的 gas token 来进行拨款。
退款机制
NXTP 协议中每一笔转账都需要设定过期时间,最短为 1 天,最长为 30 天,而且 Sender Chain 上的过期时间会比 Receiver Chain 上的过期时间长,原因是这样才能使 Router 有比较充裕的时间,在使用者完成 Receiver Chain 取款后,取得使用者在 Receiver Chain 取款的资讯和签名,回到 Sender Chain 取回在 Receiver Chain 预付的款项。
NXTP 针对转账的不同时效阶段,设计了两种退款机制,来保护协议参与者的资产:
转账过期前
NXTP 允许转账收款方在转账有效期内,取消该笔转账。
若以使用者在 Sender Chain 的转账为例,其收款方为某个特定的 Router,该 Router 有权力在转账过期前,取消使用者在 Sender Chain 上的转账,NXTP 合约会立即退还资产给使用者。
若以 Router 替使用者在 Receiver Chain 提供流动性的转账为例,其收款方为使用者指定的收款地址,该地址有权力取消 Router 在 Receiver Chain 上的转账,NXTP 合约会立即退还资产给 Router。
转账过期后
NXTP 允许任何人在转账过期后,发起退款的请求,但退款时需要支付交易手续费,因此通常还是会由参与其中的利害关系人(User & Router)来执行。
技术细节
NXTP technical architecture, photo from Connext
上图为 Connext 官方所提供的 NXTP 协议技术的示意图,此章节会针对图中的不同技术区块分别做讨论,各个区块的代码可以参考 GitHub:
https://github.com/connext/nxtp
Messaging
使用者(SDK)、Router 与 Relayer 都是透过 NATS 这套分散式系统讯息交换技术来进行沟通,NATS 提供了许多讯息交互的方式,NXTP 协议主要使用了 Request-Reply 模式,来让使用者、Router 与 Relayer 之间能够进行讯息交换,更详细的技术细节可以参考 NATS 文件:
Router
目前 Router 有白名单机制,只有官方允许的人才能成为 Router。
Router 会监听来自使用者的转账请求,即时回覆使用者转账的竞标,目前 Router 预设收取的手续费为 5%,手续费目前无法透过 config 设定,需要手动更新程序调整。
有些 Router 会同时充当 Relayer,协助使用者发送 Receiver Chain 的交易并收取额外的手续费,relay 最低的手续费可以透过 config 设定,当使用者愿意支付的 relay 费用不足时,会拒绝使用者的请求。
由于 NXTP 协议的资料都储存在链上,Router 不需要资料储存机制(例如档案、资料库)来保存额外的链下状态,而是透过 Subgraph 从链上取得运作所需的资料,例如使用者在 Sender Chain 转账准备完成的资讯、使用者在 Receiver Chain 拨款完成的资讯等等,以链上的资料与状态为 NXTP 协议共识,大大简化链下资讯同步的成本。
但没有本地状态的 Router 可能会有一些效率上的问题,目前 Router 每隔一段时间会透过 Subgraph 捞取所有与自己相关的交易,包含过去已经处理过的交易,当未来 Router 处理过的交易量逐渐增加时,会衍生出效能的问题,这是后续值得追踪与改善的部分。
SDK
NXTP 提供了让 Client App 能够快速接入协议的 SDK,对于开发者来说是非常贴心的体验。
SDK 同样会透过 Subgraph 从链上取得所需的交易资料,并且设计了一套完整的报价机制,包含发送转账资讯给 Router 取得报价,以及从众多 Router 的报价中选择最优的方案的算法。除此之外,寻找 Relayer 协助在 Receiver Chain 递送交易的细节也已经完善,还能支援不透过 Relayer,由使用者自行上链的选项。
但也有与 Router 相同的问题,当交易量过大时,有可能会衍生效能的问题,值得后续关注。
Contract
NXTP 协议的合约以 TransactionManager 为核心,实现了在运作原理章节提到的 prepare、fulfill、cancel 等功能,合约实现时同时考虑到身为 Sender Chain 和 Receiver Chain 的逻辑,因此各条链上只需要部署这一份合约就好。
另外值得注意的是,合约上除了有实操 Router 白名单机制之外,Router 在为使用者服务之前,必须先将流动性加入合约之中,以合约里记录的余额来评断 Router 是否有足够的流动性来提供服务,任何人都可以透过合约来查询 Router 流动性深度,以防止 Router 流动性不足却随意报价接单,造成协议额外的成本。
安全分析
在理解 NXTP 协议的运作之后,以下对协议运作中可能产生的风险进行讨论。
- Sender 恶意询价
- Sender 询价请求会广播到整个 NXTP 网络中,Sender 可以借此发出大量的报价请求来瘫痪 Router,Router 进行报价前都会做基本的验证,其中比较耗时的步骤是到链上合约确认流动性是否足够,大量无用的报价请求有可能会导致 Router 无法服务其他用户。
- Router 恶意报价
- 恶意 Router 可以故意提供非常低的手续费来引诱使用者选择它的报价,而当使用者接受恶意 Router 的报价后,如期地在 Sender Chain 上将转账资产锁进合约,此时恶意 Router 故意不履行后续的步骤,将会导致使用者的资产被锁住,直到转账设定的期限到期。
- Relayer 挟持交易
- 由于 Router 有可能同时扮演 Relayer 的角色,当使用者想透过 Relayer 来完成 Receiver Chain 拨款的动作时,Relayer 有能力可以拦截使用者的签章资料,直接到 Sender Chain 去完成拨款,取得使用者转账的资产。若使用者没有能力自行至 Receiver Chain 上完成拨款的话,Relayer 甚至可以等到 Receiver Chain 上的转账过期,进行退款,造成使用者单方面的损失。
方案比较
NXTP 与之前分享过的 cBridge 核心原理非常相似,都是使用类似于 HTLCs 的机制来达成 Non-custodial 的跨链、跨 Rollup 的资产转移,若对于 cBridge 或 HTLCs 还不熟悉的读者,建议可以先阅读之前分享的介绍:Rollup Bridge 介绍(三):Celer cBridge。
以下将针对 NXTP 与 cBridge 设计上的异同进行分析与比较,让我们能以更宏观的角度来了解此类型的跨链资产转移方案的长处与短处。
产品阶段
cBridge 已经在主网上线,撰文当下已经支持了 9 条公链(L1、L2 都有),以及支持了许多热门的币种,如 USDT、USDC、DAI 等等。
NXTP 还在主网测试阶段,想要试用的读者可能还要再等一下。
跨链机制
cBridge 和 NXTP 都使用了类似于 HTLCs 的机制来实现 Non-custodial 的跨链转账,但各自都依据使用情境做了一些调整。
cBridge 为了提供一致的使用者体验,调整了 HTLCs 流程中第 3 与第 4 步骤,让使用者在 Sender Chain 上就能完成所有跨链转账的操作。
NXTP 忠于 HTLCs 流程,但在协议中额外引入了 Relayer 的角色,协助使用者递送交易至 Receiver Chain,目的也是让使用者只需要关注在 Sender Chain,提升使用者的体验。除此之外,NXTP 协议使用签名来代替 hash lock,唯有使用者亲自同意并签署交易,NXTP 合约才有权力去移动锁在合约上的资产。
这些调整虽然能够提升使用者体验,但是也都带来了新的风险,相关的安全议题在各自的介绍文章里都有详细的分析,在此就不赘述。
状态保存
cBridge 节点需要依赖资料库来记录链下状态,因此跑节点时必须要同时准备资料库的基础设施,也需要时时关注资料库与链上资料是否一致,当节点遭遇异常时(如宕机、网络不稳),如何从灾难中复原并确保资料不丢失,是额外的技术考验。
NXTP 将所有状态储存在链上,不管是使用者和 Router 都是透过 Subgraph 来存取链上资料,以链上状态为共识,因此不需要额外维护链下状态,也就不用担心状态不一致的问题。但也因为没有记录任何链下状态,每一次都要从捞取完整的链上资料,实操上会面临效能方面的挑战。
中心化设施
cBridge 需要借助单一 Gateway 来寻找 cBridge 节点,NXTP 则需要依靠 NATS 设施来与 Router 通讯,都存在着 SPOF(Single Point Of Failure 单点故障)的问题,官方如何确保核心单点设施的 HA(High Availability)是值得关注的议题。
结语
以上是对于 NXTP 协议背后技术实现的介绍,如果有任何想法想要分享,或是有地方想要了解更多,都可以留下留言一起讨论 😃
风险提示:本文内容均不构成任何形式的投资意见或建议。imToken 对本文所提及的第三方服务和产品不做任何保证和承诺,亦不承担任何责任。数字资产投资有风险,请谨慎评估该等投资风险,咨询相关专业人士后自行作出决定。