如何查看自己的賬戶資產是否在默克爾樹中
什麼是默克爾樹
默克爾樹(Merkle Tree)又叫哈希樹(Hash Tree),是一種數據結構,通常是一棵二叉樹,它以特定的方式從葉節點逐層向上計算hash值,直到頂部根節點。
CoinEx默克爾樹定義
節點信息
每個樹節點存儲信息包括: 1. 節點hash值; 2. 用戶資產快照覆蓋的幣種數量(以BTC, ETH, USDT為例)
hash值{"BTC":"BTC數量","ETH":"ETH數量","USDT":"USDT數量"}
3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"}
3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"}
Hash規則
葉子節點
hash = SHA256(nonce + balances)
如:
hash = SHA256('79b0319c0003e6b5f149525a6677f1bcb7851e9bd7bf05c7089576d38dd95efa{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"}')
其中,CoinEx會給每個用戶分配一個唯一的nonce,這個nonce可以在審計數據中查詢到;balances是用戶資產快照覆蓋的幣種數量組成的json字符串,如:{"BTC":"1.023","ETH":"0","USDT":"20.2343322"},遵循如下規則:
1. json字符串為緊湊格式,無換行和空格。
2. 幣種數量去除末尾無效0,保留8位精度。
3. 幣種名按英文字母順序排序。
1. json字符串為緊湊格式,無換行和空格。
2. 幣種數量去除末尾無效0,保留8位精度。
3. 幣種名按英文字母順序排序。
父節點
hash = SHA256(h1 + h2 + balances)
· h1: 左邊子節點的哈希值
· h2: 右邊子節點的哈希值
· balances: 左邊子節點的balances + 右邊子節點的balances,把相同幣種的餘額加起來
· h2: 右邊子節點的哈希值
· balances: 左邊子節點的balances + 右邊子節點的balances,把相同幣種的餘額加起來
如:
左子節點:
3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"}
右子節點:
e9fcf13c9cdae1dfab4c2ea60d8acb62603b5f8430e265bf4b3f901fc4e45fe9{"BTC":"0.48","USDT":"100.24534"}
父節點的哈希:
hash = SHA256(3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"})
填充節點規則
構建一棵完整的Merkle Tree(滿二叉樹)需要2^n個葉子結點數據,但實際情況數據的數量未必滿足且還可能是奇數。在此種情況下,如果一個節點k沒有兄弟節點,則自動填充(padding)生成一個兄弟節點k',該兄弟節點hash(k')=hash(k),節點k'的幣種數量全置零。
如節點K:
3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"}
父節點的哈希:
hash = SHA256(3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d3d101072de66342c711e369e1e98f48c89c412e7246918ae6466a5c72e73003d{"BTC":"1.023","ETH":"0.56","USDT":"20.2343322"})
驗證規則
1. 驗證原理:根據默克爾樹定義,從用戶本身葉子結點開始往上計算父節點hash值,一直到根節點得出hash(root),對比根節點的hash值,如果二者相等則驗證通過,不等則驗證不通過。
2. 例如下面的json文本,根據用戶(self)數據計算葉子節點的哈希,然後與路徑(path)上的每個兄弟節點計算父節點哈希,最後得到的節點哈希應等於根節點(root)哈希,且餘額(balances)也相等。 (注意兄弟節點為空時表明沒有兄弟節點,按填充節點規則計算父節點哈希)
2. 例如下面的json文本,根據用戶(self)數據計算葉子節點的哈希,然後與路徑(path)上的每個兄弟節點計算父節點哈希,最後得到的節點哈希應等於根節點(root)哈希,且餘額(balances)也相等。 (注意兄弟節點為空時表明沒有兄弟節點,按填充節點規則計算父節點哈希)
默克爾樹路徑數據json文本:
{ "root": { "balances": { "CET": "14373493.24153457", "ETH": "104543541.61407674", "USDC": "2419089.97192761", "USDT": "4836955256.81519091" }, "hash": "c01a6c3b0fedde2a066f8a38968e40420c0b0742bb4ccda571a4349fb1c64f18" }, "self": { "balances": { "USDT": "3990000" }, "nonce": "9885b5df557ba3cec41a74347719a8a37d5792a1cf7f0e216510d60dd1b1fc95" }, "path": [ { "balances": { "CET": "10000.01994324", "USDC": "40000", "USDT": "1004.13066254" }, "hash": "01f94322a74bee4431b809406997cee575bed3b85ef36b4ba3b2ff9dd140f99a", "pos": "left" }, { "balances": { "CET": "1000", "ETH": "0.90765244", "USDT": "143151.30772787" }, "hash": "c99051749a3a83e60d1338454382044f9d7236928cfdc4b7fca1a7cc7450c7a6", "pos": "left" }, { "balances": { "CET": "548800.95984406", "ETH": "50000.00001068", "USDC": "9986.281143", "USDT": "62752.29303779" }, "hash": "173a9a7ef562f1b537def5d58167d7402c8e268b1423c5f8e1d806cd0c524344", "pos": "left" }, { "balances": { "CET": "10023.01105146", "ETH": "9900.74253772", "USDT": "22516389.78119662" }, "hash": "d79bd6c7a1536db199747061c119f98f86d99f9c7a8350fe63c6314ef3e8a24c", "pos": "right" }, { "balances": { "CET": "5393361.46905487", "ETH": "23711.51394236", "USDC": "201404.61667184", "USDT": "230211961.3159725" }, "hash": "115551fd3f85328d32858cc6d1bea9c1274984b0f8abba8140752f9d55e48277", "pos": "left" }, { "balances": { "CET": "1554146.8440552", "ETH": "100.0040003", "USDC": "160006.6", "USDT": "11201397.46983634" }, "hash": "7b92897456af56f473b75d5e009be090726ad64694fd27971dc46f2631db51d8", "pos": "right" }, { "balances": { "CET": "4712634.46013087", "ETH": "91469.27009748", "USDC": "1002463.00913027", "USDT": "830313049.62523756" }, "hash": "0905786187f2c582902b84175813b063c31755a2930b25dee7ba005f7c8a7cf9", "pos": "right" }, { "balances": { "CET": "2143526.47745487", "ETH": "104368359.17583576", "USDC": "1005229.4649825", "USDT": "3738515550.89151969" }, "hash": "41dc5da7477fab3ac6fe233a1bf1bec0d26d0f5dea679b5d91f2f09c488fcb2f", "pos": "right" } ] }
驗證步驟
1. 登入您的CoinEx賬戶,點擊“儲備金證明”,進入“儲備金證明”頁面,點擊“複製我的審計數據”。
2. 把複製的審計數據粘貼保存到文本文件,如merkle_proof_file.json。
3. 下載CoinEx提供的[開源驗證工具]。
4. 解壓驗證工具,將解壓後的文件和merkle_proof_file.json 放到同一個文件夾,如~/Downloads/proof-of-reserves
5. 打開終端(MacOS: 終端App;Windows: 終端或PowerShell),輸入cd ~/Downloads/proof-of-reserves 進入上面的目錄。
6. 輸入以下命令來驗證您的數據:MacOS / Linux:
./proof-of-reserves -f merkle_proof_file.json
Windows:
./proof-of-reserves.exe -f merkle_proof_file.json
7. 如果驗證通過,提示Merkle tree path validation passed,驗證失敗則提示Merkle tree path validation failed。
您也可以參考本篇文檔給出的說明以及[開源驗證工具源碼]自行編寫程序驗證。