Game of Zones 經驗分享 — muzamint

mingderwang
11 min readJun 6, 2020

參加 Cosmos GoZ 駭客松比賽的心得報告

我想這次很難得有機會參加一個維持了將近一個月的跨區塊鏈比賽, 雖然我表現不是很好, 但經驗值得跟大家分享。(我的隊名是 muzamint, 只得到一個參加獎 the Game of Zones Liveness reward, 在第二階段, zone 活得夠久就有的獎)

先講總結:

  • 原本主辦單位怕沒人會成功的第三階段(比賽內容是: 可以駭別人的 zones, 可以欺騙別人, 例如達到雙花的效果), 一開始, 都沒人做出來。卻在最後一天, 出現了大逆轉: regen network 隊發現了一個方法 (here), 利用相同的 src channel-id 與 dst channel-id,用 relayer 做出一個 path 可以造出假 tokens。還有一組 p2p , 利用複製一個 zone 的方法 (here), 來模擬雙簽達到雙花的效果。但鹿死誰手, 還是要等最後公佈才能知道。
  • 第一階段, 有點是混亂。主辦單位 hub 一再出問題, 造成三次的重新開始比賽的窘境。將近 150 個團隊, 一直跟著重複更新代碼版本, 加入 hub 重新比賽。但大家還是很有耐心, 我想這就是駭客松的精神, 志在參加, 互相幫助, 學到東西最重要。我每次都是利用參加駭客松比賽, 來快速學會怎麼使用該新技術, 找出好玩的方法, 這次也藉此機會把 Cosmos 網路的 Tendermint, Cosmos-sdk, relayer, IBC (inter-blockchain communication), 與 ABCI (Application Blockchain Interface) 都搞懂了, 也玩過一次了。
  • 更難得的是, 大家這一個月以來, 共有 348 個人都是透過 ibc-testnet-alpha (Telegram) 在交流。雖然我也是似懂非懂的邊學邊問, 有時候搞懂的東西, 試出來的結果, 也會拿來回應其他人的問題, 雖然大家正在比賽, 但都還是會彼此分享, 互相幫忙, 這就是我喜歡駭客松的地方。最後, 大家都還是會把自己的工具代碼, 視覺化網頁, 例如 irisplorer , mapofzones 等, 經驗都用medium 報告或用 twitter 分享出來, 也有人馬上改出一個給 Goz 專用的 wallet 給這次比賽用, 更有人做出線上服務, 歡迎大家使用, 順便推銷自己。大家在 Cosmos community 就變成好友, 也會有工商時間, 也拉起了合作夥伴, 共同造勢, 並進行下一個跨鏈專案的開發, 例如一些 DeFi 應用
  • 個人覺得, 主辦單位很努力的設計這場比賽。前兩階段, 先讓大家認識如何使用 cosmos 的 gaiad 還 gaiacli 來蓋 zone, 用最簡單的 keep alive 比賽, 讓大家學習如何用 relayer (實現 IBC) 建立的 channels 連線, 並用 update-client 保持連線狀態。第二階段, 才讓大家更了解什麼是 packets, 如何傳輸最多的 packets, 最後一個階段, 大家才有足夠的 know-how 來想攻擊與防衛。大家也因此能學到東西, 我想除了幫 Cosmos 研發團隊除錯以外, 也測試了這網路的成熟度 (目前還在 alpha test 中)。

稍微說明在這個比賽中, 我做哪些事:

我花了約 28.3 歐元, 在 scaleway 租了 3 台主機, 一個 load balancer, 蓋了一個我的 zone (也就是一個獨立的 blockchain), http://muzamint.com:26657。 在 namecheap 花了約 9 美元買了 muzamint.com 這個域名, 其他除了幾天熬夜(to keep my zone alive)與觀看主辦單位直播以外, 就是不斷的研讀相關技術文件以及了解他們的一些協定與代碼, 來幫助我達到這三個階段的各種挑戰。之前我只了解 Ethereum 區塊鏈的架構, 以及 Solidity DApp 智能合約開發, 與這次 Cosmos 網路與跨區塊鏈的技術截然不同!所以幾乎都要重新學。

第一階段:要求每個隊伍, 盡量跟 gameofzoneshub-1b 保持連線, 但規定 trusting-period 只能 90m 且盡量用最少的 packets 來達成。

我的策略是, 用 rly 指令, 建立一個成功的 path 後, 用 shell script 每 5000 秒執行一次

rly transact raw update-client muzamint-2 gameofzoneshub-2a <client-id>

但很不幸的是, 這個 update-client sub-command 很容易因為 packets 塞車而失敗, 通常會看到 height = “0” 的錯誤訊息, 所以還要寫一個 script 來檢查, 如果 update-client 失敗, 要在重複執行, 直到成功為止。但如果超過 90m 分鐘的 trusting-period 還沒成功 update-client 表示, 這個 channel 會斷掉, 你的 zone 與 hub 就失去連線了。

第二階段:要求每個隊伍, 跟 gameofzoneshub-2a 保持連線, trusting-period 沒有限制, 自己的 zone 可以跟 hub 傳 packets, 也可以 zone 與 zone 之間傳 packets (但比重只有 0.1), 看在比賽期間, 誰可以傳最多 packets。

我的策略是, (當時我還不知道怎麼做 zone 跟 zone 之間的 tokens 傳輸), 所以只對 hub 做送 1 muza tokens, 再把 1 muza 從 hub 傳回。執行下面指令, 自動產生一個新的 path

rly paths generate muzamint-2 transfer gameofzoneshub-2a transfer <path-id> -f -d

