Skip to content

Commit

Permalink
MerKel Tree validate
Browse files Browse the repository at this point in the history
  • Loading branch information
BitgetLimited committed Dec 3, 2022
1 parent 6863e2d commit c8a6186
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 115 deletions.
130 changes: 66 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,92 @@
# Bitget Limited 储备证明
## 背景
Bitget推出储备证明(PoR)以提高用户资产的安全性和透明度。这些工具将允许您独立审计 Bitget 的准备金证明,并验证 Bitget 的准备金是否超过交易所对用户的已知负债,以确认 Bitget 的偿付能力。
# Proof of Reserves Licensed to Bitget Limited
## Background

## 介绍
### 源码构建
下载适用于您的操作系统和体系结构的最新版本。此外,您可以自己构建源代码。
Bitget launches Proof of Reserve (PoR) to improve the security and transparency of user assets. These tools will allow you to independently audit Bitget’s Proof of Reserves as well as verify that Bitget’s reserves have exceed the exchange’s known liabilities to all users to confirm Bitget’s solvency.

[下载](https://www.oracle.com/java/technologies/downloads/)安装JDK(Java Development Kit)
[下载](https://maven.apache.org/download.cgi?.)安装Maven编译工具
## Introduction
### Build from source
Download the latest version for your operating system and architecture. Also, you can build the source code yourself.

构建此开源代码需要 Java(版本 >= 11), Maven(版本 >= 3.8.4)
[Download] (https://www.oracle.com/java/technologies/downloads/)Install JDK(Java Development Kit)

This comment has been minimized.

Copy link
@Mayrisass

Mayrisass May 19, 2024

H

[Download] (https://maven.apache.org/download.cgi.)Install Maven build tool

### 打包编译源代码
#### 进入项目目录
The minimum prerequisite to build this project requires Java version >= 11, Maven version >= 3.8.4

### Package and compile source code
#### Enter the path for the project
`cd ~/Downloads/proof-of-reserves`

#### 安装依赖
#### Install dependencies
`mvn clean install`

#### 启动
#### Start up
`java -jar proof-of-reserves.jar`

# 技术细节
## 什么是默克尔树?
默克尔树(Merkle Tree )是一种数据结构,又叫哈希树(Hash Tree)。默克尔树将数据存储在树状结构的叶子节点中,并通过对数据的逐级哈希(Hash)直到顶部根节点,叶子节点数据的任何变动,都会传递到上一级节点并最终反应到树根的变化。

### 1. 默克尔树的作用
- 零知识证明
- 确保数据的不可篡改性
- 确保数据的隐私性
### 2. Bitget Limited 默克尔树定义
#### 2.1 节点信息
每个树节点存储信息包括:
1. hash值; 2. 用户资产快照包含的币种数量(以BTC, ETH, USDT为例)
# Technical Description
## What is the Merkle Tree?
Merkle Tree is a data structure, also known as a Hash Tree. Merkle tree stores data in the leaf nodes of the tree structure, and by hashing the data step by step up to the top root node, any changes in the data of the leaf nodes will be passed to the higher level nodes and eventually displayed as changes in the root of the tree.

### 1. The roles of Merkle tree
- Zero-knowledge proof
- Ensure data immutability
- Ensures data privacy
### 2. Bitget Limited Merkle Tree Definition
#### 2.1 Node Information
Information stored in every tree node includes:
1. hash value;
2. the number of coins contained in the user's asset snapshot (BTC, ETH, USDT for example);
```
hash值,{"BTC":"BTC数量","ETH":"ETH数量","USDT":"USDT数量"}
hash value,{"BTC":"BTC amount","ETH":"ETH amount","USDT":"USDT amount"}
2070b6a5b12f4ea7,{"BTC":1.763,"ETH":362,"USDT":1077200.2274}
```
#### 2.2 Hash规则
##### 叶子结点(填充节点除外)
`hash=sha256Function(encryptUid,nonce,balances).substring(0,16)`
- encryptUid: 用户的加密uid
- nonce: 每个用户分配一个唯一值
- balances: 用户资产快照币种数量组成的json字符串,(注意:去除末尾无效0,保留8位精度)
-
#### 2.2 Hash Rules
##### Leaf nodes (except padding nodes)
`hash=sha256Function(encryptUid,nonce,balances).substring(0,16)`
- encryptUid: encrypted UID of the user
- nonce: a unique value assigned to each user
- balances: json string composed of the number of coins in the user's asset snapshot, (note: remove the invalid 0 at the end and keep precision of 8 bits)
- For example
```json
{"BTC":1.763,"ETH":362,"USDT":1077200.2274}
```
##### 父节点
##### Parent node
```
父节点的hash = sha256Function(hash1+hash2,{"BTC":(hash1(BTC数量)+hash2(BTC数量)),"ETH":(hash1(ETH数量)+hash2(ETH数量)),"USDT":(hash1(USDT数量)+hash2(USDT数量))},父节点level).substring(0,16)
Parent node's hash = sha256Function(hash1+hash2,{"BTC":(hash1(BTC amount)+hash2(BTC amount)),"ETH":(hash1(ETH amount)+hash2(ETH amount)),"USDT":(hash1(USDT amount)+hash2(USDT amount))},parent node level).substring(0,16)
```
- h1: 当前节点的左子节点的hash,
- h2: 当前节点的右子节点的hash,
- level: 父节点的层级
- h1: hash of the left child node of the current node,
- h2: hash of the right child node of the current node,
- level: where the parent node lies in

**树节点的层级定义**:构建一棵完整的Merkle Tree(满二叉树)需要2^n个叶子结点数据,叶子结点层级=n+1,父节点层级=子节点层级-1,根节点层级=1,叶子结点层级最大
**Definition of tree node level**:A complete Merkle Tree (full binary tree) requires 2^n leaf node data, leaf node level = n + 1, parent node level = child node level - 1, root node level = 1, leaf node level is the maximum

##### 填充节点规则
构建一棵完整的Merkle Tree(满二叉树)需要2^n个叶子结点数据,但实际情况数据的数量未必满足且还可能是奇数。在此种情况下,如果一个节点k没有兄弟节点,则自动填充(auto padding)生成一个兄弟节点k',该节点`hash(k')=hash(k)`,节点k'的币种数量全置零。
##### Padding node rules
A complete Merkle Tree (full binary tree) requires 2^n leaf node data, but the actual number of data may not satisfy and may be odd. In such a case, if a node k has no sibling node, then auto padding generates a sibling node k', and`hash(k')=hash(k)`, and the number of coins of node k' is set to zero.


###### 例子
###### For example
| Hash | balances |
|--------| -------------|
| hash1 | {"BTC":1,"ETH": 6,"USDT":10}|
| hash2 | {"BTC":2,"ETH":4,"USDT":8}|
| hash3 | {"BTC":5,"ETH":9,"USDT":74}|

则填充节点hash4=hash3,存储的blances为`{"BTC": 0, "ETH": 0,"USDT": 0}`,如图一高亮节点所示:
图一
<img src="images/流程图.jpg" alt="" style="text-align:right;width:500px;"/>
Then the padding node hash4 = hash3, stored balances are `{"BTC": 0, "ETH": 0,"USDT": 0}`,as shown in the highlighted node in Figure one:
Figure one
<img src="images/flowChart.jpg" alt="" style="text-align:right;width:500px;"/>

```
父节点的hash = sha256Function(hash1+hash2,{"BTC":(hash1(BTC数量)+hash2(BTC数量)),"ETH":(hash1(ETH数量)+hash2(ETH数量)),"USDT":(hash1(USDT数量)+hash2(USDT数量))},父节点level).substring(0,16)
Parent node's hash = sha256Function(hash1+hash2,{"BTC":(hash1(BTC amount)+hash2(BTC amount)),"ETH":(hash1(ETH amount)+hash2(ETH amount)),"USDT":(hash1(USDT amount)+hash2(USDT amount))},parent node level).substring(0,16)
```
Thus
`hash6 = SHA256(hash3 + hash3, {BTC: (2+0), ETH:(1+0), USDT:(12+0)}, level)`
### 验证原理
#### 1、验证原理:
根据Bitget Limited 默克尔树定义,从用户本身叶子结点开始往上计算父节点hash值,一直到根节点得出hash(root),对比“验证步骤-步骤1”中的默克尔树根节点的hash值,如果二者相等则验证通过,不等则验证不通过
### Verification Principle
#### 1、Verification principle:
According to the definition of Bitget Limited Merkle tree, the hash value of the parent node is calculated from the user's own leaf node up to the root node, and the hash value of the root node is compared with the hash value of the Merkle tree in "Verification Step - Step 1", if the two are equal, the verification passes, if not, the verification fails.
#### 2、例子
结合图一和下面的json文本,依据用户本身叶子节点h3和提供的相邻节点h4信息可以计算出父节点h6的hash,再和提供的相邻节点h5信息可以计算出父节点h7的hash,然后和默克尔树路径数据中提供的根节点h7信息对比hash值是否相等即可完成验证。
默克尔树路径数据json文本:
#### 2、Example
Combining figure one and the following json text, and based on the user's own leaf node h3 and the information provided by the adjacent node h4, we can calculate out the hash of the parent node h6, and then with the information provided by the adjacent node h5, we can calculate out the hash of the parent node h7, and then compare the hash value with the root node h7 provided in the Merkle tree path data to see if the hash values are equal to complete the validation.
Merkle tree path data json text:
```json
{
"path": [
Expand Down Expand Up @@ -140,19 +142,19 @@ Bitget推出储备证明(PoR)以提高用户资产的安全性和透明度
}
```

#### 验证步骤
1. 将您在Bitget平台下载的适用于您的操作系统和体系结构的可执行验证程序
#### Verification Steps
1. Take the executable verifier that you need to download on the Bitget platform for your operating system and architecture.
- proof-of-reserves-linux-amd64-v1.0.2.zip
- proof-of-reserves-linux-arm64-v1.0.2.zip
- proof-of-reserves-macos-v1.0.2.zip
- proof-of-reserves-windows-v1.0.2.zip
2. 解压文件到指定目录,例如
`~/Downloads/proof-of-reserves-*`
3. 将Bitget平台下载的 merkel_tree_bg.json 文件替换 `~/Downloads/proof-of-reserves-*` 目录下的同名文件
4. 运行start文件 `sh start.sh` 或者 点击运行 `start.bat`
5. 查看结果
1)如果您的数据正确,验证通过则执行结果为 “Consistent with the Merkle tree root hash. The verification succeeds”。
2. Unzip the file to a specified directory, for example:
`~/Downloads/proof-of-reserves-*`
3. Download the file merkel_tree_bg.json and substitute the file with the same name under your directory`~/Downloads/proof-of-reserves-*`
4. Run start file `sh start.sh` or Click the `start.bat` file
5. View results
1)If your data are correct and the verification passed, then the result is "Consistent with the Merkle tree root hash. The verification succeeds".
<img src="images/success.png" alt="" style="text-align:right;width:500px;"/>
2)如果您的数据错误,验证失败则执行结果为 “Inconsistent with the Merkle tree root hash. The verification fails”。
<img src="images/faild.png" alt="" style="text-align:right;width:500px;"/>
6. 您也可以参考 Bitget Limited 开源验证工具代码和默克尔树定义(参考“什么是默克尔树”章节),自行写程序验证步骤2获取到的路径数据,或者查看确认自己的资产被包含在此次审计生成的默克尔树中。
2)If your data are wrong and the verification fails, the result is "Inconsistent with the Merkle tree root hash. The verification fails".
<img src="images/faild.png" alt="" style="text-align:right;width:500px;"/>
6. You can also refer to the Bitget Limited open source verification tool code and Merkle tree definition (refer to the "What is the Merkle Tree" section) and write your own program to verify the path data obtained in step 2, or check to make sure your assets are included in the Merkel tree generated by this audit.
File renamed without changes
File renamed without changes
8 changes: 4 additions & 4 deletions src/main/java/com/upex/BgMerkleValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
import java.nio.file.Path;

