@@ -2,7 +2,10 @@ package utils
2
2
3
3
import (
4
4
"crypto/sha256"
5
+ "math"
5
6
"math/big"
7
+
8
+ "github.com/shopspring/decimal"
6
9
)
7
10
8
11
const (
@@ -12,13 +15,15 @@ const (
12
15
// number of bits in a big.Word
13
16
wordBits = 32 << (uint64 (^ big .Word (0 )) >> 63 )
14
17
// number of bytes in a big.Word
15
- wordBytes = wordBits / 8
18
+ wordBytes = wordBits / 8
19
+ BranchNodeType = "branch"
20
+ LeafNodeType = "leaf"
16
21
)
17
22
18
23
type Chunks struct {
19
24
DataRoot []byte
20
25
Chunks []Chunk
21
- Proofs []Proof
26
+ Proofs []* Proof
22
27
}
23
28
24
29
type Chunk struct {
@@ -27,68 +32,179 @@ type Chunk struct {
27
32
MaxByteRange int
28
33
}
29
34
30
- type LeafNode struct {
35
+ // Node include leaf node and branch node
36
+ type Node struct {
31
37
ID []byte
32
- DataHash [] byte
33
- Type string
34
- MinByteRange int
38
+ Type string // "branch" or "leaf"
39
+ DataHash [] byte // only leaf node
40
+ MinByteRange int // only leaf node
35
41
MaxByteRange int
42
+ ByteRange int // only branch node
43
+ LeftChild * Node // only branch node
44
+ RightChild * Node // only branch node
36
45
}
37
46
38
47
type Proof struct {
39
48
Offest int
40
49
Proof []byte
41
50
}
42
51
43
- func GenerateChunks (data []byte ) ( c Chunks ) {
52
+ func GenerateChunks (data []byte ) Chunks {
44
53
chunks := chunkData (data )
45
54
leaves := generateLeaves (chunks )
46
- // TODO, calculate root & proofs
55
+ root := buildLayer (leaves , 0 ) // leaf node level == 0
56
+ proofs := generateProofs (root )
57
+
58
+ // Discard the last chunk & proof if it's zero length.
59
+ lastChunk := chunks [len (chunks )- 1 ]
60
+ if lastChunk .MaxByteRange - lastChunk .MinByteRange == 0 {
61
+ chunks = chunks [:len (chunks )- 1 ]
62
+ proofs = proofs [:len (proofs )- 1 ]
63
+ }
47
64
48
- c .DataRoot = leaves [0 ].ID
49
- return
65
+ return Chunks {
66
+ DataRoot : root .ID ,
67
+ Chunks : chunks ,
68
+ Proofs : proofs ,
69
+ }
50
70
}
51
71
52
72
func chunkData (data []byte ) (chunks []Chunk ) {
53
73
cursor := 0
54
- // TODO
55
- // for len(data) >= MAX_CHUNK_SIZE {
56
- // }
74
+ var rest = data
75
+ // if data length > max size
76
+ for len (rest ) >= MAX_CHUNK_SIZE {
77
+ chunkSize := MAX_CHUNK_SIZE
78
+
79
+ // 查看下一轮的chunkSize 是否小于最小的size,如果是则在这轮中调整chunk size 的大小
80
+ nextChunkSize := len (rest ) - MAX_CHUNK_SIZE
81
+ if nextChunkSize > 0 && nextChunkSize < MIN_CHUNK_SIZE {
82
+ dec := decimal .NewFromFloat (math .Ceil (float64 (len (rest ) / 2 )))
83
+ chunkSize = int (dec .IntPart ())
84
+ }
85
+
86
+ chunk := rest [:chunkSize ]
87
+ dataHash := sha256 .Sum256 (chunk )
88
+ cursor += len (chunk )
89
+ chunks = append (chunks , Chunk {
90
+ DataHash : dataHash [:],
91
+ MinByteRange : cursor - len (chunk ),
92
+ MaxByteRange : cursor ,
93
+ })
57
94
58
- hash := sha256 .Sum256 (data )
95
+ rest = rest [chunkSize :]
96
+ }
97
+
98
+ hash := sha256 .Sum256 (rest )
59
99
chunks = append (chunks , Chunk {
60
100
DataHash : hash [:],
61
101
MinByteRange : cursor ,
62
- MaxByteRange : cursor + len (data ),
102
+ MaxByteRange : cursor + len (rest ),
63
103
})
64
104
return
65
105
}
66
106
67
- func generateLeaves (chunks []Chunk ) (leafs []LeafNode ) {
107
+ func generateLeaves (chunks []Chunk ) (leafs []* Node ) {
68
108
for _ , chunk := range chunks {
69
109
hDataHash := sha256 .Sum256 (chunk .DataHash )
70
110
hMaxByteRange := sha256 .Sum256 (PaddedBigBytes (big .NewInt (int64 (chunk .MaxByteRange )), 32 ))
71
111
72
- leafs = append (leafs , LeafNode {
112
+ leafs = append (leafs , & Node {
73
113
ID : hashArray (
74
114
[][]byte {hDataHash [:], hMaxByteRange [:]},
75
115
),
116
+ Type : LeafNodeType ,
76
117
DataHash : chunk .DataHash ,
77
- Type : "leaf" ,
78
118
MinByteRange : chunk .MinByteRange ,
79
119
MaxByteRange : chunk .MaxByteRange ,
120
+ ByteRange : 0 ,
121
+ LeftChild : nil ,
122
+ RightChild : nil ,
80
123
})
81
124
}
125
+ return
126
+ }
127
+
128
+ // buildLayer
129
+ func buildLayer (nodes []* Node , level int ) (root * Node ) {
130
+ if len (nodes ) == 1 {
131
+ root = nodes [0 ]
132
+ return
133
+ }
134
+
135
+ nextLayer := make ([]* Node , 0 , len (nodes )/ 2 )
136
+ for i := 0 ; i < len (nodes ); i += 2 {
137
+ leftNode := nodes [i ]
138
+ var rightNode * Node
139
+ if i + 1 < len (nodes ) {
140
+ rightNode = nodes [i + 1 ]
141
+ }
142
+ nextLayer = append (nextLayer , hashBranch (leftNode , rightNode ))
143
+ }
144
+
145
+ return buildLayer (nextLayer , level + 1 )
146
+ }
147
+
148
+ // hashBranch get branch node by child node
149
+ func hashBranch (leftNode , rightNode * Node ) (branchNode * Node ) {
150
+ // 如果只有一个node,则该node 为branch node
151
+ if rightNode == nil {
152
+ return leftNode
153
+ }
154
+ hLeafNodeId := sha256 .Sum256 (leftNode .ID )
155
+ hRightNodeId := sha256 .Sum256 (rightNode .ID )
156
+ hLeafNodeMaxRange := sha256 .Sum256 (PaddedBigBytes (big .NewInt (int64 (leftNode .MaxByteRange )), 32 ))
157
+ id := hashArray ([][]byte {hLeafNodeId [:], hRightNodeId [:], hLeafNodeMaxRange [:]})
158
+
159
+ branchNode = & Node {
160
+ Type : BranchNodeType ,
161
+ ID : id ,
162
+ DataHash : nil ,
163
+ MinByteRange : 0 ,
164
+ MaxByteRange : rightNode .MaxByteRange ,
165
+ ByteRange : leftNode .MaxByteRange ,
166
+ LeftChild : leftNode ,
167
+ RightChild : rightNode ,
168
+ }
82
169
83
170
return
84
171
}
85
172
86
- func buildLayer () {
87
- //TODO
173
+ func generateProofs ( rootNode * Node ) [] * Proof {
174
+ return resolveBranchProofs ( rootNode , [] byte {}, 0 )
88
175
}
89
176
90
- func generateProofs () {
91
- // TODO
177
+ // resolveBranchProofs 从root node 递归搜索叶子节点并为其生成证明
178
+ func resolveBranchProofs (node * Node , proof []byte , depth int ) (proofs []* Proof ) {
179
+
180
+ if node .Type == LeafNodeType {
181
+ p := & Proof {
182
+ Offest : node .MaxByteRange - 1 ,
183
+ Proof : ConcatBuffer (
184
+ proof ,
185
+ node .DataHash ,
186
+ PaddedBigBytes (big .NewInt (int64 (node .MaxByteRange )), 32 ),
187
+ ),
188
+ }
189
+ proofs = append (proofs , p )
190
+ return
191
+ }
192
+
193
+ if node .Type == BranchNodeType {
194
+ partialProof := ConcatBuffer (
195
+ proof ,
196
+ node .LeftChild .ID ,
197
+ node .RightChild .ID ,
198
+ PaddedBigBytes (big .NewInt (int64 (node .ByteRange )), 32 ),
199
+ )
200
+ leftProofs := resolveBranchProofs (node .LeftChild , partialProof , depth + 1 )
201
+ rightProofs := resolveBranchProofs (node .RightChild , partialProof , depth + 1 )
202
+ proofs = append (append (proofs , leftProofs ... ), rightProofs ... )
203
+ return
204
+ }
205
+
206
+ // node type error then return nil
207
+ return nil
92
208
}
93
209
94
210
func hashArray (data [][]byte ) []byte {
@@ -120,3 +236,18 @@ func ReadBits(bigint *big.Int, buf []byte) {
120
236
}
121
237
}
122
238
}
239
+
240
+ // ConcatBuffer
241
+ func ConcatBuffer (buffers ... []byte ) []byte {
242
+ totalLength := 0
243
+ for i := 0 ; i < len (buffers ); i ++ {
244
+ totalLength += len (buffers [i ])
245
+ }
246
+
247
+ temp := make ([]byte , 0 , totalLength )
248
+
249
+ for _ , val := range buffers {
250
+ temp = append (temp , val ... )
251
+ }
252
+ return temp
253
+ }
0 commit comments