8 "github.com/vapor/protocol/bc"
9 "github.com/vapor/protocol/vm"
10 "github.com/vapor/testutil"
13 func TestMerkleRoot(t *testing.T) {
18 witnesses: [][][]byte{
24 want: testutil.MustDecodeHash("fe34dbd5da0ce3656f423fd7aad7fc7e879353174d33a6446c2ed0e3f3512101"),
26 witnesses: [][][]byte{
36 want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
38 witnesses: [][][]byte{
49 want: testutil.MustDecodeHash("0e4b4c1af18b8f59997804d69f8f66879ad5e30027346ee003ff7c7a512e5554"),
52 for _, c := range cases {
54 for _, wit := range c.witnesses {
55 txs = append(txs, NewTx(TxData{
59 TypedInput: &SpendInput{
61 SpendCommitment: SpendCommitment{
62 AssetAmount: bc.AssetAmount{
63 AssetId: &bc.AssetID{V0: 0},
71 got, err := TxMerkleRoot(txs)
73 t.Fatalf("unexpected error %s", err)
76 t.Log("witnesses", c.witnesses)
77 t.Errorf("got merkle root = %x want %x", got.Bytes(), c.want.Bytes())
82 func TestDuplicateLeaves(t *testing.T) {
83 trueProg := []byte{byte(vm.OP_TRUE)}
84 assetID := bc.AssetID{V0: 9999}
85 txs := make([]*bc.Tx, 6)
86 for i := uint64(0); i < 6; i++ {
87 txs[i] = NewTx(TxData{
89 Outputs: []*TxOutput{NewIntraChainOutput(assetID, i, trueProg)},
93 // first, get the root of an unbalanced tree
94 txns := []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0]}
95 root1, err := TxMerkleRoot(txns)
97 t.Fatalf("unexpected error %s", err)
100 // now, get the root of a balanced tree that repeats leaves 0 and 1
101 txns = []*bc.Tx{txs[5], txs[4], txs[3], txs[2], txs[1], txs[0], txs[1], txs[0]}
102 root2, err := TxMerkleRoot(txns)
104 t.Fatalf("unexpected error %s", err)
108 t.Error("forged merkle tree by duplicating some leaves")
112 func TestAllDuplicateLeaves(t *testing.T) {
113 trueProg := []byte{byte(vm.OP_TRUE)}
114 assetID := bc.AssetID{V0: 9999}
118 Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
120 tx1, tx2, tx3, tx4, tx5, tx6 := tx, tx, tx, tx, tx, tx
122 // first, get the root of an unbalanced tree
123 txs := []*bc.Tx{tx6, tx5, tx4, tx3, tx2, tx1}
124 root1, err := TxMerkleRoot(txs)
126 t.Fatalf("unexpected error %s", err)
129 // now, get the root of a balanced tree that repeats leaves 5 and 6
130 txs = []*bc.Tx{tx6, tx5, tx6, tx5, tx4, tx3, tx2, tx1}
131 root2, err := TxMerkleRoot(txs)
133 t.Fatalf("unexpected error %s", err)
137 t.Error("forged merkle tree with all duplicate leaves")
141 func TestTxMerkleProof(t *testing.T) {
144 relatedTxIndexes []int
150 relatedTxIndexes: []int{0, 3, 7, 8},
152 expectFlags: []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
156 relatedTxIndexes: []int{},
158 expectFlags: []uint8{0},
162 relatedTxIndexes: []int{0},
164 expectFlags: []uint8{2},
168 relatedTxIndexes: []int{1, 3, 5, 7, 11, 15},
170 expectFlags: []uint8{1, 1, 1, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0, 2, 0},
173 for _, c := range cases {
174 txs, bcTxs := mockTransactions(c.txCount)
176 var nodes []merkleNode
177 for _, tx := range txs {
178 nodes = append(nodes, tx.ID)
180 tree := buildMerkleTree(nodes)
181 root, err := TxMerkleRoot(bcTxs)
183 t.Fatalf("unexpected error %s", err)
185 if tree.hash != root {
186 t.Error("build tree fail")
190 for _, index := range c.relatedTxIndexes {
191 relatedTx = append(relatedTx, txs[index])
193 proofHashes, flags := GetTxMerkleTreeProof(txs, relatedTx)
194 if !testutil.DeepEqual(flags, c.expectFlags) {
195 t.Error("The flags is not equals expect flags", flags, c.expectFlags)
197 if len(proofHashes) != c.expectHashLen {
198 t.Error("The length proof hashes is not equals expect length")
201 for _, tx := range relatedTx {
202 ids = append(ids, &tx.ID)
204 if !ValidateTxMerkleTreeProof(proofHashes, flags, ids, root) {
205 t.Error("Merkle tree validate fail")
210 func TestStatusMerkleProof(t *testing.T) {
219 relatedIndexes: []int{0, 3, 7, 8},
220 flags: []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
225 relatedIndexes: []int{},
231 relatedIndexes: []int{0},
237 relatedIndexes: []int{1, 3, 5, 7, 11, 15},
238 flags: []uint8{1, 1, 1, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0, 2, 0},
242 for _, c := range cases {
243 statuses := mockStatuses(c.statusCount)
244 var relatedStatuses []*bc.TxVerifyResult
245 for _, index := range c.relatedIndexes {
246 relatedStatuses = append(relatedStatuses, statuses[index])
248 hashes := GetStatusMerkleTreeProof(statuses, c.flags)
249 if len(hashes) != c.expectHashLen {
250 t.Error("The length proof hashes is not equals expect length")
252 root, _ := TxStatusMerkleRoot(statuses)
253 if !ValidateStatusMerkleTreeProof(hashes, c.flags, relatedStatuses, root) {
254 t.Error("Merkle tree validate fail")
259 func TestUglyValidateTxMerkleProof(t *testing.T) {
263 relatedHashes []string
270 relatedHashes: []string{},
276 flags: []uint8{1, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1, 0, 2, 1, 2, 0},
277 relatedHashes: []string{},
283 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
284 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
287 relatedHashes: []string{},
294 relatedHashes: []string{
295 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
296 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
303 flags: []uint8{1, 1, 0, 2, 1, 2, 1, 0, 1},
304 relatedHashes: []string{
305 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
306 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
308 root: "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
312 "68f03ea2b02a21ad944d1a43ad6152a7fa6a7ed4101d59be62594dd30ef2a558",
315 relatedHashes: []string{
316 "0093370a8e19f8f131fd7e75c576615950d5672ee5e18c63f105a95bcab4332c",
317 "c9b7779847fb7ab74cf4b1e7f4557133918faa2bc130042753417dfb62b12dfa",
319 root: "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
324 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
325 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
326 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
328 flags: []uint8{1, 1, 0, 2, 0},
329 relatedHashes: []string{
330 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
332 root: "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
335 // flags and hashes is correct, but relatedHashes has hash that does not exist
338 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
339 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
340 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
342 flags: []uint8{1, 1, 0, 2, 0},
343 relatedHashes: []string{
344 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
345 "281138e0a9ea19505844bd61a2f5843787035782c093da74d12b5fba73eeeb07",
347 root: "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
350 // flags and hashes is correct, but relatedHashes is not enough
353 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
354 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
355 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
357 flags: []uint8{1, 1, 0, 2, 0},
358 relatedHashes: []string{},
359 root: "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
362 // flags is correct, but hashes has additional hash at the end
365 "8ec3ee7589f95eee9b534f71fcd37142bcc839a0dbfe78124df9663827b90c35",
366 "011bd3380852b2946df507e0c6234222c559eec8f545e4bc58a89e960892259b",
367 "c205988d9c864083421f1bdb95e6cf8b52070facfcc87e46a6e8197f5389fca2",
368 "5a06c90136e81c0f9cad29725e69edc6d21bd6fb0641265f9c4b6bb6840b37dd",
370 flags: []uint8{1, 1, 0, 2, 0},
371 relatedHashes: []string{
372 "504af455e328e7dd39bbc059529851946d54ee8b459b11b3aac4a0feeb474487",
374 root: "aff81a46fe79204ef9007243f374d54104a59762b9f74d80d56b5291753db6fb",
379 for _, c := range cases {
380 var hashes, relatedHashes []*bc.Hash
381 var hashBytes, rootBytes [32]byte
383 for _, hashStr := range c.hashes {
384 if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
388 hash := bc.NewHash(hashBytes)
389 hashes = append(hashes, &hash)
391 for _, hashStr := range c.relatedHashes {
392 if hashBytes, err = convertHashStr2Bytes(hashStr); err != nil {
396 hash := bc.NewHash(hashBytes)
397 relatedHashes = append(relatedHashes, &hash)
399 if rootBytes, err = convertHashStr2Bytes(c.root); err != nil {
403 root := bc.NewHash(rootBytes)
404 if ValidateTxMerkleTreeProof(hashes, c.flags, relatedHashes, root) != c.expectResult {
405 t.Error("Validate merkle tree proof fail")
410 func convertHashStr2Bytes(hashStr string) ([32]byte, error) {
412 hashBytes, err := hex.DecodeString(hashStr)
416 copy(result[:], hashBytes)
420 func mockTransactions(txCount int) ([]*Tx, []*bc.Tx) {
423 trueProg := []byte{byte(vm.OP_TRUE)}
424 assetID := bc.AssetID{V0: 9999}
425 for i := uint64(0); i < uint64(txCount); i++ {
428 Inputs: []*TxInput{NewSpendInput(nil, bc.Hash{V0: i + 1}, assetID, i, i, trueProg)},
429 Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
431 txs = append(txs, tx)
432 bcTxs = append(bcTxs, tx.Tx)
437 func mockStatuses(statusCount int) []*bc.TxVerifyResult {
438 var statuses []*bc.TxVerifyResult
439 for i := 0; i < statusCount; i++ {
440 status := &bc.TxVerifyResult{}
443 status.StatusFail = true
445 status.StatusFail = false
447 statuses = append(statuses, status)