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 TestPackBlockFoundation(t *testing.T) { 27 28 proofedByAccount := makeAccount(proofedBy.publicKey) 29 30 r := transactionrecord.BlockFoundation{ 31 Version: 1, 32 Payments: currency.Map{ 33 currency.Bitcoin: "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn", 34 currency.Litecoin: "mmCKZS7toE69QgXNs1JZcjW6LFj8LfUbz6", 35 }, 36 Owner: proofedByAccount, 37 Nonce: 0x12345678, 38 } 39 40 expected := []byte{ 41 0x06, 0x01, 0x48, 0x01, 0x22, 0x6d, 0x69, 0x70, 42 0x63, 0x42, 0x62, 0x46, 0x67, 0x39, 0x67, 0x4d, 43 0x69, 0x43, 0x68, 0x38, 0x31, 0x4b, 0x6a, 0x38, 44 0x74, 0x71, 0x71, 0x64, 0x67, 0x6f, 0x5a, 0x75, 45 0x62, 0x31, 0x5a, 0x4a, 0x52, 0x66, 0x6e, 0x02, 46 0x22, 0x6d, 0x6d, 0x43, 0x4b, 0x5a, 0x53, 0x37, 47 0x74, 0x6f, 0x45, 0x36, 0x39, 0x51, 0x67, 0x58, 48 0x4e, 0x73, 0x31, 0x4a, 0x5a, 0x63, 0x6a, 0x57, 49 0x36, 0x4c, 0x46, 0x6a, 0x38, 0x4c, 0x66, 0x55, 50 0x62, 0x7a, 0x36, 0x21, 0x13, 0x55, 0xb2, 0x98, 51 0x88, 0x17, 0xf7, 0xea, 0xec, 0x37, 0x74, 0x1b, 52 0x82, 0x44, 0x71, 0x63, 0xca, 0xaa, 0x5a, 0x9d, 53 0xb2, 0xb6, 0xf0, 0xce, 0x72, 0x26, 0x26, 0x33, 54 0x8e, 0x5e, 0x3f, 0xd7, 0xf7, 0xf8, 0xac, 0xd1, 55 0x91, 0x01, 56 } 57 58 expectedTxId := merkle.Digest{ 59 0xc6, 0xa6, 0xca, 0x7b, 0xc1, 0xab, 0x3c, 0xac, 60 0x1f, 0x34, 0x5b, 0x2b, 0xa8, 0x1d, 0x20, 0x8d, 61 0x61, 0x65, 0x83, 0xd0, 0x5a, 0x22, 0xd9, 0xcb, 62 0x77, 0x47, 0x2d, 0x9c, 0x22, 0x49, 0x1a, 0x22, 63 } 64 65 // manually sign the record and attach signature to "expected" 66 signature := ed25519.Sign(proofedBy.privateKey, expected) 67 r.Signature = signature 68 //t.Logf("signature: %#v", r.Signature) 69 l := util.ToVarint64(uint64(len(signature))) 70 expected = append(expected, l...) 71 expected = append(expected, signature...) 72 73 // test the packer 74 packed, err := r.Pack(proofedByAccount) 75 if nil != err { 76 if nil != packed { 77 t.Errorf("partial packed:\n%s", util.FormatBytes("expected", packed)) 78 } 79 t.Fatalf("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 // check the record type 90 if transactionrecord.BlockFoundationTag != packed.Type() { 91 t.Fatalf("pack record type: %x expected: %x", packed.Type(), transactionrecord.BlockFoundationTag) 92 } 93 94 t.Logf("Packed length: %d bytes", len(packed)) 95 96 // check txIds 97 txId := packed.MakeLink() 98 99 if txId != expectedTxId { 100 t.Errorf("pack tx id: %#v expected: %#v", txId, expectedTxId) 101 t.Errorf("*** GENERATED tx id:\n%s", util.FormatBytes("expectedTxId", txId[:])) 102 } 103 104 // test the unpacker 105 unpacked, n, err := packed.Unpack(true) 106 if nil != err { 107 t.Fatalf("unpack error: %s", err) 108 } 109 110 if len(packed) != n { 111 t.Errorf("did not unpack all data: only used: %d of: %d bytes", n, len(packed)) 112 } 113 114 blockFoundation, ok := unpacked.(*transactionrecord.BlockFoundation) 115 if !ok { 116 t.Fatalf("did not unpack to BlockFoundation") 117 } 118 119 // display a JSON version for information 120 item := struct { 121 TxId merkle.Digest 122 BlockFoundation *transactionrecord.BlockFoundation 123 }{ 124 TxId: txId, 125 BlockFoundation: blockFoundation, 126 } 127 b, err := json.MarshalIndent(item, "", " ") 128 if nil != err { 129 t.Fatalf("json error: %s", err) 130 } 131 132 t.Logf("BlockFoundation: JSON: %s", b) 133 134 // check that structure is preserved through Pack/Unpack 135 // note reg is a pointer here 136 if !reflect.DeepEqual(r, *blockFoundation) { 137 t.Errorf("different, original: %v recovered: %v", r, *blockFoundation) 138 } 139 checkPackedData(t, "block foundation", packed) 140} 141 142// test the pack failure on trying to use the zero public key 143func TestPackBlockFoundationWithZeroAccount(t *testing.T) { 144 145 proofedByAccount := makeAccount(theZeroKey.publicKey) 146 147 r := transactionrecord.BlockFoundation{ 148 Version: 1, 149 Payments: currency.Map{ 150 currency.Bitcoin: "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn", 151 currency.Litecoin: "mmCKZS7toE69QgXNs1JZcjW6LFj8LfUbz6", 152 }, 153 Owner: proofedByAccount, 154 Nonce: 0x12345678, 155 Signature: []byte{1, 2, 3, 4}, 156 } 157 158 // test the packer 159 _, err := r.Pack(proofedByAccount) 160 if nil == err { 161 t.Fatalf("pack should have failed") 162 } 163 if fault.InvalidOwnerOrRegistrant != err { 164 t.Fatalf("unexpected pack error: %s", err) 165 } 166} 167