/**
* 验证账户资产是否包含在BitGet发布的Merkle树中
* Verify whether the account assets are included in the Merkle tree published by Bitget
*
* @author BitgetLimited
*/
public class BgMerkleValidator {
/**
* 定义文件路径:merkel_tree_bg.json
* merkel_tree_bg.json
**/
private static final String MERKLE_TREE_BG_FILE_PATH = "merkel_tree_bg.json";

Expand All @@ -42,7 +42,7 @@ public static void main(String[] args) {
}

/**
* 参数校验
* validate
* @param merkleProof
* @return
* @author BitgetLimited
Expand Down Expand Up @@ -74,7 +74,7 @@ private static boolean validate(MerkleProof merkleProof){


/**
* 获取merkel_tree_bg.json文件内容
* get merkel_tree_bg.json content
*
* @author BitgetLimited
* @date 2022/11/25 16:53
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/upex/constants/MerkelTreeConstants.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.upex.constants;

/**
* 默克尔树常量
* MerkelTreeConstants
* @author BitgetLimited
* @date 2022/11/25 23:03
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.upex.constants;

/**
/** TreeNodeRoleConstants
* @author BitgetLimited
* @date 2020-11-18 16:14
* @desc
Expand Down
27 changes: 13 additions & 14 deletions src/main/java/com/upex/model/MerKelTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
public class MerKelTree {

/**
* 构建merkelTree树根节点
* @param path 待验证路径
* @param self 自己节点
* build merkelTree root node
* @param path
* @param self
* @return {@link TreeNode }
* @author BitgetLimited
* @date 2022/11/27 11:56
Expand All @@ -39,9 +39,9 @@ public TreeNode buildMerkelTreeRoot(List<TreeNode> path, TreeNode self) {
}

/**
* 创建父节点
* @param friend 朋友节点
* @param self 自己节点
* createParentTreeNode
* @param friend
* @param self
* @return {@link TreeNode }
* @author BitgetLimited
* @date 2022/11/27 11:57
Expand All @@ -60,9 +60,9 @@ TreeNode createParentTreeNode(TreeNode friend, TreeNode self) {
}

/**
* 构建内部节点
* @param left 左节点
* @param right 右节点
* constructInternalNode
* @param left
* @param right
* @return
*/
private TreeNode constructInternalNode(TreeNode left, TreeNode right) {
Expand All @@ -81,8 +81,8 @@ private TreeNode constructInternalNode(TreeNode left, TreeNode right) {
}

/**
* 清除节点资产
* @param right 右节点
* clearAssetsMap
* @param right
* @return {@link java.util.Map<java.lang.String,java.math.BigDecimal> }
* @author BitgetLimited
* @date 2022/11/27 11:59
Expand All @@ -95,9 +95,8 @@ private static Map<String, BigDecimal> clearAssetsMap(TreeNode right) {
}

/**
* 创建一个空节点
* 将左节点复制,资产清空
* @param source 源节点
* createEmptyTreeNode
* @param source
* @return {@link TreeNode }
* @author BitgetLimited
* @date 2022/11/25 23:40
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/upex/model/MerkleProof.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;
/**
* 默克尔树证明实体类
* MerkleProof
* @author BitgetLimited
* @date 2022/11/25 23:40
*/
Expand All @@ -27,8 +27,8 @@ public void setSelf(TreeNode self) {
}

/**
* 默克尔树的验证
* 通过用户提供的path和self正推出一个新的root,与path中的root进行比较
* validate
* A new root is being introduced through the path and self provided by the user. Compare with the root in the path
* @return {@link boolean }
* @author BitgetLimited
* @date 2022/11/27 11:54
Expand Down
27 changes: 5 additions & 22 deletions src/main/java/com/upex/model/TreeNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,27 @@
import java.util.HashMap;
import java.util.Map;
/**
* 默克尔树节点
* TreeNode
* @author BitgetLimited
* @date 2022/11/25 23:39
*/
public class TreeNode {
/**
* 审计id
*/

private String auditId;

/**
* 资产集合
*/
private Map<String, BigDecimal> balances = new HashMap<>();

/**
* 随机值
*/
private String nonce;

/**
* 默克尔树节点值
*/
private String merkelLeaf;

/**
* 层级
*/
private Integer level;

/**
* 角色 0-空节点, 1-左节点, 2-右节点, 3-根节点
* role 0-empty, 1-left, 2-right, 3-root
*/
private Integer role;

/**
* 加密用户id
*/
private String encryptUid;

public String getAuditId() {
Expand Down Expand Up @@ -148,7 +131,7 @@ public boolean validateBalances() {
}

/**
* 合并资产
* mergeAsset
* @param childNode
*/
public void mergeAsset(TreeNode childNode){
Expand All @@ -167,7 +150,7 @@ public void mergeAsset(TreeNode childNode){
}

/**
* 验证资产集合
* validateEqualsBalances
* @return {@link boolean }
* @author BitgetLimited
* @date 2022/11/25 22:30
Expand Down
Loading

7 comments on commit c8a6186

@Oliv23ava
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0xBEC67264651cEA03A5bBfAaaBFe13C46668A7B36

@Benz19933
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0xBEC67264651cEA03A5bBfAaaBFe13C46668A7B36

@Benz19933
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

@Benz19933
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0xBEC67264651cEA03A5bBfAaaBFe13C46668A7B36

@Benz19933
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0xBEC67264651cEA03A5bBfAaaBFe13C46668A7B36

@Benz19933
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5

@Oliv23ava
Copy link

@Oliv23ava Oliv23ava commented on c8a6186 Jul 20, 2024 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.