这篇文章上次修改于 843 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

跨链理论:

源码:https://github.com/nervosnetwork/force-bridge

1 跨链流程

跨链:ETH 上的 eth 跨到 CKB 上成为 eth@ckb,而不是成为 CKB 上的 ckb。成为 CKB 上的 ckb 就不仅仅是跨链了,还是交易所。

ETH --> CKB: eth lock, ckb mint。
user.drawio (7).png

CKB --> ETH: ckb burn, eth unlock
user2.drawio (8).png

ETH --> CKB
ETC-_CKB.drawio (6).png

CKB --> ETH
CKB-_ETC.drawio (3).png

2 源码阅读

2.1 ETH -> CKB

User

  • lockTx = generateBridgeInNervosTransaction() --> Watcher
  • signedTx = wallet.signTransaction(lockTx.rawTransaction)
  • sendTransaction(signedTx) to eth

Watcher

  • startRpcServer

    • 如果 !readonly,startHandlers()
    • lockETH(): emit Locked --> ETH。committee 监听该事件,去 CKB 上 mint 对应数量的 sudt。

Relayer

  • 多签方监听和转发跨链交易。角色上分为 collector 和 verifier,collector 作为主控方构造跨链交易并向 verifiers 收集签名,verifiers 验证 collector 构造的交易并签名发回。
  • collector: startRelayer()

    • startHandlers()

      • ethHandler.start(): 启动 EthHandler

        • watchNewBlock()

          • 从 eth 获取 log,针对 lock log,

            • 如果 ethLock 表中不存在,则

              • ethDb.createEthLock():则在 ethLock 表中添加记录。
              • updateBridgeInRecord(): 将 token、recipient、sudtExtraData 更新到 ckbMint 表中,将 bridgeFee 更新到 ethLock 表中。
            • 如果是 collector

              • checkLock()
              • createCollectorCkbMint(): 在 collectorCkbMint 表中插入记录。状态为 todo。
      • ckbHandler.start()

        • handleMintRecords(): Listen database to get new mint events, send tx.

          • 如果不是 collector,结束。
          • collectorCkbMint 表中获得状态为 todo 的记录,根据其 id 查询 ckbMint 表,并将其状态置为 success
          • createBridgeCell(): 从 ckbIndexer 获取 MultisigCell,作为 intput
          • collectSignatures(): 向 verifiers 发出请求 signingEntries,收集 sign
          • sealTransaction(): 用收集到的 sing 和 ckb.privateKey 加密交易
          • rpc.send_transaction(): to ckb
        • watchNewBlock(): Listen CKB chain to get new events.

          • 从 ckb 上批量获得新的区块,并获得其中的 mintTxs 和 burnTxs
          • 对于 mintTxs

            • watcherCreateMint(): 在 ckbMint 表中添加记录
            • updateBridgeInRecords(): 更新 ethLock 表中的 bridgeFee,更新 ckbMint 表中的 token、recipient、sudtExtraData
            • 如果是 collector,updateCollectorCkbMintStatus(): 将 collectorCkbMint 表中的状态更新为 success
      • btcHandler.start();
      • eosHandler.start();
      • tronHandler.start();
      • auditHandler.start();
  • verifiers: startSigServer()

    • startHandlers()
    • 添加响应,比如 signingEntries

2.2 CKB -> ETH

User

  • unlockTx = generateBridgeOutNervosTransaction() --> Watcher
  • signedTx = wallet.signTransaction(unlockTx.rawTransaction)
  • sendTransaction(signedTx) to ckb

Watcher

  • startRpcServer

    • burn(): 向 indexer 发出请求,收集 sudtCells,构造并返回 tx。

Relayer

  • 多签方监听和转发跨链交易。角色上分为 collector 和 verifier,collector 作为主控方构造跨链交易并向 verifiers 收集签名,verifiers 验证 collector 构造的交易并签名发回。
  • collector: startRelayer()

    • startHandlers

      • ckbHandler.start()

        • watchNewBlock(): Listen CKB chain to get new events.

          • 从 ckb 上批量获得新的区块,并获得其中的 mintTxs 和 burnTxs
          • 对于 burnTxs

            • 如果 ckbBurn 表中不存在

              • 从 ckb 获得 tx,插入到 ckbBurn 表。
              • updateBurnBridgeFee(): 根据 tx hash,将 ethUnlock 中相应记录的 ckbBurn 表的 bridgeFee 更新。
            • 如果是 collector

              • onCkbBurnConfirmed(): createCollectorEthUnlock() 在 collectorEthUnlock 表中添加记录,状态为 todo。
      • ethHandler.start(): 启动 EthHandler

        • watchNewBlock()

          • createWithdrawedBridgeFee()
          • createEthUnlock(): ethUnlock
          • updateBurnBridgeFee(): ckbBurn
          • 如果是 collector,updateCollectorUnlockStatus(): collectorEthUnlock 改为 success
        • handleUnlockRecords():

          • 如果不是 collector,结束。
          • getUnlockRecords(): 从 collectorEthUnlock 表获得状态为 todo 的记录,将对应 ethUnlock 记录的状态设置为 success。
          • doHandleUnlockRecords(): 将 collectorEthUnlock 中记录的状态改为 pending
          • sendUnlockTxs():

            • signUnlockRecords(): 使用 collectSignatures() 签名。
            • unlock(): emit UnLocked --> ETH。
          • saveCollectorEthUnlock()
      • btcHandler.start();
      • eosHandler.start();
      • tronHandler.start();
      • auditHandler.start();
    • verifiers: startSigServer()

      • startHandlers