# IBC 是什么？Cosmos 跨链跟其他妖艳贱货有什么不一样？

By [Cosmos 爱好者](https://paragraph.com/@cosmosfans) · 2022-01-10

---

各位不知是否用过 Cosmos 生态的跨链工具？如果没有的话建议去用一下，奶一般顺滑。按我之前写的这个[教程](https://mirror.xyz/0x0cfA8593065464B1AcA37B2B3e07A76EA9c171fb/QMbMzoC1gpAJcLyHXHpCHwnZcUBIf4Wc8KEZVWwuHh0)走下来就好，说不定还有空投哦。那大家是否好奇过 Cosmos 的跨链是怎么做到的？它跟主流 EVM 生态上跨链又有什么区别呢？

经常用 Cosmos 跨链的同学应该也经常听到一个名词就是 [IBC](https://ibcprotocol.org/)，全称叫 `INTER‑BLOCKCHAIN COMMUNICATION PROTOCOL`（链间通信协议）。字如其名，它是一款**链与链之间的通信协议**，类比互联网相当于 TCP/IP 协议。因此实现了 IBC 协议的两条链就像能听懂对方语言的老乡，互相沟通毫无障碍。同时也类似互联网上 HTTP 等等协议能基于 TCP/IP 协议之上构建，因此我们也就能基于 IBC 之上构建代币跨链协议（能听懂对方语言当然也就方便做买卖了）。当然，IBC 并不是 Cosmos 的专利，目前包括 Polkadot, Solana 在内的多家项目方也在积极实现 IBC 协议，而 Cosmos 算是最早实现也是最早把 IBC 用起来的生态了。

![ibc_working](https://storage.googleapis.com/papyrus_images/25ed46b04cabf561c20fc7d34281eab74b0b65795a5b7ea2c9a21ea501d704d3.png)

ibc\_working

那 IBC 是怎么工作的呢？它首先需要一个类似中间人的角色叫 `Relayer`，在正式跨链之前它首先需要分别向这俩链请求连接（`Connection`）并建立通道（`Channel`）。这个通道是双向且绑定的，因为通道需要被赋予唯一 ID 且不同的链曾经被申请过的通道数量不一样，所以我们会看到相同的通道在不同的链所被赋予的 ID 是不同的（例如 Cosmos Hub 跟 Osmosis 之间最常用的通道是 `Cosmos Hub/Channel-141 <=> Osmosis/Channel-0`），当通道建立起来后就可以开始通信了。

现在你们两位老乡已经可以开始聊天了，那聊天是不是需要找个话题？类似的，IBC 传输的内容也需要同时带上"话题"(`Port`)。例如 Cosmos 生态**代币跨链**双方约定的“话题”就是 `transfer`。当你想从 A 链跨到 B 链，你首先需要在 A 链发起特定的跨链交易；等这笔交易被 A 链确认后，`Relayer`便会把这笔交易以及相关证明（`Proof`）转发到 B 链；B 链随后验证这笔交易及其证明，如果正常便会按照既定的逻辑执行相关操作。想深入了解的同学可以看 [Cosmos 官方介绍](https://ibc.cosmos.network/main/ibc/overview.html) 。

诶，等等，那我的币从 A 跨到 B 是意味着这个币从 A 链消失了吗？**不一定**，我们可以看下具体过程：

1.  你发起一笔[跨链交易](https://www.mintscan.io/osmosis/txs/1858F63B1B1E909B010D8669A8FAADF3B224E4FCE47AA67ED20DAF1491FB2F49)，打算从 Osmosis 往 Cosmos Hub 跨 0.01 个 OSMO。因为目前 `Cosmos Hub/Channel-141 <=> Osmosis/Channel-0` 是最常用的通道，且代币跨链的约定“话题”是 `transfer`。所以你依次指定 `sourceChannel` 为 `channel-0`，`sourcePort` 为 `transfer`，以及 Cosmos Hub 上的收款人 `cosmos186440u3pwts7s3jljngak37xnmy5le8nztf9az`
    
2.  当节点收到并识别出你这笔交易是跨链交易而且也知道你是想**从 Osmosis 去往 Cosmos Hub**，此时它**不会被销毁**，而是会把你的 OSMO 转给保管账户。那这保管账户从哪里来的？是由外部实体控制的吗？放心，不是的。保管账户的计算逻辑是：
    
        pubkey = sha256(
          Buffer.from("ics20-1", "utf-8") 
          + Buffer.from([0]) 
          + Buffer.from(`${sourcePort}/${sourceChannel}`, "utf-8")
        ).slice(0, 20)
        
        Bech32.encode(addressPrefix, pubkey)
        // 此时 addressPrefix: "osmo", sourcePort: "transfer", sourceChannel: "channel-0"
        
    
    因此我们可以计算出保管账户便是 [osmo1a53udazy8ayufvy0s434pfwjcedzqv347h34au](https://www.mintscan.io/osmosis/account/osmo1a53udazy8ayufvy0s434pfwjcedzqv347h34au)，有兴趣可以点进这个地址看具体有多少币从 `Osmosis/Channel-0` 去往 Cosmos Hub 了
    
3.  接着 `Relayer` 会把这条跨链消息转发到 Cosmos Hub。Cosmos Hub 接收到这条消息并充分验证后，便会直接给 `cosmos186440u3pwts7s3jljngak37xnmy5le8nztf9az` 地址铸造 0.01 个 `ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC`。不是 OSMO 吗？这是什么鬼？其实这便是精妙之处。因为这个币是凭空铸造的，而它的"代号"(`denom`)是**不能跟已有的币种重合**，所以便可通过以下方式得出：
    
        "ibc/" + sha256(Buffer.from(`${dstPort}/${dstChannel}/${originDenom}`, 'utf-8')).toString("hex").toUpperCase()
        // 此时 dstPort: transfer, dstChannel: channel-141, originDenom: uosmo
        
    

​ 当然你在 Cosmos Hub 使用过程中不需要看到这种无法阅读的代号，钱包或者浏览器都智能的把它名字替换成 OSMO。

至此通过在 Osmosis 锁定资产，然后在 Cosmos Hub 铸造资产的方式帮你把资产跨过来了，此时你便能愉快的玩耍了。那你如果想回到 Osmosis 链怎么办？类似的：

1.  你又发起一笔[跨链交易](https://www.mintscan.io/cosmos/txs/39FE6C9C1F42A918FEB909C5BAC40FDDB7B5CD0D21EB527F2CCA1489F2753677)，分别指定 `sourceChannel` 为 `channel-141`，`sourcePort` 为 `transfer` 以及 Osmosis 上的收款人 `osmo186440u3pwts7s3jljngak37xnmy5le8n2s64ts`
    
2.  节点收到交易后检测发现你是想**从 Cosmos Hub 回到 Osmosis**，因此它此时会**直接销毁**这笔之前凭空铸造的币。
    
3.  然后 Relayer 把跨链消息转发到 Osmosis 后，Osmosis 经过充分验证便会把之前放在保管地址上的 OSMO 转给你的收款地址。
    

> 想了解更多细节的同学同样可以从[规范](https://github.com/cosmos/ibc/blob/master/spec/app/ics-020-fungible-token-transfer/README.md)和[源码](https://github.com/cosmos/ibc-go/blob/457095517b7832c42ecf13571fee1e550fec02d0/modules/apps/transfer/keeper/relay.go)找到答案

**但聪明如你一定会注意到一个细节，这个凭空铸造币的过程包含了 ChannelID。那不就相当于说原本同一个币通过不同通道过来就会变成不同的币，它们无法共享流动性吗？** 对的，这也是为什么看[浏览器](https://www.mintscan.io/cosmos/relayers)不同链之间通道这么多，但有流量的就只有一个的原因。但理论上它们是等价的，我想后面会有 DeFi 项目补足这个缺点。

**那如果有流量的通道只有一个，怎么防止 Relayer 作恶呢？** 答案是 `Relayer` 无法作恶，因为保管账户不属于 `Relayer` ，而 `Relayer` 只是负责传输消息。当然这个担心不无道理，目前 `Relayer` 没有经济激励，甚至还要倒贴（因为转发的消息也需要上链，需要消耗币），我想 Cosmos 官方也意识到这点并会在后面提出优化方案。

**那我能自己做 Relayer 吗？** 当然可以，你无需新建通道，只需知道已有通道分别在俩链的 ChannelID，任何人都可以搭建自己的 `Relayer`。但你需要保证你的账户分别在俩链都有余额，参考 [ts-relayer](https://github.com/confio/ts-relayer)

**我注意到 Terra Station 首页有 Native Token 和 CW20 Token，它们有什么区别？都能跨链吗？** 两者的区别就类似 ETH 跟 ERC20 的区别，Native Token 是 Cosmos 内建模块(`bank module`)支持的，而 [CW20 Token](https://docs.terra.money/Tutorials/Smart-contracts/Manage-CW20-tokens.html#checking-cw20-balance) 需要先部署智能合约，代币数据便是智能合约的状态。因此 Native Token 是能直接跨链的，而 CW20 Token 目前还不支持跨链。可能后面官方会提出将 CW20 Token 封装成 Native Token 的方案。

扩展阅读：

*   [IBC Explained to Cosmonauts](https://www.youtube.com/watch?v=dYuTYykRhH4&t=3162s)
    
*   [Interacting with other chains using IBC and relayers](https://www.youtube.com/watch?v=816PP8oXv0Q&t=5056s)

---

*Originally published on [Cosmos 爱好者](https://paragraph.com/@cosmosfans/ibc-cosmos)*
