@@ -2,6 +2,8 @@ package utils
2
2
3
3
import (
4
4
"crypto/sha256"
5
+ "github.com/shopspring/decimal"
6
+ "math"
5
7
"math/big"
6
8
)
7
9
@@ -12,13 +14,15 @@ const (
12
14
// number of bits in a big.Word
13
15
wordBits = 32 << (uint64 (^ big .Word (0 )) >> 63 )
14
16
// number of bytes in a big.Word
15
- wordBytes = wordBits / 8
17
+ wordBytes = wordBits / 8
18
+ BranchNodeType = "branch"
19
+ LeafNodeType = "leaf"
16
20
)
17
21
18
22
type Chunks struct {
19
23
DataRoot []byte
20
24
Chunks []Chunk
21
- Proofs []Proof
25
+ Proofs []* Proof
22
26
}
23
27
24
28
type Chunk struct {
@@ -27,68 +31,179 @@ type Chunk struct {
27
31
MaxByteRange int
28
32
}
29
33
30
- type LeafNode struct {
34
+ // Node include leaf node and branch node
35
+ type Node struct {
31
36
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
35
40
MaxByteRange int
41
+ ByteRange int // only branch node
42
+ LeftChild * Node // only branch node
43
+ RightChild * Node // only branch node
36
44
}
37
45
38
46
type Proof struct {
39
47
Offest int
40
48
Proof []byte
41
49
}
42
50
43
- func GenerateChunks (data []byte ) ( c Chunks ) {
51
+ func GenerateChunks (data []byte ) Chunks {
44
52
chunks := chunkData (data )
45
53
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
+ }
47
63
48
- c .DataRoot = leaves [0 ].ID
49
- return
64
+ return Chunks {
65
+ DataRoot : root .ID ,
66
+ Chunks : chunks ,
67
+ Proofs : proofs ,
68
+ }
50
69
}
51
70
52
71
func chunkData (data []byte ) (chunks []Chunk ) {
53
72
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
+ }
57
96
58
- hash := sha256 .Sum256 (data )
97
+ hash := sha256 .Sum256 (rest )
59
98
chunks = append (chunks , Chunk {
60
99
DataHash : hash [:],
61
100
MinByteRange : cursor ,
62
- MaxByteRange : cursor + len (data ),
101
+ MaxByteRange : cursor + len (rest ),
63
102
})
64
103
return
65
104
}
66
105
67
- func generateLeaves (chunks []Chunk ) (leafs []LeafNode ) {
106
+ func generateLeaves (chunks []Chunk ) (leafs []* Node ) {
68
107
for _ , chunk := range chunks {
69
108
hDataHash := sha256 .Sum256 (chunk .DataHash )
70
109
hMaxByteRange := sha256 .Sum256 (PaddedBigBytes (big .NewInt (int64 (chunk .MaxByteRange )), 32 ))
71
110
72
- leafs = append (leafs , LeafNode {
111
+ leafs = append (leafs , & Node {
73
112
ID : hashArray (
74
113
[][]byte {hDataHash [:], hMaxByteRange [:]},
75
114
),
115
+ Type : LeafNodeType ,
76
116
DataHash : chunk .DataHash ,
77
- Type : "leaf" ,
78
117
MinByteRange : chunk .MinByteRange ,
79
118
MaxByteRange : chunk .MaxByteRange ,
119
+ ByteRange : 0 ,
120
+ LeftChild : nil ,
121
+ RightChild : nil ,
80
122
})
81
123
}
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
+ }
82
168
83
169
return
84
170
}
85
171
86
- func buildLayer () {
87
- //TODO
172
+ func generateProofs ( rootNode * Node ) [] * Proof {
173
+ return resolveBranchProofs ( rootNode , [] byte {}, 0 )
88
174
}
89
175
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
92
207
}
93
208
94
209
func hashArray (data [][]byte ) []byte {
@@ -120,3 +235,18 @@ func ReadBits(bigint *big.Int, buf []byte) {
120
235
}
121
236
}
122
237
}
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