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 base record
24//
25// ensures that pack->unpack returns the same original value
26func TestPackBaseData(t *testing.T) {
27
28	proofedByAccount := makeAccount(proofedBy.publicKey)
29
30	r := transactionrecord.OldBaseData{
31		Currency:       currency.Bitcoin,
32		PaymentAddress: "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn",
33		Owner:          proofedByAccount,
34		Nonce:          0x12345678,
35	}
36
37	expected := []byte{
38		0x01, 0x01, 0x22, 0x6d, 0x69, 0x70, 0x63, 0x42,
39		0x62, 0x46, 0x67, 0x39, 0x67, 0x4d, 0x69, 0x43,
40		0x68, 0x38, 0x31, 0x4b, 0x6a, 0x38, 0x74, 0x71,
41		0x71, 0x64, 0x67, 0x6f, 0x5a, 0x75, 0x62, 0x31,
42		0x5a, 0x4a, 0x52, 0x66, 0x6e, 0x21, 0x13, 0x55,
43		0xb2, 0x98, 0x88, 0x17, 0xf7, 0xea, 0xec, 0x37,
44		0x74, 0x1b, 0x82, 0x44, 0x71, 0x63, 0xca, 0xaa,
45		0x5a, 0x9d, 0xb2, 0xb6, 0xf0, 0xce, 0x72, 0x26,
46		0x26, 0x33, 0x8e, 0x5e, 0x3f, 0xd7, 0xf7, 0xf8,
47		0xac, 0xd1, 0x91, 0x01,
48	}
49
50	expectedTxId := merkle.Digest{
51		0x9e, 0x93, 0x2b, 0x8e, 0xa1, 0xa3, 0xd4, 0x30,
52		0xc5, 0x9a, 0x23, 0xfd, 0x56, 0x75, 0xe8, 0xba,
53		0x64, 0x0e, 0xe8, 0x1c, 0xf3, 0x0e, 0x68, 0xca,
54		0x14, 0x8e, 0xe1, 0x1f, 0x13, 0xdb, 0xd4, 0x27,
55	}
56
57	// manually sign the record and attach signature to "expected"
58	signature := ed25519.Sign(proofedBy.privateKey, expected)
59	r.Signature = signature
60	//t.Logf("signature: %#v", r.Signature)
61	l := util.ToVarint64(uint64(len(signature)))
62	expected = append(expected, l...)
63	expected = append(expected, signature...)
64
65	// test the packer
66	packed, err := r.Pack(proofedByAccount)
67	if nil != err {
68		t.Fatalf("pack error: %s", err)
69	}
70
71	// if either of above fail we will have the message _without_ a signature
72	if !bytes.Equal(packed, expected) {
73		t.Errorf("pack record: %x  expected: %x", packed, expected)
74		t.Errorf("*** GENERATED Packed:\n%s", util.FormatBytes("expected", packed))
75		t.Fatal("fatal error")
76	}
77
78	// check the record type
79	if transactionrecord.BaseDataTag != packed.Type() {
80		t.Fatalf("pack record type: %x  expected: %x", packed.Type(), transactionrecord.BaseDataTag)
81	}
82
83	t.Logf("Packed length: %d bytes", len(packed))
84
85	// check txIds
86	txId := packed.MakeLink()
87
88	if txId != expectedTxId {
89		t.Errorf("pack tx id: %#v  expected: %#v", txId, expectedTxId)
90		t.Errorf("*** GENERATED tx id:\n%s", util.FormatBytes("expectedTxId", txId[:]))
91	}
92
93	// test the unpacker
94	unpacked, n, err := packed.Unpack(true)
95	if nil != err {
96		t.Fatalf("unpack error: %s", err)
97	}
98
99	if len(packed) != n {
100		t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed))
101	}
102
103	baseData, ok := unpacked.(*transactionrecord.OldBaseData)
104	if !ok {
105		t.Fatalf("did not unpack to BaseData")
106	}
107
108	// display a JSON version for information
109	item := struct {
110		TxId     merkle.Digest
111		BaseData *transactionrecord.OldBaseData
112	}{
113		TxId:     txId,
114		BaseData: baseData,
115	}
116	b, err := json.MarshalIndent(item, "", "  ")
117	if nil != err {
118		t.Fatalf("json error: %s", err)
119	}
120
121	t.Logf("BaseData: JSON: %s", b)
122
123	// check that structure is preserved through Pack/Unpack
124	// note reg is a pointer here
125	if !reflect.DeepEqual(r, *baseData) {
126		t.Errorf("different, original: %v  recovered: %v", r, *baseData)
127	}
128	checkPackedData(t, "base data", packed)
129}
130
131// test the pack failure on trying to use the zero public key
132func TestPackBaseDataWithZeroAccount(t *testing.T) {
133
134	proofedByAccount := makeAccount(theZeroKey.publicKey)
135
136	r := transactionrecord.OldBaseData{
137		Currency:       currency.Bitcoin,
138		PaymentAddress: "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn",
139		Owner:          proofedByAccount,
140		Nonce:          0x12345678,
141		Signature:      []byte{1, 2, 3, 4},
142	}
143
144	// test the packer
145	_, err := r.Pack(proofedByAccount)
146	if nil == err {
147		t.Fatalf("pack should have failed")
148	}
149	if fault.InvalidOwnerOrRegistrant != err {
150		t.Fatalf("unexpected pack error: %s", err)
151	}
152}
153