1// SPDX-License-Identifier: ISC
2// Copyright (c) 2014-2020 Bitmark Inc.
3// Use of this source code is governed by an ISC
4// license that can be found in the LICENSE file.
5
6package transactionrecord_test
7
8import (
9	"bytes"
10	"encoding/json"
11	"reflect"
12	"testing"
13
14	"golang.org/x/crypto/ed25519"
15
16	"github.com/bitmark-inc/bitmarkd/currency"
17	"github.com/bitmark-inc/bitmarkd/fault"
18	"github.com/bitmark-inc/bitmarkd/merkle"
19	"github.com/bitmark-inc/bitmarkd/transactionrecord"
20	"github.com/bitmark-inc/bitmarkd/util"
21)
22
23// test the packing/unpacking of Bitmark transfer record
24//
25// transfer from issue
26// ensures that pack->unpack returns the same original value
27func TestPackBitmarkTransferCountersignedOne(t *testing.T) {
28
29	issuerAccount := makeAccount(issuer.publicKey)
30	ownerOneAccount := makeAccount(ownerOne.publicKey)
31
32	var link merkle.Digest
33	err := merkleDigestFromLE("79a67be2b3d313bd490363fb0d27901c46ed53d3f7b21f60d48bc42439b06084", &link)
34	if nil != err {
35		t.Fatalf("hex to link error: %s", err)
36	}
37
38	r := transactionrecord.BitmarkTransferCountersigned{
39		Link:  link,
40		Owner: ownerOneAccount,
41	}
42
43	expected := []byte{
44		0x05, 0x20, 0x79, 0xa6, 0x7b, 0xe2, 0xb3, 0xd3,
45		0x13, 0xbd, 0x49, 0x03, 0x63, 0xfb, 0x0d, 0x27,
46		0x90, 0x1c, 0x46, 0xed, 0x53, 0xd3, 0xf7, 0xb2,
47		0x1f, 0x60, 0xd4, 0x8b, 0xc4, 0x24, 0x39, 0xb0,
48		0x60, 0x84, 0x00, 0x21, 0x13, 0x27, 0x64, 0x0e,
49		0x4a, 0xab, 0x92, 0xd8, 0x7b, 0x4a, 0x6a, 0x2f,
50		0x30, 0xb8, 0x81, 0xf4, 0x49, 0x29, 0xf8, 0x66,
51		0x04, 0x3a, 0x84, 0x1c, 0x38, 0x14, 0xb1, 0x66,
52		0xb8, 0x89, 0x44, 0xb0, 0x92,
53	}
54
55	expectedTxId := merkle.Digest{
56		0x6e, 0x72, 0xbb, 0x9a, 0x58, 0x50, 0xcc, 0x28,
57		0x8e, 0x3c, 0x72, 0x6f, 0xbb, 0xe4, 0x33, 0xa0,
58		0xe0, 0x81, 0x78, 0xac, 0xde, 0x1c, 0x8c, 0xb0,
59		0x31, 0xa4, 0x36, 0x2d, 0x77, 0xa0, 0x4e, 0x09,
60	}
61
62	// manually sign the record and attach signature to "expected"
63	signature := ed25519.Sign(issuer.privateKey, expected)
64	r.Signature = signature
65	l := util.ToVarint64(uint64(len(signature)))
66	expected = append(expected, l...)
67	expected = append(expected, signature...)
68
69	// manually countersign the record and attach countersignature to "expected"
70	signature = ed25519.Sign(ownerOne.privateKey, expected)
71	r.Countersignature = signature
72	l = util.ToVarint64(uint64(len(signature)))
73	expected = append(expected, l...)
74	expected = append(expected, signature...)
75
76	// test the packer
77	packed, err := r.Pack(issuerAccount)
78	if nil != err {
79		t.Errorf("pack error: %s", err)
80	}
81
82	// if either of above fail we will have the message _without_ a signature
83	if !bytes.Equal(packed, expected) {
84		t.Errorf("pack record: %x  expected: %x", packed, expected)
85		t.Errorf("*** GENERATED Packed:\n%s", util.FormatBytes("expected", packed))
86		t.Fatal("fatal error")
87	}
88
89	t.Logf("Packed length: %d bytes", len(packed))
90
91	// check txId
92	txId := packed.MakeLink()
93
94	if txId != expectedTxId {
95		t.Errorf("pack txId: %#v  expected: %x", txId, expectedTxId)
96		t.Errorf("*** GENERATED txId:\n%s", util.FormatBytes("expectedTxId", txId[:]))
97		t.Fatal("fatal error")
98	}
99
100	// test the unpacker
101	unpacked, n, err := packed.Unpack(true)
102	if nil != err {
103		t.Fatalf("unpack error: %s", err)
104	}
105	if len(packed) != n {
106		t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed))
107	}
108
109	bmt, ok := unpacked.(*transactionrecord.BitmarkTransferCountersigned)
110	if !ok {
111		t.Fatalf("did not unpack to BitmarkTransferCountersigned")
112	}
113
114	// display a JSON version for information
115	item := struct {
116		TxId                         merkle.Digest
117		BitmarkTransferCountersigned *transactionrecord.BitmarkTransferCountersigned
118	}{
119		txId,
120		bmt,
121	}
122	b, err := json.MarshalIndent(item, "", "  ")
123	if nil != err {
124		t.Fatalf("json error: %s", err)
125	}
126
127	t.Logf("Bitmark Transfer: JSON: %s", b)
128
129	// check that structure is preserved through Pack/Unpack
130	// note reg is a pointer here
131	if !reflect.DeepEqual(r, *bmt) {
132		t.Fatalf("different, original: %v  recovered: %v", r, *bmt)
133	}
134}
135
136// test the packing/unpacking of Bitmark transfer record
137//
138// test transfer to transfer
139// ensures that pack->unpack returns the same original value
140func TestPackBitmarkTransferCountersignedTwo(t *testing.T) {
141
142	ownerOneAccount := makeAccount(ownerOne.publicKey)
143	ownerTwoAccount := makeAccount(ownerTwo.publicKey)
144
145	var link merkle.Digest
146	err := merkleDigestFromLE("630c041cd1f586bcb9097e816189185c1e0379f67bbfc2f0626724f542047873", &link)
147	if nil != err {
148		t.Fatalf("hex to link error: %s", err)
149	}
150
151	r := transactionrecord.BitmarkTransferCountersigned{
152		Link: link,
153		Escrow: &transactionrecord.Payment{
154			Currency: currency.Bitcoin,
155			Address:  "mnnemVbQECtikaGZPYux4dGHH3YZyCg4sq",
156			Amount:   250000,
157		},
158		Owner: ownerTwoAccount,
159	}
160
161	expected := []byte{
162		0x05, 0x20, 0x63, 0x0c, 0x04, 0x1c, 0xd1, 0xf5,
163		0x86, 0xbc, 0xb9, 0x09, 0x7e, 0x81, 0x61, 0x89,
164		0x18, 0x5c, 0x1e, 0x03, 0x79, 0xf6, 0x7b, 0xbf,
165		0xc2, 0xf0, 0x62, 0x67, 0x24, 0xf5, 0x42, 0x04,
166		0x78, 0x73, 0x01, 0x01, 0x22, 0x6d, 0x6e, 0x6e,
167		0x65, 0x6d, 0x56, 0x62, 0x51, 0x45, 0x43, 0x74,
168		0x69, 0x6b, 0x61, 0x47, 0x5a, 0x50, 0x59, 0x75,
169		0x78, 0x34, 0x64, 0x47, 0x48, 0x48, 0x33, 0x59,
170		0x5a, 0x79, 0x43, 0x67, 0x34, 0x73, 0x71, 0x90,
171		0xa1, 0x0f, 0x21, 0x13, 0xa1, 0x36, 0x32, 0xd5,
172		0x42, 0x5a, 0xed, 0x3a, 0x6b, 0x62, 0xe2, 0xbb,
173		0x6d, 0xe4, 0xc9, 0x59, 0x48, 0x41, 0xc1, 0x5b,
174		0x70, 0x15, 0x69, 0xec, 0x99, 0x99, 0xdc, 0x20,
175		0x1c, 0x35, 0xf7, 0xb3,
176	}
177
178	expectedTxId := merkle.Digest{
179		0x2a, 0xf9, 0xd9, 0xf1, 0xbb, 0x8d, 0x8a, 0x54,
180		0x68, 0x55, 0x7c, 0x86, 0x97, 0x96, 0x01, 0x18,
181		0x48, 0x2c, 0x08, 0x6a, 0x76, 0xc1, 0xcb, 0xb0,
182		0x21, 0xf7, 0x3f, 0x4d, 0x27, 0x65, 0x37, 0x70,
183	}
184
185	// manually sign the record and attach signature to "expected"
186	signature := ed25519.Sign(ownerOne.privateKey, expected)
187	r.Signature = signature
188	l := util.ToVarint64(uint64(len(signature)))
189	expected = append(expected, l...)
190	expected = append(expected, signature...)
191
192	// manually countersign the record and attach countersignature to "expected"
193	signature = ed25519.Sign(ownerTwo.privateKey, expected)
194	r.Countersignature = signature
195	l = util.ToVarint64(uint64(len(signature)))
196	expected = append(expected, l...)
197	expected = append(expected, signature...)
198
199	// test the packer
200	packed, err := r.Pack(ownerOneAccount)
201	if nil != err {
202		t.Errorf("pack error: %s", err)
203	}
204
205	// if either of above fail we will have the message _without_ a signature
206	if !bytes.Equal(packed, expected) {
207		t.Errorf("pack record: %x  expected: %x", packed, expected)
208		t.Errorf("*** GENERATED Packed:\n%s", util.FormatBytes("expected", packed))
209		t.Fatal("fatal error")
210	}
211
212	t.Logf("Packed length: %d bytes", len(packed))
213
214	// check txId
215	txId := packed.MakeLink()
216
217	if txId != expectedTxId {
218		t.Errorf("pack txId: %#v  expected: %x", txId, expectedTxId)
219		t.Errorf("*** GENERATED txId:\n%s", util.FormatBytes("expectedTxId", txId[:]))
220		t.Fatal("fatal error")
221	}
222
223	// test the unpacker
224	unpacked, n, err := packed.Unpack(true)
225	if nil != err {
226		t.Fatalf("unpack error: %s", err)
227	}
228	if len(packed) != n {
229		t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed))
230	}
231
232	bmt, ok := unpacked.(*transactionrecord.BitmarkTransferCountersigned)
233	if !ok {
234		t.Fatalf("did not unpack to BitmarkTransferCountersigned")
235	}
236
237	// display a JSON version for information
238	item := struct {
239		TxId                         merkle.Digest
240		BitmarkTransferCountersigned *transactionrecord.BitmarkTransferCountersigned
241	}{
242		txId,
243		bmt,
244	}
245	b, err := json.MarshalIndent(item, "", "  ")
246	if nil != err {
247		t.Fatalf("json error: %s", err)
248	}
249
250	t.Logf("Bitmark Transfer: JSON: %s", b)
251
252	// check that structure is preserved through Pack/Unpack
253	// note reg is a pointer here
254	if !reflect.DeepEqual(r, *bmt) {
255		t.Fatalf("different, original: %v  recovered: %v", r, *bmt)
256	}
257}
258
259// test the packing/unpacking of Bitmark transfer record
260//
261// test transfer to transfer
262// ensures that pack->unpack returns the same original value
263func TestPackBitmarkTransferCountersignedThree(t *testing.T) {
264
265	ownerOneAccount := makeAccount(ownerOne.publicKey)
266	ownerTwoAccount := makeAccount(ownerTwo.publicKey)
267
268	var link merkle.Digest
269	err := merkleDigestFromLE("14eb103a0c8fb22e50e73ae9b4ff88595b1cd5f60c4afb690d8fbd014c3ed091", &link)
270	if nil != err {
271		t.Fatalf("hex to link error: %s", err)
272	}
273
274	r := transactionrecord.BitmarkTransferCountersigned{
275		Link:   link,
276		Escrow: nil,
277		Owner:  ownerOneAccount,
278	}
279
280	expected := []byte{
281		0x05, 0x20, 0x14, 0xeb, 0x10, 0x3a, 0x0c, 0x8f,
282		0xb2, 0x2e, 0x50, 0xe7, 0x3a, 0xe9, 0xb4, 0xff,
283		0x88, 0x59, 0x5b, 0x1c, 0xd5, 0xf6, 0x0c, 0x4a,
284		0xfb, 0x69, 0x0d, 0x8f, 0xbd, 0x01, 0x4c, 0x3e,
285		0xd0, 0x91, 0x00, 0x21, 0x13, 0x27, 0x64, 0x0e,
286		0x4a, 0xab, 0x92, 0xd8, 0x7b, 0x4a, 0x6a, 0x2f,
287		0x30, 0xb8, 0x81, 0xf4, 0x49, 0x29, 0xf8, 0x66,
288		0x04, 0x3a, 0x84, 0x1c, 0x38, 0x14, 0xb1, 0x66,
289		0xb8, 0x89, 0x44, 0xb0, 0x92,
290	}
291
292	expectedTxId := merkle.Digest{
293		0xb9, 0xdd, 0xe2, 0x87, 0x3a, 0x98, 0x21, 0xaa,
294		0x27, 0x52, 0x13, 0x76, 0x91, 0x4c, 0x8c, 0xb1,
295		0x17, 0x9d, 0xb6, 0x36, 0xd3, 0x72, 0xaa, 0x4a,
296		0x2a, 0x25, 0xfa, 0x2e, 0x15, 0x88, 0x3a, 0xb5,
297	}
298
299	// manually sign the record and attach signature to "expected"
300	signature := ed25519.Sign(ownerTwo.privateKey, expected)
301	r.Signature = signature
302	l := util.ToVarint64(uint64(len(signature)))
303	expected = append(expected, l...)
304	expected = append(expected, signature...)
305
306	// manually countersign the record and attach countersignature to "expected"
307	signature = ed25519.Sign(ownerOne.privateKey, expected)
308	r.Countersignature = signature
309	l = util.ToVarint64(uint64(len(signature)))
310	expected = append(expected, l...)
311	expected = append(expected, signature...)
312
313	// test the packer
314	packed, err := r.Pack(ownerTwoAccount)
315	if nil != err {
316		t.Errorf("pack error: %s", err)
317	}
318
319	// if either of above fail we will have the message _without_ a signature
320	if !bytes.Equal(packed, expected) {
321		t.Errorf("pack record: %x  expected: %x", packed, expected)
322		t.Errorf("*** GENERATED Packed:\n%s", util.FormatBytes("expected", packed))
323		t.Fatal("fatal error")
324	}
325
326	t.Logf("Packed length: %d bytes", len(packed))
327
328	// check txId
329	txId := packed.MakeLink()
330
331	if txId != expectedTxId {
332		t.Errorf("pack txId: %#v  expected: %x", txId, expectedTxId)
333		t.Errorf("*** GENERATED txId:\n%s", util.FormatBytes("expectedTxId", txId[:]))
334		t.Fatal("fatal error")
335	}
336
337	// test the unpacker
338	unpacked, n, err := packed.Unpack(true)
339	if nil != err {
340		t.Fatalf("unpack error: %s", err)
341	}
342	if len(packed) != n {
343		t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed))
344	}
345
346	bmt, ok := unpacked.(*transactionrecord.BitmarkTransferCountersigned)
347	if !ok {
348		t.Fatalf("did not unpack to BitmarkTransferCountersigned")
349	}
350
351	// display a JSON version for information
352	item := struct {
353		TxId                         merkle.Digest
354		BitmarkTransferCountersigned *transactionrecord.BitmarkTransferCountersigned
355	}{
356		txId,
357		bmt,
358	}
359	b, err := json.MarshalIndent(item, "", "  ")
360	if nil != err {
361		t.Fatalf("json error: %s", err)
362	}
363
364	t.Logf("Bitmark Transfer: JSON: %s", b)
365
366	// check that structure is preserved through Pack/Unpack
367	// note reg is a pointer here
368	if !reflect.DeepEqual(r, *bmt) {
369		t.Fatalf("different, original: %v  recovered: %v", r, *bmt)
370	}
371}
372
373// test the packing/unpacking of Bitmark transfer record
374//
375// check for error on incorrect countersignature
376func TestPackBitmarkTransferCountersignedFail(t *testing.T) {
377
378	ownerOneAccount := makeAccount(ownerOne.publicKey)
379	ownerTwoAccount := makeAccount(ownerTwo.publicKey)
380
381	var link merkle.Digest
382	err := merkleDigestFromLE("14eb103a0c8fb22e50e73ae9b4ff88595b1cd5f60c4afb690d8fbd014c3ed091", &link)
383	if nil != err {
384		t.Fatalf("hex to link error: %s", err)
385	}
386
387	r := transactionrecord.BitmarkTransferCountersigned{
388		Link:   link,
389		Escrow: nil,
390		Owner:  ownerOneAccount,
391	}
392
393	expected := []byte{
394		0x05, 0x20, 0x14, 0xeb, 0x10, 0x3a, 0x0c, 0x8f,
395		0xb2, 0x2e, 0x50, 0xe7, 0x3a, 0xe9, 0xb4, 0xff,
396		0x88, 0x59, 0x5b, 0x1c, 0xd5, 0xf6, 0x0c, 0x4a,
397		0xfb, 0x69, 0x0d, 0x8f, 0xbd, 0x01, 0x4c, 0x3e,
398		0xd0, 0x91, 0x00, 0x21, 0x13, 0x27, 0x64, 0x0e,
399		0x4a, 0xab, 0x92, 0xd8, 0x7b, 0x4a, 0x6a, 0x2f,
400		0x30, 0xb8, 0x81, 0xf4, 0x49, 0x29, 0xf8, 0x66,
401		0x04, 0x3a, 0x84, 0x1c, 0x38, 0x14, 0xb1, 0x66,
402		0xb8, 0x89, 0x44, 0xb0, 0x92,
403	}
404
405	// manually sign the record and attach signature to "expected"
406	signature := ed25519.Sign(ownerTwo.privateKey, expected)
407	r.Signature = signature
408	l := util.ToVarint64(uint64(len(signature)))
409	expected = append(expected, l...)
410	expected = append(expected, signature...)
411
412	// manually countersign the record and attach countersignature to "expected"
413	signature = ed25519.Sign(ownerTwo.privateKey, expected) // wrong signature
414	r.Countersignature = signature
415
416	// test the packer
417	_, err = r.Pack(ownerTwoAccount)
418	if fault.InvalidSignature == err {
419		return
420	}
421	if nil == err {
422		t.Error("unexpected pack success, should fail with invalid signature")
423	} else {
424		t.Errorf("pack error: %s", err)
425	}
426
427	t.Fatal("fatal error")
428}
429
430// test the pack failure on trying to use the zero public key
431func TestPackBitmarkTransferCountersignedFromZeroAccount(t *testing.T) {
432
433	ownerDeletedAccount := makeAccount(theZeroKey.publicKey)
434	ownerOneAccount := makeAccount(ownerOne.publicKey)
435
436	var link merkle.Digest
437	err := merkleDigestFromLE("14eb103a0c8fb22e50e73ae9b4ff88595b1cd5f60c4afb690d8fbd014c3ed091", &link)
438	if nil != err {
439		t.Fatalf("hex to link error: %s", err)
440	}
441
442	r := transactionrecord.BitmarkTransferCountersigned{
443		Link:             link,
444		Escrow:           nil,
445		Owner:            ownerOneAccount,
446		Signature:        []byte{1, 2, 3, 4},
447		Countersignature: []byte{1, 2, 3, 4},
448	}
449
450	// test the packer
451	_, err = r.Pack(ownerDeletedAccount)
452	if nil == err {
453		t.Fatalf("pack should have failed")
454	}
455	if fault.InvalidOwnerOrRegistrant != err {
456		t.Fatalf("unexpected pack error: %s", err)
457	}
458}
459
460// test the pack failure on trying to use the zero public key
461func TestPackBitmarkTransferCountersignedToZeroAccount(t *testing.T) {
462
463	ownerOneAccount := makeAccount(ownerOne.publicKey)
464	ownerDeletedAccount := makeAccount(theZeroKey.publicKey)
465
466	var link merkle.Digest
467	err := merkleDigestFromLE("14eb103a0c8fb22e50e73ae9b4ff88595b1cd5f60c4afb690d8fbd014c3ed091", &link)
468	if nil != err {
469		t.Fatalf("hex to link error: %s", err)
470	}
471
472	r := transactionrecord.BitmarkTransferCountersigned{
473		Link:             link,
474		Escrow:           nil,
475		Owner:            ownerDeletedAccount,
476		Signature:        []byte{1, 2, 3, 4},
477		Countersignature: []byte{1, 2, 3, 4},
478	}
479
480	// test the packer
481	_, err = r.Pack(ownerOneAccount)
482	if nil == err {
483		t.Fatalf("pack should have failed")
484	}
485	if fault.InvalidOwnerOrRegistrant != err {
486		t.Fatalf("unexpected pack error: %s", err)
487	}
488}
489