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 "fmt" 12 "reflect" 13 "testing" 14 15 "golang.org/x/crypto/ed25519" 16 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 issue record 24// 25// ensures that pack->unpack returns the same original value 26func TestPackBitmarkIssue(t *testing.T) { 27 28 issuerAccount := makeAccount(issuer.publicKey) 29 30 var assetId transactionrecord.AssetIdentifier 31 _, err := fmt.Sscan("59d06155d25dffdb982729de8dce9d7855ca094d8bab8124b347c40668477056b3c27ccb7d71b54043d207ccd187642bf9c8466f9a8d0dbefb4c41633a7e39ef", &assetId) 32 if nil != err { 33 t.Fatalf("hex to asset id error: %s", err) 34 } 35 36 r := transactionrecord.BitmarkIssue{ 37 AssetId: assetId, 38 Owner: issuerAccount, 39 Nonce: 99, 40 } 41 42 expected := []byte{ 43 0x03, 0x40, 0x59, 0xd0, 0x61, 0x55, 0xd2, 0x5d, 44 0xff, 0xdb, 0x98, 0x27, 0x29, 0xde, 0x8d, 0xce, 45 0x9d, 0x78, 0x55, 0xca, 0x09, 0x4d, 0x8b, 0xab, 46 0x81, 0x24, 0xb3, 0x47, 0xc4, 0x06, 0x68, 0x47, 47 0x70, 0x56, 0xb3, 0xc2, 0x7c, 0xcb, 0x7d, 0x71, 48 0xb5, 0x40, 0x43, 0xd2, 0x07, 0xcc, 0xd1, 0x87, 49 0x64, 0x2b, 0xf9, 0xc8, 0x46, 0x6f, 0x9a, 0x8d, 50 0x0d, 0xbe, 0xfb, 0x4c, 0x41, 0x63, 0x3a, 0x7e, 51 0x39, 0xef, 0x21, 0x13, 0x9f, 0xc4, 0x86, 0xa2, 52 0x53, 0x4f, 0x17, 0xe3, 0x67, 0x07, 0xfa, 0x4b, 53 0x95, 0x3e, 0x3b, 0x34, 0x00, 0xe2, 0x72, 0x9f, 54 0x65, 0x61, 0x16, 0xdd, 0x7b, 0x01, 0x8d, 0xf3, 55 0x46, 0x98, 0xbd, 0xc2, 0x63, 56 } 57 58 expectedTxId := merkle.Digest{ 59 0x79, 0xa6, 0x7b, 0xe2, 0xb3, 0xd3, 0x13, 0xbd, 60 0x49, 0x03, 0x63, 0xfb, 0x0d, 0x27, 0x90, 0x1c, 61 0x46, 0xed, 0x53, 0xd3, 0xf7, 0xb2, 0x1f, 0x60, 62 0xd4, 0x8b, 0xc4, 0x24, 0x39, 0xb0, 0x60, 0x84, 63 } 64 65 // manually sign the record and attach signature to "expected" 66 signature := ed25519.Sign(issuer.privateKey, expected) 67 r.Signature = signature 68 l := util.ToVarint64(uint64(len(signature))) 69 expected = append(expected, l...) 70 expected = append(expected, signature...) 71 72 // test the packer 73 packed, err := r.Pack(issuerAccount) 74 if nil != err { 75 if nil != packed { 76 t.Errorf("partial packed:\n%s", util.FormatBytes("expected", packed)) 77 } 78 t.Errorf("pack error: %s", err) 79 } 80 81 // if either of above fail we will have the message _without_ a signature 82 if !bytes.Equal(packed, expected) { 83 t.Errorf("pack record: %x expected: %x", packed, expected) 84 t.Errorf("*** GENERATED Packed:\n%s", util.FormatBytes("expected", packed)) 85 t.Fatal("fatal error") 86 } 87 88 t.Logf("Packed length: %d bytes", len(packed)) 89 90 // check txId 91 txId := packed.MakeLink() 92 93 if txId != expectedTxId { 94 t.Errorf("pack tx id: %#v expected: %x", txId, expectedTxId) 95 t.Errorf("*** GENERATED tx id:\n%s", util.FormatBytes("expectedTxId", txId[:])) 96 t.Fatal("fatal error") 97 } 98 99 // test the unpacker 100 unpacked, n, err := packed.Unpack(true) 101 if nil != err { 102 t.Fatalf("unpack error: %s", err) 103 } 104 if len(packed) != n { 105 t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed)) 106 } 107 108 bmt, ok := unpacked.(*transactionrecord.BitmarkIssue) 109 if !ok { 110 t.Fatalf("did not unpack to BitmarkIssue") 111 } 112 113 // display a JSON version for information 114 item := struct { 115 TxId merkle.Digest 116 BitmarkIssue *transactionrecord.BitmarkIssue 117 }{ 118 txId, 119 bmt, 120 } 121 b, err := json.MarshalIndent(item, "", " ") 122 if nil != err { 123 t.Fatalf("json error: %s", err) 124 } 125 126 t.Logf("Bitmark Issue: JSON: %s", b) 127 128 // check that structure is preserved through Pack/Unpack 129 // note reg is a pointer here 130 if !reflect.DeepEqual(r, *bmt) { 131 t.Fatalf("different, original: %v recovered: %v", r, *bmt) 132 } 133 checkPackedData(t, "issue", packed) 134} 135 136// make 10 separate issues for testing 137// 138// This only prints out 10 valid issue records that can be used for 139// simple testing 140func TestPackTenBitmarkIssues(t *testing.T) { 141 142 issuerAccount := makeAccount(issuer.publicKey) 143 144 var assetId transactionrecord.AssetIdentifier 145 _, err := fmt.Sscan("59d06155d25dffdb982729de8dce9d7855ca094d8bab8124b347c40668477056b3c27ccb7d71b54043d207ccd187642bf9c8466f9a8d0dbefb4c41633a7e39ef", &assetId) 146 if nil != err { 147 t.Fatalf("hex to asset id error: %s", err) 148 } 149 150 rs := make([]*transactionrecord.BitmarkIssue, 10) 151 for i := 0; i < len(rs); i += 1 { 152 r := &transactionrecord.BitmarkIssue{ 153 AssetId: assetId, 154 Owner: issuerAccount, 155 Nonce: uint64(i) + 1, 156 } 157 rs[i] = r 158 159 partial, err := r.Pack(issuerAccount) 160 if fault.InvalidSignature != err { 161 if nil != partial { 162 t.Errorf("partial packed:\n%s", util.FormatBytes("expected", partial)) 163 } 164 t.Fatalf("pack error: %s", err) 165 } 166 signature := ed25519.Sign(issuer.privateKey, partial) 167 r.Signature = signature 168 169 _, err = r.Pack(issuerAccount) 170 if nil != err { 171 t.Fatalf("pack error: %s", err) 172 } 173 } 174 // display a JSON version for information 175 b, err := json.MarshalIndent(rs, "", " ") 176 if nil != err { 177 t.Fatalf("json error: %s", err) 178 } 179 180 t.Logf("Bitmark Issue: JSON: %s", b) 181} 182 183// test the pack failure on trying to use the zero public key 184func TestPackBitmarkIssueWithZeroAccount(t *testing.T) { 185 186 issuerAccount := makeAccount(theZeroKey.publicKey) 187 188 var assetId transactionrecord.AssetIdentifier 189 _, err := fmt.Sscan("59d06155d25dffdb982729de8dce9d7855ca094d8bab8124b347c40668477056b3c27ccb7d71b54043d207ccd187642bf9c8466f9a8d0dbefb4c41633a7e39ef", &assetId) 190 if nil != err { 191 t.Fatalf("hex to asset id error: %s", err) 192 } 193 194 r := transactionrecord.BitmarkIssue{ 195 AssetId: assetId, 196 Owner: issuerAccount, 197 Nonce: 99, 198 Signature: []byte{1, 2, 3, 4}, 199 } 200 201 // test the packer 202 _, err = r.Pack(issuerAccount) 203 if nil == err { 204 t.Fatalf("pack should have failed") 205 } 206 if fault.InvalidOwnerOrRegistrant != err { 207 t.Fatalf("unexpected pack error: %s", err) 208 } 209} 210