Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
justlovediaodiao committed Dec 12, 2022
0 parents commit a051d41
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CoinEx Proof-of-Reserves

## Introduction

Download the [latest build](https://github.com/coinexcom/proof-of-reserves/releases/latest) for your operating system and architecture. Also, you can build from source code by yourself.

Building from source code requires Go (version >= 1.18).

Build:

```
go build
```

## Usage

Example:

```
./proof-of-reservers -f ./example/merkle_proof_file.json
```
60 changes: 60 additions & 0 deletions example/merkle_proof_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"root": {
"balances": {
"BTC": "106218647.69797369",
"CET": "14442925.91120209",
"ETH": "104543542.83007564",
"USDT": "4837050599.79548026"
},
"hash": "b272a9a8142f3942dc640936d267ce785ae9d29aaf904c1ec1f0990242047569"
},
"self": {
"balances": {
"USDT": "374.250573"
},
"nonce": "79b0319c0003e6b5f149525a6677f1bcb7851e9bd7bf05c7089576d38dd95efa"
},
"path": [
{},
{},
{},
{
"balances": {
"BTC": "920",
"USDT": "562050.3686362"
},
"hash": "e26395de3b539c88e6bcbcfe05a2be4cc02758eb97e5693ffb580d43bfc16139",
"pos": "left"
},
{
"balances": {
"BTC": "100003253.72911745",
"ETH": "100000007.28283543",
"USDT": "452570150.50789245"
},
"hash": "e9fcf13c9cdae1dfab4c2ea60d8acb62603b5f8430e265bf4b3f901fc4e45fe9",
"pos": "left"
},
{},
{
"balances": {
"BTC": "1551201.86132819",
"CET": "1747265.68106336",
"ETH": "4378250.41175252",
"USDT": "3286012972.62381777"
},
"hash": "629dfeba50db22597a7ed01de60a458968767c2c46693c268326ef09f302f28d",
"pos": "left"
},
{
"balances": {
"BTC": "4663272.10752805",
"CET": "12695660.23013873",
"ETH": "165285.13548769",
"USDT": "1097905052.04456084"
},
"hash": "43308c37e60588b4c042567f75b7fc36fd8e3ebde985246548c95ac3c0aac449",
"pos": "left"
}
]
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/coinexcom/proof-of-reserves

go 1.18

require github.com/shopspring/decimal v1.3.1
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
140 changes: 140 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package main

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"os"

"github.com/shopspring/decimal"
)

type Pos string

var (
Left Pos = "left"
Right Pos = "right"
)

type Balance map[string]decimal.Decimal

func (b Balance) Format() string {
v, _ := json.Marshal(b) // ASCII code asc, no indent
return string(v)
}

func (b Balance) Add(other Balance) Balance {
r := make(Balance)
for k, v := range b {
r[k] = v
}
for k, v := range other {
vv, ok := r[k]
if ok {
r[k] = v.Add(vv)
} else {
r[k] = v
}
}
return r
}

func (b Balance) Equal(other Balance) bool {
if len(b) != len(other) {
return false
}
for k, v := range b {
vv, ok := other[k]
if !ok {
return false
}
if !v.Equal(vv) {
return false
}
}
return true
}

func hash(v string) string {
h := sha256.New()
h.Write([]byte(v))
b := h.Sum(nil)
return hex.EncodeToString(b)
}

type MarkelProof struct {
Root struct {
Balances Balance
Hash string
}
Self struct {
Balances Balance
Nonce string
}
Path []struct {
Balances Balance
Hash string
Pos Pos
}
}

func (m *MarkelProof) Validate() bool {
h := hash(m.Self.Nonce + m.Self.Balances.Format())
b := m.Self.Balances
for _, path := range m.Path {
if path.Hash == "" { // no right node
h = hash(h + h + b.Format())
} else {
b = b.Add(path.Balances)
if path.Pos == Left {
h = hash(path.Hash + h + b.Format())
} else {
h = hash(h + path.Hash + b.Format())
}
}
}

fmt.Printf("proofed hash: %s\n", h)
fmt.Printf("root hash: %s\n", m.Root.Hash)
if h != m.Root.Hash {
return false
}
fmt.Printf("proofed balances: %s\n", b.Format())
fmt.Printf("root balances: %s\n", m.Root.Balances.Format())
if !b.Equal(m.Root.Balances) {
return false
}
return true
}

func main() {
var f string
flag.StringVar(&f, "f", "", "merkle proof file")
flag.Parse()
if f == "" {
flag.Usage()
return
}

b, err := os.ReadFile(f)
if err != nil {
fmt.Println("invalid merkle proof file", err)
return
}
var m MarkelProof
if err := json.Unmarshal(b, &m); err != nil {
fmt.Println("invalid merkle proof file", err)
return
}
if m.Root.Hash == "" || len(m.Path) == 0 {
fmt.Println("empty merkle proof file")
return
}
if m.Validate() {
fmt.Println("Merkle tree path validation passed")
} else {
fmt.Println("Merkle tree path validation failed.")
}
}

0 comments on commit a051d41

Please sign in to comment.