再用無限迴圈執行, 但因為大家都要搶最多的 packets 傳 tokens, hub 很快就負荷不了, GG 了. 所以第一名的, 應該是累積最多 zone 與 zone 之間的 packets 數, 而非只有 zone 與 hub 之間的傳輸。

我的代碼如下, rly q unrelayed 的指令是查詢是否有因為沒傳成功的 packets 還卡在 queue 裡 (因為目前 relayer 只支援 order: ORDERED), 可以用 rly tx rly, 來 push 出去, 如果成功, 它會把未完成的 token 傳輸的動作做完, 但我只成功過一次, 其他幾乎都無法修復, 只能重新再開一個 path 來用。 (所以又要不時的起床, 來看是否需要手動修復)

#!/bin/bash
while true; do
./loop.sh
./loopback.sh
rly q unrelayed <path-id>
rly tx rly <path-id> -d
done

loop.sh

rly tx transfer muzamint-2 gameofzoneshub-2a 1muza true cosmos1runeqr6aagcgv9ysw420mvw0sfymsz58szxew9  -p <path-id> -d

loopback.sh

rly tx transfer gameofzoneshub-2a muzamint-2 1muza false cosmos10y9827y2s42kc7e5n8je3zqpdw37hjdzyh0xxj -p <path-id> -d

主辦單位用 data dog 來統計大家的傳輸量(如下圖), 雖然我的 zone, muzamint 還在 data dog 的名單上, 但傳輸量遠遠落後別人。

雖然我也嘗試著自己加一個 validator 參加 hub, 而把 path 的對象從大家共用的 hub rpc-address (http://35.190.35.11:80) 指向自己的 validator node。不幸的是, 每 100 個 blocks, hub 就會 hang 15 分鐘 (聽說是 pruning 的 bugs), 後來主辦單位懶得修了, 這問題到第三階段還存在。我的 node 也無法 sync 到同一個 block, height 一直跟 hub 不一致, 所以也做不要 tokens 傳輸了。

第三階段:就自由發揮了, 找出攻擊, 欺騙, 或雙花的問題和方法。

當然我還是有我的策略, 也嘗試的很多方法, 想 IBC 是否有漏洞, 但都沒成功找到問題。第一個錯誤是, 本以為有人會攻擊我的 zone, 不用標準的 Sentry Node 方法, 改用 scaleway 上的 load balancer。結果沒有發生任何事情, 可能是偷我的代幣沒多大意義吧!

所以改用跟 hub 連線做實驗, 但 hub 還是跟階段二一樣, 官方的 rpc-address 始終連不上, 我的 timezone 跟官方不同, 沒人要修 hub, 只好自己再蓋一個 zone 來互相欺騙。

這個策略不錯, 至少自己的 zones 比較穩定, 可以多做幾次實驗。這次做了兩個 zones, muzamint-3 跟 muzamint-4 (原本也想連上 irishub, 但後來因沒 iris 的 tokens 只好作罷), 也建立了雙向兩個 path (通道), demo, demo2

➜  rly ch l
0: gameofzoneshub-3 -> key(✔) bal(✔) lite(✔) path(✘)
1: irishub -> key(✘) bal(✘) lite(✘) path(✘)
2: muzamint-3 -> key(✔) bal(✔) lite(✔) path(✔)
3: muzamint-4 -> key(✔) bal(✔) lite(✔) path(✔)
➜ rly pth l
0: demo -> chns(✔) clnts(✔) conn(✔) chan(✔) (muzamint-3:transfer<>muzamint-4:transfer)
1: demo2 -> chns(✔) clnts(✔) conn(✔) chan(✔) (muzamint-3:transfer<>muzamint-4:transfer)

最妙的是, 我假設兩個 zones 都用同一種幣名 “default-denom”: “muza”, 看看會不會可以混淆視聽, 騙對方 tokens?結論是 No.

relayer 的 IBC 機制, 成功的知道哪個 muza tokens 是哪一個 channel 送過來的, 所以雙方的 muza tokens 並沒被混淆。(所以第三階段, 我也輸了)

在經過幾次交易, muzamint-3 傳 muza tokens 給 muzamint-4 或在把原 muza tokens 傳回 muzamint-3, 都會正確的被分開

如下, 12transfer/qjxjzuwnpd/muza 是來自 muzamint-4 的 muza tokens, 不會被加入 muzamint-3 自己 mint 的 muza tokens(最後現存 80001013muza)

➜  rly q bal muzamint-3
80001013muza,12transfer/qjxjzuwnpd/muza,100000000transfer/qjxjzuwnpd/stake
➜ rly q bal muzamint-4
97990988muza,3600transfer/dkrcvlekli/muza,600transfer/eesaukpmbb/muza,100transfer/jhuozsvbnh/muza,17transfer/qaczetvpmm/muza,16transfer/qgpabuqmlh/muza,100transfer/rmsmcxgwcx/muza,100transfer/tguzrevlpk/muza,19884447transfer/ujdlgfltxw/muza,100000000transfer/ujdlgfltxw/stake,1000000transfer/ujdlgfltxw/transfer/hvmksxkfhp/muza,1000000transfer/ujdlgfltxw/transfer/uldphwjhob/doubloons

最後, 我還是要感謝主辦單位給我們這個機會, 有的玩又有獎金可拿。還有感謝 Zaki Manian 在 Telegram 上耐心且無私的回答我們問題, 才有今天的重大技術收穫可以來跟大家分享。

幕後花絮

GoZ 主辦團隊, 常常在我們(台灣)的三更半夜開直播, 說明進度與回答問題, 辛苦你們了…

--

--