Skip to content

Commit 2b8d506

Browse files
committed
feat(): add merkle
1 parent 4535e3b commit 2b8d506

File tree

3 files changed

+159
-23
lines changed

3 files changed

+159
-23
lines changed

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ module github.com/everFinance/goar
33
go 1.14
44

55
require github.com/stretchr/testify v1.6.1
6-
require github.com/everFinance/gojwk v1.0.0
6+
7+
require (
8+
github.com/everFinance/gojwk v1.0.0
9+
github.com/shopspring/decimal v1.2.0 // indirect
10+
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/everFinance/gojwk v1.0.0 h1:le/oI2NgXlrqg3MHU6ka+V30EWcD7TD6+Ilh+go79
44
github.com/everFinance/gojwk v1.0.0/go.mod h1:icXSXsIdpAczlpAtSljQlmABkMTRZENr73KHmo0GOGc=
55
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
66
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
8+
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
79
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
810
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
911
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

utils/merkle.go

+152-22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package utils
22

33
import (
44
"crypto/sha256"
5+
"github.com/shopspring/decimal"
6+
"math"
57
"math/big"
68
)
79

@@ -12,13 +14,15 @@ const (
1214
// number of bits in a big.Word
1315
wordBits = 32 << (uint64(^big.Word(0)) >> 63)
1416
// number of bytes in a big.Word
15-
wordBytes = wordBits / 8
17+
wordBytes = wordBits / 8
18+
BranchNodeType = "branch"
19+
LeafNodeType = "leaf"
1620
)
1721

1822
type Chunks struct {
1923
DataRoot []byte
2024
Chunks []Chunk
21-
Proofs []Proof
25+
Proofs []*Proof
2226
}
2327

2428
type Chunk struct {
@@ -27,68 +31,179 @@ type Chunk struct {
2731
MaxByteRange int
2832
}
2933

30-
type LeafNode struct {
34+
// Node include leaf node and branch node
35+
type Node struct {
3136
ID []byte
32-
DataHash []byte
33-
Type string
34-
MinByteRange int
37+
Type string // "branch" or "leaf"
38+
DataHash []byte // only leaf node
39+
MinByteRange int // only leaf node
3540
MaxByteRange int
41+
ByteRange int // only branch node
42+
LeftChild *Node // only branch node
43+
RightChild *Node // only branch node
3644
}
3745

3846
type Proof struct {
3947
Offest int
4048
Proof []byte
4149
}
4250

43-
func GenerateChunks(data []byte) (c Chunks) {
51+
func GenerateChunks(data []byte) Chunks {
4452
chunks := chunkData(data)
4553
leaves := generateLeaves(chunks)
46-
// TODO, calculate root & proofs
54+
root := buildLayer(leaves, 0) // leaf node level == 0
55+
proofs := generateProofs(root)
56+
57+
// Discard the last chunk & proof if it's zero length.
58+
lastChunk := chunks[len(chunks)-1]
59+
if lastChunk.MaxByteRange-lastChunk.MinByteRange == 0 {
60+
chunks = chunks[:len(chunks)-1]
61+
proofs = proofs[:len(proofs)-1]
62+
}
4763

48-
c.DataRoot = leaves[0].ID
49-
return
64+
return Chunks{
65+
DataRoot: root.ID,
66+
Chunks: chunks,
67+
Proofs: proofs,
68+
}
5069
}
5170

5271
func chunkData(data []byte) (chunks []Chunk) {
5372
cursor := 0
54-
// TODO
55-
// for len(data) >= MAX_CHUNK_SIZE {
56-
// }
73+
var rest = data
74+
// if data length > max size
75+
for len(rest) >= MAX_CHUNK_SIZE {
76+
chunkSize := MAX_CHUNK_SIZE
77+
78+
// 查看下一轮的chunkSize 是否小于最小的size,如果是则在这轮中调整chunk size 的大小
79+
nextChunkSize := len(rest) - MAX_CHUNK_SIZE
80+
if nextChunkSize > 0 && nextChunkSize < MIN_CHUNK_SIZE {
81+
dec := decimal.NewFromFloat(math.Ceil(float64(len(rest) / 2)))
82+
chunkSize = int(dec.IntPart())
83+
}
84+
85+
chunk := rest[:chunkSize]
86+
dataHash := sha256.Sum256(chunk)
87+
cursor += len(chunk)
88+
chunks = append(chunks, Chunk{
89+
DataHash: dataHash[:],
90+
MinByteRange: cursor - len(chunk),
91+
MaxByteRange: cursor,
92+
})
93+
94+
rest = rest[chunkSize:]
95+
}
5796

58-
hash := sha256.Sum256(data)
97+
hash := sha256.Sum256(rest)
5998
chunks = append(chunks, Chunk{
6099
DataHash: hash[:],
61100
MinByteRange: cursor,
62-
MaxByteRange: cursor + len(data),
101+
MaxByteRange: cursor + len(rest),
63102
})
64103
return
65104
}
66105

67-
func generateLeaves(chunks []Chunk) (leafs []LeafNode) {
106+
func generateLeaves(chunks []Chunk) (leafs []*Node) {
68107
for _, chunk := range chunks {
69108
hDataHash := sha256.Sum256(chunk.DataHash)
70109
hMaxByteRange := sha256.Sum256(PaddedBigBytes(big.NewInt(int64(chunk.MaxByteRange)), 32))
71110

72-
leafs = append(leafs, LeafNode{
111+
leafs = append(leafs, &Node{
73112
ID: hashArray(
74113
[][]byte{hDataHash[:], hMaxByteRange[:]},
75114
),
115+
Type: LeafNodeType,
76116
DataHash: chunk.DataHash,
77-
Type: "leaf",
78117
MinByteRange: chunk.MinByteRange,
79118
MaxByteRange: chunk.MaxByteRange,
119+
ByteRange: 0,
120+
LeftChild: nil,
121+
RightChild: nil,
80122
})
81123
}
124+
return
125+
}
126+
127+
// buildLayer
128+
func buildLayer(nodes []*Node, level int) (root *Node) {
129+
if len(nodes) == 1 {
130+
root = nodes[0]
131+
return
132+
}
133+
134+
nextLayer := make([]*Node, 0, len(nodes)/2)
135+
for i := 0; i < len(nodes); i += 2 {
136+
leftNode := nodes[i]
137+
var rightNode *Node
138+
if i+1 < len(nodes) {
139+
rightNode = nodes[i+1]
140+
}
141+
nextLayer = append(nextLayer, hashBranch(leftNode, rightNode))
142+
}
143+
144+
return buildLayer(nextLayer, level+1)
145+
}
146+
147+
// hashBranch get branch node by child node
148+
func hashBranch(leftNode, rightNode *Node) (branchNode *Node) {
149+
// 如果只有一个node,则该node 为branch node
150+
if rightNode == nil {
151+
return leftNode
152+
}
153+
hLeafNodeId := sha256.Sum256(leftNode.ID)
154+
hRightNodeId := sha256.Sum256(rightNode.ID)
155+
hLeafNodeMaxRange := sha256.Sum256(PaddedBigBytes(big.NewInt(int64(leftNode.MaxByteRange)), 32))
156+
id := hashArray([][]byte{hLeafNodeId[:], hRightNodeId[:], hLeafNodeMaxRange[:]})
157+
158+
branchNode = &Node{
159+
Type: BranchNodeType,
160+
ID: id,
161+
DataHash: nil,
162+
MinByteRange: 0,
163+
MaxByteRange: rightNode.MaxByteRange,
164+
ByteRange: leftNode.MaxByteRange,
165+
LeftChild: leftNode,
166+
RightChild: rightNode,
167+
}
82168

83169
return
84170
}
85171

86-
func buildLayer() {
87-
//TODO
172+
func generateProofs(rootNode *Node) []*Proof {
173+
return resolveBranchProofs(rootNode, []byte{}, 0)
88174
}
89175

90-
func generateProofs() {
91-
// TODO
176+
// resolveBranchProofs 从root node 递归搜索叶子节点并为其生成证明
177+
func resolveBranchProofs(node *Node, proof []byte, depth int) (proofs []*Proof) {
178+
179+
if node.Type == LeafNodeType {
180+
p := &Proof{
181+
Offest: node.MaxByteRange - 1,
182+
Proof: ConcatBuffer(
183+
proof,
184+
node.DataHash,
185+
PaddedBigBytes(big.NewInt(int64(node.MaxByteRange)), 32),
186+
),
187+
}
188+
proofs = append(proofs, p)
189+
return
190+
}
191+
192+
if node.Type == BranchNodeType {
193+
partialProof := ConcatBuffer(
194+
proof,
195+
node.LeftChild.ID,
196+
node.RightChild.ID,
197+
PaddedBigBytes(big.NewInt(int64(node.ByteRange)), 32),
198+
)
199+
leftProofs := resolveBranchProofs(node.LeftChild, partialProof, depth+1)
200+
rightProofs := resolveBranchProofs(node.RightChild, partialProof, depth+1)
201+
proofs = append(append(proofs, leftProofs...), rightProofs...)
202+
return
203+
}
204+
205+
// node type error then return nil
206+
return nil
92207
}
93208

94209
func hashArray(data [][]byte) []byte {
@@ -120,3 +235,18 @@ func ReadBits(bigint *big.Int, buf []byte) {
120235
}
121236
}
122237
}
238+
239+
// ConcatBuffer
240+
func ConcatBuffer(buffers ...[]byte) []byte {
241+
totalLength := 0
242+
for i := 0; i < len(buffers); i++ {
243+
totalLength += len(buffers[i])
244+
}
245+
246+
temp := make([]byte, 0, totalLength)
247+
248+
for _, val := range buffers {
249+
temp = append(temp, val...)
250+
}
251+
return temp
252+
}

0 commit comments

Comments
 (0)