Implement Clone and Equal for all model types (#1155)

* [NOD-1575] Implement Clone and Equal for all model types

* [NOD-1575] Add assertion for transaction ID equality

* [NOD-1575] Use DomainTransaction.Equal to compare to expected coinbase transaction

* [NOD-1575] Add TestDomainBlockHeader_Clone

* [NOD-1575] Don't clone nil values

* [NOD-1575] Add type assertions

* [NOD-1575] Don't clone nil values

* [NOD-1575] Add missing Equals

* [NOD-1575] Add length checks

* [NOD-1575] Update comment

* [NOD-1575] Check length for TransactionAcceptanceData

* [NOD-1575] Explicitly clone nils where needed

* [NOD-1575] Clone tx id

* [NOD-1575] Flip condition

* Nod 1576 make coverage tests for equal clone inside model externalapi (#1177)

* [NOD-1576] Make coverage tests for equal and clone inside model and externalapi

* Some formatting and naming fixes

* Made transactionToCompare type exported

* Added some tests and made some changes to the tests code

* No changes made

* Some formatting and naming changes made

* Made better test coverage for externalapi clone and equal functions

* Changed expected result for two cases

* Added equal and clone functions tests for ghostdag and utxodiff

* Added tests

* [NOD-1576] Implement reachabilitydata equal/clone unit tests

* [NOD-1576]  Full coverage of reachabilitydata equal/clone unit tests

* Made changes and handling panic to transaction_equal_clone_test.go and formating of utxodiff_equal_clone_test.go

* Added recoverForEqual2 for handling panic to transaction_equal_clone_test.go

* [NOD-1576]  Full coverage of transaction equal unit test

* [NOD-1576] Add expects panic

* [NOD-1576] Allow composites in go vet

* [NOD-1576] Code review fixes (#1223)

* [NOD-1576] Code review fixes

* [NOD-1576] Code review fixes part 2

* [NOD-1576] Fix wrong name

Co-authored-by: karim1king <karimkaspersky@yahoo.com>
Co-authored-by: Ori Newman <orinewman1@gmail.com>
Co-authored-by: Karim <karim1king@users.noreply.github.com>

* Fix merge errors

* Use Equal where possible

* Use Equal where possible

* Use Equal where possible

Co-authored-by: andrey-hash <74914043+andrey-hash@users.noreply.github.com>
Co-authored-by: karim1king <karimkaspersky@yahoo.com>
Co-authored-by: Karim <karim1king@users.noreply.github.com>
This commit is contained in:
Ori Newman 2020-12-22 17:38:54 +02:00 committed by GitHub
parent c2cec2f170
commit cb9d7e313d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 4346 additions and 174 deletions

View File

@ -71,7 +71,7 @@ func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 {
// Note: this operation modifies the block in place.
func (msg *MsgBlock) ConvertToPartial(subnetworkID *externalapi.DomainSubnetworkID) {
for _, tx := range msg.Transactions {
if tx.SubnetworkID != *subnetworkID {
if !tx.SubnetworkID.Equal(subnetworkID) {
tx.Payload = []byte{}
}
}

View File

@ -110,7 +110,7 @@ func TestConvertToPartial(t *testing.T) {
for _, testTransaction := range transactions {
var subnetworkTx *MsgTx
for _, blockTransaction := range block.Transactions {
if blockTransaction.SubnetworkID == *testTransaction.subnetworkID {
if blockTransaction.SubnetworkID.Equal(testTransaction.subnetworkID) {
subnetworkTx = blockTransaction
}
}

View File

@ -26,7 +26,7 @@ func TestRequstIBDBlocks(t *testing.T) {
// Ensure we get the same data back out.
msg := NewMsgRequstHeaders(lowHash, highHash)
if *msg.HighHash != *highHash {
if !msg.HighHash.Equal(highHash) {
t.Errorf("NewMsgRequstHeaders: wrong high hash - got %v, want %v",
msg.HighHash, highHash)
}

View File

@ -256,8 +256,8 @@ func (msg *MsgTx) MaxPayloadLength(pver uint32) uint32 {
// 3. The transaction's subnetwork
func (msg *MsgTx) IsSubnetworkCompatible(subnetworkID *externalapi.DomainSubnetworkID) bool {
return subnetworkID == nil ||
*subnetworkID == subnetworks.SubnetworkIDNative ||
*subnetworkID == msg.SubnetworkID
subnetworkID.Equal(&subnetworks.SubnetworkIDNative) ||
subnetworkID.Equal(&msg.SubnetworkID)
}
// newMsgTx returns a new tx message that conforms to the Message interface.

View File

@ -53,7 +53,7 @@ func TestTx(t *testing.T) {
// testing package functionality.
prevOutIndex := uint32(1)
prevOut := NewOutpoint(txID, prevOutIndex)
if prevOut.TxID != *txID {
if !prevOut.TxID.Equal(txID) {
t.Errorf("NewOutpoint: wrong ID - got %v, want %v",
spew.Sprint(&prevOut.TxID), spew.Sprint(txID))
}
@ -179,7 +179,7 @@ func TestTxHashAndID(t *testing.T) {
// Ensure the TxID for coinbase transaction is the same as TxHash.
tx1ID := tx1.TxID()
if *tx1ID != *wantTxID1 {
if !tx1ID.Equal(wantTxID1) {
t.Errorf("TxID: wrong ID - got %v, want %v",
spew.Sprint(tx1ID), spew.Sprint(wantTxID1))
}
@ -236,19 +236,19 @@ func TestTxHashAndID(t *testing.T) {
// Ensure the hash produced is expected.
tx2Hash := tx2.TxHash()
if *tx2Hash != *wantHash2 {
if !tx2Hash.Equal(wantHash2) {
t.Errorf("TxHash: wrong hash - got %v, want %v",
spew.Sprint(tx2Hash), spew.Sprint(wantHash2))
}
// Ensure the TxID for coinbase transaction is the same as TxHash.
tx2ID := tx2.TxID()
if *tx2ID != *wantID2 {
if !tx2ID.Equal(wantID2) {
t.Errorf("TxID: wrong ID - got %v, want %v",
spew.Sprint(tx2ID), spew.Sprint(wantID2))
}
if *tx2ID == (externalapi.DomainTransactionID)(*tx2Hash) {
if tx2ID.Equal((*externalapi.DomainTransactionID)(tx2Hash)) {
t.Errorf("tx2ID and tx2Hash shouldn't be the same for non-coinbase transaction with signature and/or payload")
}

View File

@ -130,7 +130,7 @@ func (f *FlowContext) findChildOrphansOfBlock(blockHash *externalapi.DomainHash)
var childOrphans []externalapi.DomainHash
for orphanHash, orphanBlock := range f.orphans {
for _, orphanBlockParentHash := range orphanBlock.Header.ParentHashes {
if *orphanBlockParentHash == *blockHash {
if orphanBlockParentHash.Equal(blockHash) {
childOrphans = append(childOrphans, orphanHash)
break
}

View File

@ -171,7 +171,7 @@ func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHas
block := appmessage.MsgBlockToDomainBlock(msgBlock)
blockHash := consensushashing.BlockHash(block)
if *blockHash != *requestHash {
if !blockHash.Equal(requestHash) {
return nil, false, protocolerrors.Errorf(true, "got unrequested block %s", blockHash)
}

View File

@ -279,7 +279,7 @@ func (flow *handleRelayInvsFlow) syncMissingBlockBodies(highHash *externalapi.Do
block := appmessage.MsgBlockToDomainBlock(msgIBDBlock.MsgBlock)
blockHash := consensushashing.BlockHash(block)
if *expectedHash != *blockHash {
if !expectedHash.Equal(blockHash) {
return protocolerrors.Errorf(true, "expected block %s but got %s", expectedHash, blockHash)
}

View File

@ -90,7 +90,7 @@ func (flow *receiveVersionFlow) start() (*appmessage.NetAddress, error) {
isRemoteNodeFull := msgVersion.SubnetworkID == nil
isOutbound := flow.peer.Connection().IsOutbound()
if (isLocalNodeFull && !isRemoteNodeFull && isOutbound) ||
(!isLocalNodeFull && !isRemoteNodeFull && *msgVersion.SubnetworkID != *localSubnetworkID) {
(!isLocalNodeFull && !isRemoteNodeFull && !msgVersion.SubnetworkID.Equal(localSubnetworkID)) {
return nil, protocolerrors.New(false, "incompatible subnetworks")
}

View File

@ -19,7 +19,7 @@ staticcheck -checks "\
SA4022,SA4023,SA5000,SA5002,SA5004,SA5005,SA5007,SA5008,SA5009,SA5010,SA5011,SA5012,SA6001,SA6002,SA9001,SA9002, \
SA9003,SA9004,SA9005,SA9006,ST1019" ./...
go vet $FLAGS ./...
go vet -composites=false $FLAGS ./...
go build $FLAGS -o kaspad .

View File

@ -171,7 +171,7 @@ func (s *consensus) GetPruningPointUTXOSet(expectedPruningPointHash *externalapi
return nil, err
}
if *expectedPruningPointHash != *pruningPointHash {
if !expectedPruningPointHash.Equal(pruningPointHash) {
return nil, errors.Wrapf(ruleerrors.ErrWrongPruningPointHash, "expected pruning point %s but got %s",
expectedPruningPointHash,
pruningPointHash)

View File

@ -107,7 +107,7 @@ func TestFinality(t *testing.T) {
if err != nil {
t.Fatalf("TestFinality: Failed getting virtual selectedParent: %v", err)
}
if *consensushashing.BlockHash(selectedTip) != *sideChainTipHash {
if !consensushashing.BlockHash(selectedTip).Equal(sideChainTipHash) {
t.Fatalf("Overtaking block in side-chain is not selectedTip")
}
@ -125,7 +125,7 @@ func TestFinality(t *testing.T) {
t.Fatalf("TestFinality: Failed getting the virtual's finality point: %v", err)
}
if *virtualFinality == *params.GenesisHash {
if virtualFinality.Equal(params.GenesisHash) {
t.Fatalf("virtual's finalityPoint is still genesis after adding finalityInterval + 1 blocks to the main chain")
}
@ -309,7 +309,7 @@ func TestBoundedMergeDepth(t *testing.T) {
// Make sure it's actually blue
found := false
for _, blue := range virtualGhotDagData.MergeSetBlues() {
if *blue == *kosherizingBlockHash {
if blue.Equal(kosherizingBlockHash) {
found = true
break
}
@ -329,7 +329,7 @@ func TestBoundedMergeDepth(t *testing.T) {
t.Fatalf("TestBoundedMergeDepth: Failed getting the virtual selected parent %v", err)
}
if *consensushashing.BlockHash(virtualSelectedParent) != *consensushashing.BlockHash(pointAtBlueKosherizing) {
if !consensushashing.BlockHash(virtualSelectedParent).Equal(consensushashing.BlockHash(pointAtBlueKosherizing)) {
t.Fatalf("TestBoundedMergeDepth: Expected %s to be the selectedTip but found %s instead", consensushashing.BlockHash(pointAtBlueKosherizing), consensushashing.BlockHash(virtualSelectedParent))
}
@ -346,7 +346,7 @@ func TestBoundedMergeDepth(t *testing.T) {
t.Fatalf("TestBoundedMergeDepth: Failed getting the virtual selected parent %v", err)
}
if *consensushashing.BlockHash(virtualSelectedParent) != *tip {
if !consensushashing.BlockHash(virtualSelectedParent).Equal(tip) {
t.Fatalf("TestBoundedMergeDepth: Expected %s to be the selectedTip but found %s instead", tip, consensushashing.BlockHash(virtualSelectedParent))
}
@ -357,7 +357,7 @@ func TestBoundedMergeDepth(t *testing.T) {
// Make sure it's actually blue
found = false
for _, blue := range virtualGhotDagData.MergeSetBlues() {
if *blue == *kosherizingBlockHash {
if blue.Equal(kosherizingBlockHash) {
found = true
break
}
@ -382,7 +382,7 @@ func TestBoundedMergeDepth(t *testing.T) {
t.Fatalf("TestBoundedMergeDepth: Failed getting the virtual selected parent %v", err)
}
if *consensushashing.BlockHash(virtualSelectedParent) != *consensushashing.BlockHash(transitiveBlueKosherizing) {
if !consensushashing.BlockHash(virtualSelectedParent).Equal(consensushashing.BlockHash(transitiveBlueKosherizing)) {
t.Fatalf("TestBoundedMergeDepth: Expected %s to be the selectedTip but found %s instead", consensushashing.BlockHash(transitiveBlueKosherizing), consensushashing.BlockHash(virtualSelectedParent))
}

View File

@ -0,0 +1,809 @@
package model_test
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"reflect"
"testing"
)
func initTestTransactionAcceptanceDataForClone() []*externalapi.TransactionAcceptanceData {
tests := []*externalapi.TransactionAcceptanceData{
{
&externalapi.DomainTransaction{
Version: 1,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
},
}
return tests
}
type testTransactionAcceptanceDataToCompare struct {
transactionAcceptanceData *externalapi.TransactionAcceptanceData
expectedResult bool
}
type testTransactionAcceptanceDataStruct struct {
baseTransactionAcceptanceData *externalapi.TransactionAcceptanceData
transactionAcceptanceDataToCompareTo []testTransactionAcceptanceDataToCompare
}
func initTransactionAcceptanceDataForEqual() []testTransactionAcceptanceDataStruct {
var testTransactionAcceptanceDataBase = externalapi.TransactionAcceptanceData{
&externalapi.DomainTransaction{
Version: 1,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}
var testTransactionAcceptanceData1 = externalapi.TransactionAcceptanceData{
&externalapi.DomainTransaction{
Version: 1,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}
// test 2: different transactions
var testTransactionAcceptanceData2 = externalapi.TransactionAcceptanceData{
&externalapi.DomainTransaction{
Version: 2,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}
//test 3: different Fee
var testTransactionAcceptanceData3 = externalapi.TransactionAcceptanceData{
&externalapi.DomainTransaction{
Version: 1,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
2,
true,
}
//test 4: different isAccepted
var testTransactionAcceptanceData4 = externalapi.TransactionAcceptanceData{
&externalapi.DomainTransaction{
Version: 1,
Inputs: []*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
Outputs: []*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
LockTime: 1,
SubnetworkID: externalapi.DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
false,
}
tests := []testTransactionAcceptanceDataStruct{
{
baseTransactionAcceptanceData: &testTransactionAcceptanceDataBase,
transactionAcceptanceDataToCompareTo: []testTransactionAcceptanceDataToCompare{
{
transactionAcceptanceData: &testTransactionAcceptanceData1,
expectedResult: true,
}, {
transactionAcceptanceData: &testTransactionAcceptanceData2,
expectedResult: false,
}, {
transactionAcceptanceData: &testTransactionAcceptanceData3,
expectedResult: false,
}, {
transactionAcceptanceData: &testTransactionAcceptanceData4,
expectedResult: false,
}, {
transactionAcceptanceData: nil,
expectedResult: false,
},
},
}, {
baseTransactionAcceptanceData: nil,
transactionAcceptanceDataToCompareTo: []testTransactionAcceptanceDataToCompare{
{
transactionAcceptanceData: &testTransactionAcceptanceData1,
expectedResult: false,
}, {
transactionAcceptanceData: nil,
expectedResult: true,
},
},
},
}
return tests
}
func TestTransactionAcceptanceData_Equal(t *testing.T) {
acceptanceData := initTransactionAcceptanceDataForEqual()
for i, test := range acceptanceData {
for j, subTest := range test.transactionAcceptanceDataToCompareTo {
result1 := test.baseTransactionAcceptanceData.Equal(subTest.transactionAcceptanceData)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.transactionAcceptanceData.Equal(test.baseTransactionAcceptanceData)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestTransactionAcceptanceData_Clone(t *testing.T) {
testTransactionAcceptanceData := initTestTransactionAcceptanceDataForClone()
for i, transactionAcceptanceData := range testTransactionAcceptanceData {
transactionAcceptanceDataClone := transactionAcceptanceData.Clone()
if !transactionAcceptanceDataClone.Equal(transactionAcceptanceData) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(transactionAcceptanceData, transactionAcceptanceDataClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}
func initTestBlockAcceptanceDataForClone() []*externalapi.BlockAcceptanceData {
tests := []*externalapi.BlockAcceptanceData{{&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{
{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}},
},
}
return tests
}
type testBlockAcceptanceDataToCompare struct {
blockAcceptanceData *externalapi.BlockAcceptanceData
expectedResult bool
}
type testBlockAcceptanceDataStruct struct {
baseBlockAcceptanceData *externalapi.BlockAcceptanceData
blockAcceptanceDataToCompareTo []testBlockAcceptanceDataToCompare
}
func iniBlockAcceptanceDataForEqual() []testBlockAcceptanceDataStruct {
var testBlockAcceptanceDataBase = externalapi.BlockAcceptanceData{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}
//test 1: structs are equal
var testBlockAcceptanceData1 = externalapi.BlockAcceptanceData{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}
// test 2: different size
var testBlockAcceptanceData2 = externalapi.BlockAcceptanceData{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}, {}}}
//test 3: different transactions, same size
var testBlockAcceptanceData3 = externalapi.BlockAcceptanceData{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
false,
}}}
// test 4 - different block hash
var testBlockAcceptanceData4 = externalapi.BlockAcceptanceData{
&externalapi.DomainHash{2},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}
tests := []testBlockAcceptanceDataStruct{
{
baseBlockAcceptanceData: &testBlockAcceptanceDataBase,
blockAcceptanceDataToCompareTo: []testBlockAcceptanceDataToCompare{
{
blockAcceptanceData: &testBlockAcceptanceData1,
expectedResult: true,
}, {
blockAcceptanceData: &testBlockAcceptanceData2,
expectedResult: false,
}, {
blockAcceptanceData: &testBlockAcceptanceData3,
expectedResult: false,
}, {
blockAcceptanceData: nil,
expectedResult: false,
},
{
blockAcceptanceData: &testBlockAcceptanceData4,
expectedResult: false,
},
},
}, {
baseBlockAcceptanceData: nil,
blockAcceptanceDataToCompareTo: []testBlockAcceptanceDataToCompare{
{
blockAcceptanceData: &testBlockAcceptanceData1,
expectedResult: false,
}, {
blockAcceptanceData: nil,
expectedResult: true,
},
},
},
}
return tests
}
func TestBlockAcceptanceData_Equal(t *testing.T) {
blockAcceptances := iniBlockAcceptanceDataForEqual()
for i, test := range blockAcceptances {
for j, subTest := range test.blockAcceptanceDataToCompareTo {
result1 := test.baseBlockAcceptanceData.Equal(subTest.blockAcceptanceData)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.blockAcceptanceData.Equal(test.baseBlockAcceptanceData)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestBlockAcceptanceData_Clone(t *testing.T) {
testBlockAcceptanceData := initTestBlockAcceptanceDataForClone()
for i, blockAcceptanceData := range testBlockAcceptanceData {
blockAcceptanceDataClone := blockAcceptanceData.Clone()
if !blockAcceptanceDataClone.Equal(blockAcceptanceData) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(blockAcceptanceData, blockAcceptanceDataClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}
func initTestAcceptanceDataForClone() []externalapi.AcceptanceData {
test1 := []*externalapi.BlockAcceptanceData{{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{
{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}},
},
}
tests := []externalapi.AcceptanceData{test1, test1}
return tests
}
type testAcceptanceDataToCompare struct {
acceptanceData externalapi.AcceptanceData
expectedResult bool
}
type testAcceptanceDataStruct struct {
baseAcceptanceData externalapi.AcceptanceData
acceptanceDataToCompareTo []testAcceptanceDataToCompare
}
func initAcceptanceDataForEqual() []testAcceptanceDataStruct {
var testAcceptanceDataBase = []*externalapi.BlockAcceptanceData{
{
&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}}
//test 1: structs are equal
var testAcceptanceData1 = []*externalapi.BlockAcceptanceData{
{&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}}
// test 2: different size
var testAcceptanceData2 = []*externalapi.BlockAcceptanceData{
{&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
1,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}, {}}
//test 3: different transactions, same size
var testAcceptanceData3 = []*externalapi.BlockAcceptanceData{
{&externalapi.DomainHash{1},
[]*externalapi.TransactionAcceptanceData{{
&externalapi.DomainTransaction{
2,
[]*externalapi.DomainTransactionInput{{
externalapi.DomainOutpoint{
externalapi.DomainTransactionID{0x01}, 0xFFFF},
[]byte{1, 2, 3},
uint64(0xFFFFFFFF),
utxo.NewUTXOEntry(1, []byte{0, 1, 2, 3}, true, 2)}},
[]*externalapi.DomainTransactionOutput{{uint64(0xFFFF),
[]byte{1, 2}},
{uint64(0xFFFF),
[]byte{1, 3}}},
1,
externalapi.DomainSubnetworkID{0x01},
1,
externalapi.DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
[]byte{0x01},
0,
1,
&externalapi.DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
},
1,
true,
}}}}
tests := []testAcceptanceDataStruct{
{
baseAcceptanceData: testAcceptanceDataBase,
acceptanceDataToCompareTo: []testAcceptanceDataToCompare{
{
acceptanceData: testAcceptanceData1,
expectedResult: true,
}, {
acceptanceData: testAcceptanceData2,
expectedResult: false,
}, {
acceptanceData: testAcceptanceData3,
expectedResult: false,
},
},
},
}
return tests
}
func TestAcceptanceData_Equal(t *testing.T) {
acceptances := initAcceptanceDataForEqual()
for i, test := range acceptances {
for j, subTest := range test.acceptanceDataToCompareTo {
result1 := test.baseAcceptanceData.Equal(subTest.acceptanceData)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.acceptanceData.Equal(test.baseAcceptanceData)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestAcceptanceData_Clone(t *testing.T) {
testAcceptanceData := initTestAcceptanceDataForClone()
for i, acceptanceData := range testAcceptanceData {
acceptanceDataClone := acceptanceData.Clone()
if !acceptanceDataClone.Equal(acceptanceData) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(acceptanceData, acceptanceDataClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -10,12 +10,29 @@ type BlockRelations struct {
// Clone returns a clone of BlockRelations
func (br *BlockRelations) Clone() *BlockRelations {
if br == nil {
return nil
}
return &BlockRelations{
Parents: externalapi.CloneHashes(br.Parents),
Children: externalapi.CloneHashes(br.Children),
}
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &BlockRelations{[]*externalapi.DomainHash{}, []*externalapi.DomainHash{}}
// Equal returns whether br equals to other
func (br *BlockRelations) Equal(other *BlockRelations) bool {
if br == nil || other == nil {
return br == other
}
if !externalapi.HashesEqual(br.Parents, other.Parents) {
return false
}
if !externalapi.HashesEqual(br.Children, other.Children) {
return false
}
return true
}

View File

@ -0,0 +1,115 @@
package model
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"reflect"
"testing"
)
func initTestBlockRelationsForClone() []*BlockRelations {
tests := []*BlockRelations{
{
[]*externalapi.DomainHash{{1}, {2}},
[]*externalapi.DomainHash{{3}, {4}},
},
}
return tests
}
type testBlockRelationsToCompare struct {
blockRelations *BlockRelations
expectedResult bool
}
type testBlockRelationsStruct struct {
baseBlockRelations *BlockRelations
blockRelationsToCompareTo []testBlockRelationsToCompare
}
func initTestBlockRelationsForEqual() []testBlockRelationsStruct {
var testBlockRelationsBase = BlockRelations{
[]*externalapi.DomainHash{{1}, {2}},
[]*externalapi.DomainHash{{3}, {4}},
}
//First test: structs are equal
var testBlockRelations1 = BlockRelations{
[]*externalapi.DomainHash{{1}, {2}},
[]*externalapi.DomainHash{{3}, {4}},
}
//Second test: children changed
var testBlockRelations2 = BlockRelations{
[]*externalapi.DomainHash{{1}, {2}},
[]*externalapi.DomainHash{{3}, {5}},
}
//Third test: parents changed
var testBlockRelations3 = BlockRelations{
[]*externalapi.DomainHash{{6}, {2}},
[]*externalapi.DomainHash{{3}, {4}},
}
tests := []testBlockRelationsStruct{
{
baseBlockRelations: &testBlockRelationsBase,
blockRelationsToCompareTo: []testBlockRelationsToCompare{
{
blockRelations: &testBlockRelations1,
expectedResult: true,
}, {
blockRelations: &testBlockRelations2,
expectedResult: false,
}, {
blockRelations: &testBlockRelations3,
expectedResult: false,
}, {
blockRelations: nil,
expectedResult: false,
},
},
}, {
baseBlockRelations: nil,
blockRelationsToCompareTo: []testBlockRelationsToCompare{
{
blockRelations: &testBlockRelations1,
expectedResult: false,
}, {
blockRelations: nil,
expectedResult: true,
},
},
},
}
return tests
}
func TestBlockRelationsData_Equal(t *testing.T) {
blockRelationss := initTestBlockRelationsForEqual()
for i, test := range blockRelationss {
for j, subTest := range test.blockRelationsToCompareTo {
result1 := test.baseBlockRelations.Equal(subTest.blockRelations)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.blockRelations.Equal(test.baseBlockRelations)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestBlockRelations_Clone(t *testing.T) {
testBlockRelations := initTestBlockRelationsForClone()
for i, blockRelations := range testBlockRelations {
blockRelationsClone := blockRelations.Clone()
if !blockRelationsClone.Equal(blockRelations) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(blockRelations, blockRelationsClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -4,11 +4,27 @@ package externalapi
// It's ordered in the same way as the block merge set blues.
type AcceptanceData []*BlockAcceptanceData
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ AcceptanceData = []*BlockAcceptanceData{}
// Equal returns whether ad equals to other
func (ad AcceptanceData) Equal(other AcceptanceData) bool {
if len(ad) != len(other) {
return false
}
for i, blockAcceptanceData := range ad {
if !blockAcceptanceData.Equal(other[i]) {
return false
}
}
return true
}
// Clone clones the AcceptanceData
func (ad AcceptanceData) Clone() AcceptanceData {
if ad == nil {
return nil
}
clone := make(AcceptanceData, len(ad))
for i, blockAcceptanceData := range ad {
clone[i] = blockAcceptanceData.Clone()
@ -24,6 +40,33 @@ type BlockAcceptanceData struct {
TransactionAcceptanceData []*TransactionAcceptanceData
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &BlockAcceptanceData{&DomainHash{}, []*TransactionAcceptanceData{}}
// Equal returns whether bad equals to other
func (bad *BlockAcceptanceData) Equal(other *BlockAcceptanceData) bool {
if bad == nil || other == nil {
return bad == other
}
if !bad.BlockHash.Equal(other.BlockHash) {
return false
}
if len(bad.TransactionAcceptanceData) != len(other.TransactionAcceptanceData) {
return false
}
for i, acceptanceData := range bad.TransactionAcceptanceData {
if !acceptanceData.Equal(other.TransactionAcceptanceData[i]) {
return false
}
}
return true
}
// Clone returns a clone of BlockAcceptanceData
func (bad *BlockAcceptanceData) Clone() *BlockAcceptanceData {
if bad == nil {
@ -49,12 +92,33 @@ type TransactionAcceptanceData struct {
IsAccepted bool
}
// Clone returns a clone of TransactionAcceptanceData
func (tad *TransactionAcceptanceData) Clone() *TransactionAcceptanceData {
if tad == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &TransactionAcceptanceData{&DomainTransaction{}, 0, false}
// Equal returns whether tad equals to other
func (tad *TransactionAcceptanceData) Equal(other *TransactionAcceptanceData) bool {
if tad == nil || other == nil {
return tad == other
}
if !tad.Transaction.Equal(other.Transaction) {
return false
}
if tad.Fee != other.Fee {
return false
}
if tad.IsAccepted != other.IsAccepted {
return false
}
return true
}
// Clone returns a clone of TransactionAcceptanceData
func (tad *TransactionAcceptanceData) Clone() *TransactionAcceptanceData {
return &TransactionAcceptanceData{
Transaction: tad.Transaction.Clone(),
Fee: tad.Fee,

View File

@ -8,10 +8,6 @@ type DomainBlock struct {
// Clone returns a clone of DomainBlock
func (block *DomainBlock) Clone() *DomainBlock {
if block == nil {
return nil
}
transactionClone := make([]*DomainTransaction, len(block.Transactions))
for i, tx := range block.Transactions {
transactionClone[i] = tx.Clone()
@ -23,6 +19,33 @@ func (block *DomainBlock) Clone() *DomainBlock {
}
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = DomainBlock{&DomainBlockHeader{}, []*DomainTransaction{}}
// Equal returns whether block equals to other
func (block *DomainBlock) Equal(other *DomainBlock) bool {
if block == nil || other == nil {
return block == other
}
if len(block.Transactions) != len(other.Transactions) {
return false
}
if !block.Header.Equal(other.Header) {
return false
}
for i, tx := range block.Transactions {
if !tx.Equal(other.Transactions[i]) {
return false
}
}
return true
}
// DomainBlockHeader represents the header part of a Kaspa block
type DomainBlockHeader struct {
Version int32
@ -37,10 +60,6 @@ type DomainBlockHeader struct {
// Clone returns a clone of DomainBlockHeader
func (header *DomainBlockHeader) Clone() *DomainBlockHeader {
if header == nil {
return nil
}
return &DomainBlockHeader{
Version: header.Version,
ParentHashes: CloneHashes(header.ParentHashes),
@ -52,3 +71,49 @@ func (header *DomainBlockHeader) Clone() *DomainBlockHeader {
Nonce: header.Nonce,
}
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &DomainBlockHeader{0, []*DomainHash{}, DomainHash{},
DomainHash{}, DomainHash{}, 0, 0, 0}
// Equal returns whether header equals to other
func (header *DomainBlockHeader) Equal(other *DomainBlockHeader) bool {
if header == nil || other == nil {
return header == other
}
if header.Version != other.Version {
return false
}
if !HashesEqual(header.ParentHashes, other.ParentHashes) {
return false
}
if !header.HashMerkleRoot.Equal(&other.HashMerkleRoot) {
return false
}
if !header.AcceptedIDMerkleRoot.Equal(&other.AcceptedIDMerkleRoot) {
return false
}
if !header.UTXOCommitment.Equal(&other.UTXOCommitment) {
return false
}
if header.TimeInMilliseconds != other.TimeInMilliseconds {
return false
}
if header.Bits != other.Bits {
return false
}
if header.Nonce != other.Nonce {
return false
}
return true
}

View File

@ -0,0 +1,375 @@
package externalapi
import (
"reflect"
"testing"
)
type blockToCompare struct {
block *DomainBlock
expectedResult bool
}
type TestBlockStruct struct {
baseBlock *DomainBlock
blocksToCompareTo []blockToCompare
}
func initTestBaseTransactions() []*DomainTransaction {
testTx := []*DomainTransaction{{
Version: 1,
Inputs: []*DomainTransactionInput{},
Outputs: []*DomainTransactionOutput{},
LockTime: 1,
SubnetworkID: DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
}}
return testTx
}
func initTestAnotherTransactions() []*DomainTransaction {
testTx := []*DomainTransaction{{
Version: 1,
Inputs: []*DomainTransactionInput{},
Outputs: []*DomainTransactionOutput{},
LockTime: 1,
SubnetworkID: DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
}}
return testTx
}
func initTestTwoTransactions() []*DomainTransaction {
testTx := []*DomainTransaction{{
Version: 1,
Inputs: []*DomainTransactionInput{},
Outputs: []*DomainTransactionOutput{},
LockTime: 1,
SubnetworkID: DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
}, {
Version: 1,
Inputs: []*DomainTransactionInput{},
Outputs: []*DomainTransactionOutput{},
LockTime: 1,
SubnetworkID: DomainSubnetworkID{0x01},
Gas: 1,
PayloadHash: DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
Payload: []byte{0x01},
Fee: 0,
Mass: 1,
ID: &DomainTransactionID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
}}
return testTx
}
func initTestBlockStructsForClone() []*DomainBlock {
tests := []*DomainBlock{
{
&DomainBlockHeader{
0,
[]*DomainHash{{0}},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
initTestBaseTransactions(),
}, {
&DomainBlockHeader{
0,
[]*DomainHash{},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
initTestBaseTransactions(),
},
}
return tests
}
func initTestBlockStructsForEqual() *[]TestBlockStruct {
tests := []TestBlockStruct{
{
baseBlock: nil,
blocksToCompareTo: []blockToCompare{
{
block: nil,
expectedResult: true,
},
{
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{0}},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
initTestBaseTransactions()},
expectedResult: false,
},
},
}, {
baseBlock: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestBaseTransactions(),
},
blocksToCompareTo: []blockToCompare{
{
block: nil,
expectedResult: false,
},
{
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestAnotherTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: true,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}, {2}}, // Changed
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{100}}, // Changed
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestTwoTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{100}, // Changed
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{100}, // Changed
DomainHash{4},
5,
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{100}, // Changed
5,
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
100, // Changed
6,
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
100, // Changed
7,
},
initTestBaseTransactions(),
},
expectedResult: false,
}, {
block: &DomainBlock{
&DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
100, // Changed
},
initTestBaseTransactions(),
},
expectedResult: false,
},
},
},
}
return &tests
}
func TestDomainBlock_Equal(t *testing.T) {
blockTests := initTestBlockStructsForEqual()
for i, test := range *blockTests {
for j, subTest := range test.blocksToCompareTo {
result1 := test.baseBlock.Equal(subTest.block)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.block.Equal(test.baseBlock)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestDomainBlock_Clone(t *testing.T) {
blocks := initTestBlockStructsForClone()
for i, block := range blocks {
blockClone := block.Clone()
if !blockClone.Equal(block) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(block, blockClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -6,3 +6,12 @@ type BlockInfo struct {
BlockStatus BlockStatus
BlueScore uint64
}
// Clone returns a clone of BlockInfo
func (bi *BlockInfo) Clone() *BlockInfo {
return &BlockInfo{
Exists: bi.Exists,
BlockStatus: bi.BlockStatus.Clone(),
BlueScore: bi.BlueScore,
}
}

View File

@ -0,0 +1,45 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestBlockInfoStructsForClone() []*BlockInfo {
tests := []*BlockInfo{
{
true,
BlockStatus(0x01),
0,
}, {
true,
BlockStatus(0x02),
0,
}, {
true,
1,
1,
}, {
true,
255,
2,
}, {
true,
0,
3,
},
}
return tests
}
func TestBlockInfo_Clone(t *testing.T) {
blockInfos := initTestBlockInfoStructsForClone()
for i, blockInfo := range blockInfos {
blockInfoClone := blockInfo.Clone()
if !reflect.DeepEqual(blockInfo, blockInfoClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -15,3 +15,8 @@ package externalapi
// The block locator for block 17 would be the hashes of blocks:
// [17 16 14 11 7 2 genesis]
type BlockLocator []*DomainHash
// Clone returns a clone of BlockLocator
func (locator BlockLocator) Clone() BlockLocator {
return CloneHashes(locator)
}

View File

@ -0,0 +1,67 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestBlockLocatorForClone() []*BlockLocator {
tests := []*BlockLocator{{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
}, {
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1, 1},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2, 1},
},
}
return tests
}
func TestBlockLocator_Clone(t *testing.T) {
testBlockLocator := initTestBlockLocatorForClone()
for i, blockLocator := range testBlockLocator {
blockLocatorClone := blockLocator.Clone()
if !reflect.DeepEqual(blockLocator, &blockLocatorClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -8,6 +8,15 @@ func (bs BlockStatus) Clone() BlockStatus {
return bs
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ BlockStatus = 0
// Equal returns whether bs equals to other
func (bs BlockStatus) Equal(other BlockStatus) bool {
return bs == other
}
const (
// StatusInvalid indicates that the block is invalid.
StatusInvalid BlockStatus = iota

View File

@ -0,0 +1,87 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestBlockStatusForClone() []BlockStatus {
tests := []BlockStatus{1, 2, 0xFF, 0}
return tests
}
type TestBlockStatusToCompare struct {
blockStatus BlockStatus
expectedResult bool
}
type TestBlockStatusStruct struct {
baseBlockStatus BlockStatus
blockStatusesToCompareTo []TestBlockStatusToCompare
}
func initTestBlockStatusForEqual() []TestBlockStatusStruct {
tests := []TestBlockStatusStruct{
{
baseBlockStatus: 0,
blockStatusesToCompareTo: []TestBlockStatusToCompare{
{
blockStatus: 1,
expectedResult: false,
},
{
blockStatus: 0,
expectedResult: true,
},
},
}, {
baseBlockStatus: 255,
blockStatusesToCompareTo: []TestBlockStatusToCompare{
{
blockStatus: 1,
expectedResult: false,
},
{
blockStatus: 255,
expectedResult: true,
},
},
},
}
return tests
}
func TestBlockStatus_Equal(t *testing.T) {
testBlockStatus := initTestBlockStatusForEqual()
for i, test := range testBlockStatus {
for j, subTest := range test.blockStatusesToCompareTo {
result1 := test.baseBlockStatus.Equal(subTest.blockStatus)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.blockStatus.Equal(test.baseBlockStatus)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestBlockStatus_Clone(t *testing.T) {
testBlockStatus := initTestBlockStatusForClone()
for i, blockStatus := range testBlockStatus {
blockStatusClone := blockStatus.Clone()
if !blockStatusClone.Equal(blockStatus) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(blockStatus, blockStatusClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -6,3 +6,17 @@ type DomainCoinbaseData struct {
ScriptPublicKey []byte
ExtraData []byte
}
// Clone returns a clone of DomainCoinbaseData
func (dcd *DomainCoinbaseData) Clone() *DomainCoinbaseData {
scriptPubKeyClone := make([]byte, len(dcd.ScriptPublicKey))
copy(scriptPubKeyClone, dcd.ScriptPublicKey)
extraDataClone := make([]byte, len(dcd.ExtraData))
copy(extraDataClone, dcd.ExtraData)
return &DomainCoinbaseData{
ScriptPublicKey: scriptPubKeyClone,
ExtraData: extraDataClone,
}
}

View File

@ -0,0 +1,59 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestCoinbaseDataStructsForClone() []*DomainCoinbaseData {
tests := []*DomainCoinbaseData{
{
[]byte{1, 2, 3, 4, 5, 6},
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
}, {
[]byte{0, 0, 0, 0, 55},
[]byte{0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF},
},
}
return tests
}
func TestDomainCoinbaseData_Clone(t *testing.T) {
coinbaseData := initTestCoinbaseDataStructsForClone()
for i, coinbase := range coinbaseData {
coinbaseClone := coinbase.Clone()
if !reflect.DeepEqual(coinbase, coinbaseClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -0,0 +1,238 @@
package externalapi
import (
"reflect"
"testing"
)
func TestDomainBlockHeader_Equal(t *testing.T) {
type headerToCompare struct {
header *DomainBlockHeader
expectedResult bool
}
tests := []struct {
baseHeader *DomainBlockHeader
headersToCompareTo []headerToCompare
}{
{
baseHeader: nil,
headersToCompareTo: []headerToCompare{
{
header: nil,
expectedResult: true,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{0}},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
expectedResult: false,
},
},
},
{
baseHeader: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
headersToCompareTo: []headerToCompare{
{
header: nil,
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
expectedResult: true,
},
{
header: &DomainBlockHeader{
100,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}, {2}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{100}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{100},
DomainHash{3},
DomainHash{4},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{100},
DomainHash{4},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{100},
5,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
100,
6,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
100,
7,
},
expectedResult: false,
},
{
header: &DomainBlockHeader{
0,
[]*DomainHash{{1}},
DomainHash{2},
DomainHash{3},
DomainHash{4},
5,
6,
100,
},
expectedResult: false,
},
},
},
}
for i, test := range tests {
for j, subTest := range test.headersToCompareTo {
result1 := test.baseHeader.Equal(subTest.header)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.header.Equal(test.baseHeader)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestDomainBlockHeader_Clone(t *testing.T) {
headers := []*DomainBlockHeader{
{
0,
[]*DomainHash{{0}},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
{
0,
[]*DomainHash{},
DomainHash{1},
DomainHash{2},
DomainHash{3},
4,
5,
6,
},
}
for i, header := range headers {
clone := header.Clone()
if !clone.Equal(header) {
t.Fatalf("Test #%d: clone should be equal to the original", i)
}
if !reflect.DeepEqual(header, clone) {
t.Fatalf("Test #%d: clone should be equal to the original", i)
}
}
}

View File

@ -19,14 +19,37 @@ func (hash DomainHash) String() string {
// Clone clones the hash
func (hash *DomainHash) Clone() *DomainHash {
if hash == nil {
return nil
}
hashClone := *hash
return &hashClone
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ DomainHash = [DomainHashSize]byte{}
// Equal returns whether hash equals to other
func (hash *DomainHash) Equal(other *DomainHash) bool {
if hash == nil || other == nil {
return hash == other
}
return *hash == *other
}
// HashesEqual returns whether the given hash slices are equal.
func HashesEqual(a, b []*DomainHash) bool {
if len(a) != len(b) {
return false
}
for i, hash := range a {
if !hash.Equal(b[i]) {
return false
}
}
return true
}
// CloneHashes returns a clone of the given hashes slice
func CloneHashes(hashes []*DomainHash) []*DomainHash {
clone := make([]*DomainHash, len(hashes))

View File

@ -0,0 +1,119 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestDomainHashForClone() []*DomainHash {
tests := []*DomainHash{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
}
return tests
}
type testHashToCompare struct {
hash *DomainHash
expectedResult bool
}
type testHashStruct struct {
baseHash *DomainHash
hashesToCompareTo []testHashToCompare
}
func initTestDomainHashForEqual() []*testHashStruct {
tests := []*testHashStruct{
{
baseHash: nil,
hashesToCompareTo: []testHashToCompare{
{
hash: nil,
expectedResult: true,
}, {
hash: &DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
expectedResult: false,
},
},
}, {
baseHash: &DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
hashesToCompareTo: []testHashToCompare{
{
hash: nil,
expectedResult: false,
}, {
hash: &DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
expectedResult: false,
}, {
hash: &DomainHash{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
expectedResult: true,
},
},
},
}
return tests
}
func TestDomainHash_Equal(t *testing.T) {
hashTests := initTestDomainHashForEqual()
for i, test := range hashTests {
for j, subTest := range test.hashesToCompareTo {
result1 := test.baseHash.Equal(subTest.hash)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.hash.Equal(test.baseHash)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestDomainHash_Clone(t *testing.T) {
hashes := initTestDomainHashForClone()
for i, hash := range hashes {
hashClone := hash.Clone()
if !hashClone.Equal(hash) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(hash, hashClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -18,10 +18,19 @@ func (id DomainSubnetworkID) String() string {
// Clone returns a clone of DomainSubnetworkID
func (id *DomainSubnetworkID) Clone() *DomainSubnetworkID {
if id == nil {
return nil
}
idClone := *id
return &idClone
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ DomainSubnetworkID = [DomainSubnetworkIDSize]byte{}
// Equal returns whether id equals to other
func (id *DomainSubnetworkID) Equal(other *DomainSubnetworkID) bool {
if id == nil || other == nil {
return id == other
}
return *id == *other
}

View File

@ -0,0 +1,99 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestDomainSubnetworkIDForClone() []*DomainSubnetworkID {
tests := []*DomainSubnetworkID{{1, 0, 0xFF, 0}, {0, 1, 0xFF, 1},
{0, 1, 0xFF, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}
return tests
}
type testDomainSubnetworkIDToCompare struct {
domainSubnetworkID *DomainSubnetworkID
expectedResult bool
}
type testDomainSubnetworkIDStruct struct {
baseDomainSubnetworkID *DomainSubnetworkID
domainSubnetworkIDToCompareTo []testDomainSubnetworkIDToCompare
}
func initTestDomainSubnetworkIDForEqual() []testDomainSubnetworkIDStruct {
tests := []testDomainSubnetworkIDStruct{
{
baseDomainSubnetworkID: nil,
domainSubnetworkIDToCompareTo: []testDomainSubnetworkIDToCompare{
{
domainSubnetworkID: &DomainSubnetworkID{255, 255, 0xFF, 0},
expectedResult: false,
},
{
domainSubnetworkID: nil,
expectedResult: true,
},
},
}, {
baseDomainSubnetworkID: &DomainSubnetworkID{0},
domainSubnetworkIDToCompareTo: []testDomainSubnetworkIDToCompare{
{
domainSubnetworkID: &DomainSubnetworkID{255, 254, 0xFF, 0},
expectedResult: false,
},
{
domainSubnetworkID: &DomainSubnetworkID{0},
expectedResult: true,
},
},
}, {
baseDomainSubnetworkID: &DomainSubnetworkID{0, 1, 0xFF, 1, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
domainSubnetworkIDToCompareTo: []testDomainSubnetworkIDToCompare{
{
domainSubnetworkID: &DomainSubnetworkID{0, 1, 0xFF, 1, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
expectedResult: true,
},
{
domainSubnetworkID: &DomainSubnetworkID{0, 10, 0xFF, 0},
expectedResult: false,
},
},
},
}
return tests
}
func TestDomainSubnetworkID_Equal(t *testing.T) {
domainSubnetworkIDs := initTestDomainSubnetworkIDForEqual()
for i, test := range domainSubnetworkIDs {
for j, subTest := range test.domainSubnetworkIDToCompareTo {
result1 := test.baseDomainSubnetworkID.Equal(subTest.domainSubnetworkID)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.domainSubnetworkID.Equal(test.baseDomainSubnetworkID)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestDomainSubnetworkID_Clone(t *testing.T) {
domainSubnetworkIDs := initTestDomainSubnetworkIDForClone()
for i, domainSubnetworkID := range domainSubnetworkIDs {
domainSubnetworkIDClone := domainSubnetworkID.Clone()
if !domainSubnetworkIDClone.Equal(domainSubnetworkID) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(domainSubnetworkID, domainSubnetworkIDClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -7,3 +7,42 @@ type SyncInfo struct {
HeaderCount uint64
BlockCount uint64
}
// Clone returns a clone of SyncInfo
func (si *SyncInfo) Clone() *SyncInfo {
return &SyncInfo{
IsAwaitingUTXOSet: si.IsAwaitingUTXOSet,
IBDRootUTXOBlockHash: si.IBDRootUTXOBlockHash.Clone(),
HeaderCount: si.HeaderCount,
BlockCount: si.BlockCount,
}
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = SyncInfo{false, &DomainHash{}, 0, 0}
// Equal returns whether si equals to other
func (si *SyncInfo) Equal(other *SyncInfo) bool {
if si == nil || other == nil {
return si == other
}
if si.IsAwaitingUTXOSet != other.IsAwaitingUTXOSet {
return false
}
if !si.IBDRootUTXOBlockHash.Equal(other.IBDRootUTXOBlockHash) {
return false
}
if si.HeaderCount != other.HeaderCount {
return false
}
if si.BlockCount != other.BlockCount {
return false
}
return true
}

View File

@ -0,0 +1,126 @@
package externalapi
import (
"reflect"
"testing"
)
func initTestSyncInfoForClone() []*SyncInfo {
tests := []*SyncInfo{{
false,
&DomainHash{1, 2},
0xF,
0xF}}
return tests
}
type testSyncInfoToCompare struct {
syncInfo *SyncInfo
expectedResult bool
}
type testSyncInfoStruct struct {
baseSyncInfo *SyncInfo
syncInfoToCompareTo []testSyncInfoToCompare
}
func initTestSyncInfoForEqual() []*testSyncInfoStruct {
tests := []*testSyncInfoStruct{
{
baseSyncInfo: nil,
syncInfoToCompareTo: []testSyncInfoToCompare{
{
syncInfo: &SyncInfo{
false,
&DomainHash{1, 2},
0xF,
0xF},
expectedResult: false,
}, {
syncInfo: nil,
expectedResult: true,
},
}}, {
baseSyncInfo: &SyncInfo{
false,
&DomainHash{1, 2},
0xF,
0xF},
syncInfoToCompareTo: []testSyncInfoToCompare{
{
syncInfo: &SyncInfo{
false,
&DomainHash{1, 2},
0xF,
0xF},
expectedResult: true,
}, {
syncInfo: &SyncInfo{
true,
&DomainHash{1, 2},
0xF,
0xF},
expectedResult: false,
},
{
syncInfo: &SyncInfo{
false,
&DomainHash{1, 3},
0xF,
0xF},
expectedResult: false,
},
{
syncInfo: &SyncInfo{
false,
&DomainHash{1, 2},
0xF1,
0xF},
expectedResult: false,
}, {
syncInfo: nil,
expectedResult: false,
}, {
syncInfo: &SyncInfo{
false,
&DomainHash{1, 2},
0xF,
0xF1},
expectedResult: false},
},
},
}
return tests
}
func TestSyncInfo_Equal(t *testing.T) {
testSyncState := initTestSyncInfoForEqual()
for i, test := range testSyncState {
for j, subTest := range test.syncInfoToCompareTo {
result1 := test.baseSyncInfo.Equal(subTest.syncInfo)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.syncInfo.Equal(test.baseSyncInfo)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestSyncInfo_Clone(t *testing.T) {
testSyncInfo := initTestSyncInfoForClone()
for i, syncInfo := range testSyncInfo {
syncStateClone := syncInfo.Clone()
if !syncStateClone.Equal(syncInfo) {
t.Fatalf("Test #%d:[Equal] clone should be equal to the original", i)
}
if !reflect.DeepEqual(syncInfo, syncStateClone) {
t.Fatalf("Test #%d:[DeepEqual] clone should be equal to the original", i)
}
}
}

View File

@ -1,7 +1,9 @@
package externalapi
import (
"bytes"
"fmt"
"github.com/pkg/errors"
)
// DomainTransaction represents a Kaspa transaction
@ -25,10 +27,6 @@ type DomainTransaction struct {
// Clone returns a clone of DomainTransaction
func (tx *DomainTransaction) Clone() *DomainTransaction {
if tx == nil {
return nil
}
payloadClone := make([]byte, len(tx.Payload))
copy(payloadClone, tx.Payload)
@ -42,6 +40,11 @@ func (tx *DomainTransaction) Clone() *DomainTransaction {
outputsClone[i] = output.Clone()
}
var idClone *DomainTransactionID
if tx.ID != nil {
idClone = tx.ID.Clone()
}
return &DomainTransaction{
Version: tx.Version,
Inputs: inputsClone,
@ -53,9 +56,81 @@ func (tx *DomainTransaction) Clone() *DomainTransaction {
Payload: payloadClone,
Fee: tx.Fee,
Mass: tx.Mass,
ID: idClone,
}
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = DomainTransaction{0, []*DomainTransactionInput{}, []*DomainTransactionOutput{}, 0,
DomainSubnetworkID{}, 0, DomainHash{}, []byte{}, 0, 0,
&DomainTransactionID{}}
// Equal returns whether tx equals to other
func (tx *DomainTransaction) Equal(other *DomainTransaction) bool {
if tx == nil || other == nil {
return tx == other
}
if tx.Version != other.Version {
return false
}
if len(tx.Inputs) != len(other.Inputs) {
return false
}
for i, input := range tx.Inputs {
if !input.Equal(other.Inputs[i]) {
return false
}
}
if len(tx.Outputs) != len(other.Outputs) {
return false
}
for i, output := range tx.Outputs {
if !output.Equal(other.Outputs[i]) {
return false
}
}
if tx.LockTime != other.LockTime {
return false
}
if !tx.SubnetworkID.Equal(&other.SubnetworkID) {
return false
}
if tx.Gas != other.Gas {
return false
}
if !tx.PayloadHash.Equal(&other.PayloadHash) {
return false
}
if !bytes.Equal(tx.Payload, other.Payload) {
return false
}
if tx.Fee != other.Fee {
return false
}
if tx.Mass != other.Mass {
return false
}
if tx.ID != nil && other.ID != nil && !tx.ID.Equal(other.ID) {
panic(errors.New("identical transactions should always have the same ID"))
}
return true
}
// DomainTransactionInput represents a Kaspa transaction input
type DomainTransactionInput struct {
PreviousOutpoint DomainOutpoint
@ -65,12 +140,37 @@ type DomainTransactionInput struct {
UTXOEntry UTXOEntry
}
// Clone returns a clone of DomainTransactionInput
func (input *DomainTransactionInput) Clone() *DomainTransactionInput {
if input == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &DomainTransactionInput{DomainOutpoint{}, []byte{}, 0, nil}
// Equal returns whether input equals to other
func (input *DomainTransactionInput) Equal(other *DomainTransactionInput) bool {
if input == nil || other == nil {
return input == other
}
if !input.PreviousOutpoint.Equal(&other.PreviousOutpoint) {
return false
}
if !bytes.Equal(input.SignatureScript, other.SignatureScript) {
return false
}
if input.Sequence != other.Sequence {
return false
}
if !input.UTXOEntry.Equal(other.UTXOEntry) {
return false
}
return true
}
// Clone returns a clone of DomainTransactionInput
func (input *DomainTransactionInput) Clone() *DomainTransactionInput {
signatureScriptClone := make([]byte, len(input.SignatureScript))
copy(signatureScriptClone, input.SignatureScript)
@ -88,12 +188,21 @@ type DomainOutpoint struct {
Index uint32
}
// Clone returns a clone of DomainOutpoint
func (op *DomainOutpoint) Clone() *DomainOutpoint {
if op == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = DomainOutpoint{DomainTransactionID{}, 0}
// Equal returns whether op equals to other
func (op *DomainOutpoint) Equal(other *DomainOutpoint) bool {
if op == nil || other == nil {
return op == other
}
return *op == *other
}
// Clone returns a clone of DomainOutpoint
func (op *DomainOutpoint) Clone() *DomainOutpoint {
return &DomainOutpoint{
TransactionID: *op.TransactionID.Clone(),
Index: op.Index,
@ -119,12 +228,29 @@ type DomainTransactionOutput struct {
ScriptPublicKey []byte
}
// Clone returns a clone of DomainTransactionOutput
func (output *DomainTransactionOutput) Clone() *DomainTransactionOutput {
if output == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = DomainTransactionOutput{0, []byte{}}
// Equal returns whether output equals to other
func (output *DomainTransactionOutput) Equal(other *DomainTransactionOutput) bool {
if output == nil || other == nil {
return output == other
}
if output.Value != other.Value {
return false
}
if !bytes.Equal(output.ScriptPublicKey, other.ScriptPublicKey) {
return false
}
return true
}
// Clone returns a clone of DomainTransactionOutput
func (output *DomainTransactionOutput) Clone() *DomainTransactionOutput {
scriptPublicKeyClone := make([]byte, len(output.ScriptPublicKey))
copy(scriptPublicKeyClone, output.ScriptPublicKey)
@ -144,10 +270,19 @@ func (id DomainTransactionID) String() string {
// Clone returns a clone of DomainTransactionID
func (id *DomainTransactionID) Clone() *DomainTransactionID {
if id == nil {
return nil
}
idClone := *id
return &idClone
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ DomainTransactionID = [DomainHashSize]byte{}
// Equal returns whether id equals to other
func (id *DomainTransactionID) Equal(other *DomainTransactionID) bool {
if id == nil || other == nil {
return id == other
}
return *id == *other
}

File diff suppressed because it is too large Load Diff

View File

@ -9,4 +9,5 @@ type UTXOEntry interface {
ScriptPublicKey() []byte // The public key script for the output.
BlockBlueScore() uint64 // Blue score of the block accepting the tx.
IsCoinbase() bool
Equal(other UTXOEntry) bool
}

View File

@ -12,15 +12,32 @@ type ReachabilityData struct {
FutureCoveringSet FutureCoveringTreeNodeSet
}
// Clone returns a clone of ReachabilityData
func (rd *ReachabilityData) Clone() *ReachabilityData {
if rd == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &ReachabilityData{&ReachabilityTreeNode{}, FutureCoveringTreeNodeSet{}}
// Equal returns whether rd equals to other
func (rd *ReachabilityData) Equal(other *ReachabilityData) bool {
if rd == nil || other == nil {
return rd == other
}
if !rd.TreeNode.Equal(other.TreeNode) {
return false
}
if !rd.FutureCoveringSet.Equal(other.FutureCoveringSet) {
return false
}
return true
}
// Clone returns a clone of ReachabilityData
func (rd *ReachabilityData) Clone() *ReachabilityData {
return &ReachabilityData{
TreeNode: rd.TreeNode.Clone(),
FutureCoveringSet: externalapi.CloneHashes(rd.FutureCoveringSet),
FutureCoveringSet: rd.FutureCoveringSet.Clone(),
}
}
@ -48,15 +65,43 @@ type ReachabilityTreeNode struct {
Interval *ReachabilityInterval
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &ReachabilityTreeNode{[]*externalapi.DomainHash{}, &externalapi.DomainHash{},
&ReachabilityInterval{}}
// Equal returns whether rtn equals to other
func (rtn *ReachabilityTreeNode) Equal(other *ReachabilityTreeNode) bool {
if rtn == nil || other == nil {
return rtn == other
}
if !externalapi.HashesEqual(rtn.Children, other.Children) {
return false
}
if !rtn.Parent.Equal(other.Parent) {
return false
}
if !rtn.Interval.Equal(other.Interval) {
return false
}
return true
}
// Clone returns a clone of ReachabilityTreeNode
func (rtn *ReachabilityTreeNode) Clone() *ReachabilityTreeNode {
if rtn == nil {
return nil
var parentClone *externalapi.DomainHash
if rtn.Parent != nil {
parentClone = rtn.Parent.Clone()
}
return &ReachabilityTreeNode{
Children: externalapi.CloneHashes(rtn.Children),
Parent: rtn.Parent.Clone(),
Parent: parentClone,
Interval: rtn.Interval.Clone(),
}
}
@ -69,12 +114,29 @@ type ReachabilityInterval struct {
End uint64
}
// Clone returns a clone of ReachabilityInterval
func (ri *ReachabilityInterval) Clone() *ReachabilityInterval {
if ri == nil {
return nil
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ = &ReachabilityInterval{0, 0}
// Equal returns whether ri equals to other
func (ri *ReachabilityInterval) Equal(other *ReachabilityInterval) bool {
if ri == nil || other == nil {
return ri == other
}
if ri.Start != other.Start {
return false
}
if ri.End != other.End {
return false
}
return true
}
// Clone returns a clone of ReachabilityInterval
func (ri *ReachabilityInterval) Clone() *ReachabilityInterval {
return &ReachabilityInterval{
Start: ri.Start,
End: ri.End,
@ -98,3 +160,17 @@ func (ri *ReachabilityInterval) String() string {
//
// See insertNode, hasAncestorOf, and isInPast for further details.
type FutureCoveringTreeNodeSet []*externalapi.DomainHash
// Clone returns a clone of FutureCoveringTreeNodeSet
func (fctns FutureCoveringTreeNodeSet) Clone() FutureCoveringTreeNodeSet {
return externalapi.CloneHashes(fctns)
}
// If this doesn't compile, it means the type definition has been changed, so it's
// an indication to update Equal and Clone accordingly.
var _ FutureCoveringTreeNodeSet = []*externalapi.DomainHash{}
// Equal returns whether fctns equals to other
func (fctns FutureCoveringTreeNodeSet) Equal(other FutureCoveringTreeNodeSet) bool {
return externalapi.HashesEqual(fctns, other)
}

View File

@ -0,0 +1,296 @@
package model
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"reflect"
"testing"
)
func TestReachabilityData_Equal(t *testing.T) {
type dataToCompare struct {
data *ReachabilityData
expectedResult bool
}
tests := []struct {
baseData *ReachabilityData
dataToCompareTo []dataToCompare
}{
// Test nil data
{
baseData: nil,
dataToCompareTo: nil,
},
// Test empty data
{
baseData: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{},
},
dataToCompareTo: []dataToCompare{
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{},
},
expectedResult: true,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}}, // Changed
&externalapi.DomainHash{},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{1}, // Changed
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{100, 0}, // Changed start
},
FutureCoveringTreeNodeSet{},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{0, 100}, // Changed end
},
FutureCoveringTreeNodeSet{},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{{1}, {2}}, // Changed
},
expectedResult: false,
},
},
},
// Test filled data
{
baseData: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
dataToCompareTo: []dataToCompare{
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: true,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{}, // Changed
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
&ReachabilityInterval{200, 200}, // Changed start
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
nil, //Changed
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}, {3}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 100}, // Changed end
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{}, // Changed
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}},
&externalapi.DomainHash{}, // Changed
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}},
&externalapi.DomainHash{1},
&ReachabilityInterval{}, // Changed
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
expectedResult: false,
},
{
data: &ReachabilityData{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{}, // Changed
},
expectedResult: false,
},
{
data: &ReachabilityData{
nil,
FutureCoveringTreeNodeSet{},
},
expectedResult: false,
},
{
data: nil,
expectedResult: false,
},
},
},
}
for i, test := range tests {
for j, subTest := range test.dataToCompareTo {
result1 := test.baseData.Equal(subTest.data)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.data.Equal(test.baseData)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}
func TestReachabilityData_Clone(t *testing.T) {
testData := []*ReachabilityData{
{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{},
},
{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{{1}, {2}},
&externalapi.DomainHash{1},
&ReachabilityInterval{},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
{
&ReachabilityTreeNode{
[]*externalapi.DomainHash{},
&externalapi.DomainHash{1},
&ReachabilityInterval{100, 200},
},
FutureCoveringTreeNodeSet{{1}, {2}},
},
}
for i, data := range testData {
clone := data.Clone()
if !clone.Equal(data) {
t.Fatalf("Test #%d: clone should be equal to the original", i)
}
if !reflect.DeepEqual(data, clone) {
t.Fatalf("Test #%d: clone should be equal to the original", i)
}
}
}

View File

@ -74,7 +74,7 @@ func (bp *blockProcessor) validateAndInsertBlock(block *externalapi.DomainBlock,
}
var oldHeadersSelectedTip *externalapi.DomainHash
isGenesis := *blockHash == *bp.genesisHash
isGenesis := blockHash.Equal(bp.genesisHash)
if !isGenesis {
var err error
oldHeadersSelectedTip, err = bp.headersSelectedTipStore.HeadersSelectedTip(bp.databaseContext)
@ -156,7 +156,7 @@ func (bp *blockProcessor) updateReachabilityReindexRoot(oldHeadersSelectedTip *e
return err
}
if *headersSelectedTip == *oldHeadersSelectedTip {
if headersSelectedTip.Equal(oldHeadersSelectedTip) {
return nil
}

View File

@ -17,7 +17,7 @@ func (bp *blockProcessor) validateAndInsertPruningPoint(newPruningPoint *externa
newPruningPointHash := consensushashing.BlockHash(newPruningPoint)
if *expectedNewPruningPointHash != *newPruningPointHash {
if !expectedNewPruningPointHash.Equal(newPruningPointHash) {
return errors.Wrapf(ruleerrors.ErrUnexpectedPruningPoint, "expected pruning point %s but got %s",
expectedNewPruningPointHash, newPruningPointHash)
}

View File

@ -143,7 +143,7 @@ func (v *blockValidator) checkTransactionsInIsolation(block *externalapi.DomainB
func (v *blockValidator) checkBlockHashMerkleRoot(block *externalapi.DomainBlock) error {
calculatedHashMerkleRoot := merkle.CalculateHashMerkleRoot(block.Transactions)
if block.Header.HashMerkleRoot != *calculatedHashMerkleRoot {
if !block.Header.HashMerkleRoot.Equal(calculatedHashMerkleRoot) {
return errors.Wrapf(ruleerrors.ErrBadMerkleRoot, "block hash merkle root is invalid - block "+
"header indicates %s, but calculated value is %s",
block.Header.HashMerkleRoot, calculatedHashMerkleRoot)

View File

@ -86,7 +86,7 @@ func (v *blockValidator) hasValidatedHeader(blockHash *externalapi.DomainHash) (
func (v *blockValidator) checkParentsIncest(header *externalapi.DomainBlockHeader) error {
for _, parentA := range header.ParentHashes {
for _, parentB := range header.ParentHashes {
if *parentA == *parentB {
if parentA.Equal(parentB) {
continue
}

View File

@ -35,7 +35,7 @@ func (v *blockValidator) ValidateHeaderInIsolation(blockHash *externalapi.Domain
func (v *blockValidator) checkParentsLimit(header *externalapi.DomainBlockHeader) error {
hash := consensushashing.HeaderHash(header)
if len(header.ParentHashes) == 0 && *hash != *v.genesisHash {
if len(header.ParentHashes) == 0 && !hash.Equal(v.genesisHash) {
return errors.Wrapf(ruleerrors.ErrNoParents, "block has no parents")
}

View File

@ -68,7 +68,7 @@ func (csm *consensusStateManager) isCandidateToBeNextVirtualSelectedParent(block
log.Tracef("isCandidateToBeNextVirtualSelectedParent start for block %s", blockHash)
defer log.Tracef("isCandidateToBeNextVirtualSelectedParent end for block %s", blockHash)
if *blockHash == *csm.genesisHash {
if blockHash.Equal(csm.genesisHash) {
log.Tracef("Block %s is the genesis block, therefore it is "+
"the selected parent by definition", blockHash)
return true, nil
@ -87,7 +87,7 @@ func (csm *consensusStateManager) isCandidateToBeNextVirtualSelectedParent(block
}
log.Tracef("The next selected parent is: %s", nextVirtualSelectedParent)
return *blockHash == *nextVirtualSelectedParent, nil
return blockHash.Equal(nextVirtualSelectedParent), nil
}
func (csm *consensusStateManager) addTip(newTipHash *externalapi.DomainHash) (newTips []*externalapi.DomainHash, err error) {
@ -111,7 +111,7 @@ func (csm *consensusStateManager) calculateNewTips(newTipHash *externalapi.Domai
log.Tracef("calculateNewTips start for new tip %s", newTipHash)
defer log.Tracef("calculateNewTips end for new tip %s", newTipHash)
if *newTipHash == *csm.genesisHash {
if newTipHash.Equal(csm.genesisHash) {
log.Tracef("The new tip is the genesis block, therefore it is the only tip by definition")
return []*externalapi.DomainHash{newTipHash}, nil
}
@ -133,7 +133,7 @@ func (csm *consensusStateManager) calculateNewTips(newTipHash *externalapi.Domai
for _, currentTip := range currentTips {
isCurrentTipInNewTipParents := false
for _, newTipParent := range newTipParents {
if *currentTip == *newTipParent {
if currentTip.Equal(newTipParent) {
isCurrentTipInNewTipParents = true
break
}

View File

@ -18,7 +18,7 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(blockHash *
log.Tracef("CalculatePastUTXOAndAcceptanceData start for block %s", blockHash)
defer log.Tracef("CalculatePastUTXOAndAcceptanceData end for block %s", blockHash)
if *blockHash == *csm.genesisHash {
if blockHash.Equal(csm.genesisHash) {
log.Tracef("Block %s is the genesis. By definition, "+
"it has an empty UTXO diff, empty acceptance data, and a blank multiset", blockHash)
return utxo.NewUTXODiff(), externalapi.AcceptanceData{}, multiset.New(), nil

View File

@ -154,7 +154,7 @@ func TestPastUTXOMultiset(t *testing.T) {
secondMultisetHash := secondMultiset.Hash()
// Make sure the multiset hasn't changed
if *firstMultisetHash != *secondMultisetHash {
if !firstMultisetHash.Equal(secondMultisetHash) {
t.Fatalf("TestPastUTXOMultiSet: selectedParentMultiset appears to have changed!")
}
})

View File

@ -8,7 +8,7 @@ func (csm *consensusStateManager) isViolatingFinality(blockHash *externalapi.Dom
log.Tracef("isViolatingFinality start for block %s", blockHash)
defer log.Tracef("isViolatingFinality end for block %s", blockHash)
if *blockHash == *csm.genesisHash {
if blockHash.Equal(csm.genesisHash) {
log.Tracef("Block %s is the genesis block, "+
"and does not violate finality by definition", blockHash)
return false, false, nil

View File

@ -51,7 +51,7 @@ func (csm *consensusStateManager) calculateSelectedParentChainChanges(
// Walk down from the toBlockHash to the common ancestor
var added []*externalapi.DomainHash
current = toBlockHash
for *current != *commonAncestor {
for !current.Equal(commonAncestor) {
added = append(added, current)
currentGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, current)
if err != nil {

View File

@ -35,7 +35,7 @@ func TestCalculateSelectedParentChainChanges(t *testing.T) {
t.Fatalf("The `added` slice contains an unexpected amount of items after inserting block A. "+
"Want: %d, got: %d", 1, len(blockASelectedParentChainChanges.Added))
}
if *blockASelectedParentChainChanges.Added[0] != *blockAHash {
if !blockASelectedParentChainChanges.Added[0].Equal(blockAHash) {
t.Fatalf("The `added` slice contains an unexpected hash. Want: %s, got: %s",
blockAHash, blockASelectedParentChainChanges.Added[0])
}
@ -53,7 +53,7 @@ func TestCalculateSelectedParentChainChanges(t *testing.T) {
}
virtualSelectedParent := virtualGHOSTDAGData.SelectedParent()
notVirtualSelectedParent := blockAHash
if *virtualSelectedParent == *blockAHash {
if virtualSelectedParent.Equal(blockAHash) {
notVirtualSelectedParent = blockBHash
}
@ -71,7 +71,7 @@ func TestCalculateSelectedParentChainChanges(t *testing.T) {
t.Fatalf("The `removed` slice contains an unexpected amount of items after inserting block C. "+
"Want: %d, got: %d", 1, len(blockCSelectedParentChainChanges.Removed))
}
if *blockCSelectedParentChainChanges.Removed[0] != *virtualSelectedParent {
if !blockCSelectedParentChainChanges.Removed[0].Equal(virtualSelectedParent) {
t.Fatalf("The `removed` slice contains an unexpected hash. "+
"Want: %s, got: %s", virtualSelectedParent, blockCSelectedParentChainChanges.Removed[0])
}
@ -82,11 +82,11 @@ func TestCalculateSelectedParentChainChanges(t *testing.T) {
t.Fatalf("The `added` slice contains an unexpected amount of items after inserting block C. "+
"Want: %d, got: %d", 2, len(blockCSelectedParentChainChanges.Added))
}
if *blockCSelectedParentChainChanges.Added[0] != *notVirtualSelectedParent {
if !blockCSelectedParentChainChanges.Added[0].Equal(notVirtualSelectedParent) {
t.Fatalf("The `added` slice contains an unexpected hash as the first item. "+
"Want: %s, got: %s", notVirtualSelectedParent, blockCSelectedParentChainChanges.Added[0])
}
if *blockCSelectedParentChainChanges.Added[1] != *blockCHash {
if !blockCSelectedParentChainChanges.Added[1].Equal(blockCHash) {
t.Fatalf("The `added` slice contains an unexpected hash as the second item. "+
"Want: %s, got: %s", blockCHash, blockCSelectedParentChainChanges.Added[1])
}

View File

@ -109,7 +109,7 @@ func (csm *consensusStateManager) selectVirtualSelectedParent(
// remove virtual from parentChildren if it's there
for i, parentChild := range parentChildren {
if *parentChild == *model.VirtualBlockHash {
if parentChild.Equal(model.VirtualBlockHash) {
parentChildren = append(parentChildren[:i], parentChildren[i+1:]...)
break
}

View File

@ -70,7 +70,7 @@ func (csm *consensusStateManager) findSelectedParentStatus(unverifiedBlocks []*e
defer log.Tracef("findSelectedParentStatus end")
lastUnverifiedBlock := unverifiedBlocks[len(unverifiedBlocks)-1]
if *lastUnverifiedBlock == *csm.genesisHash {
if lastUnverifiedBlock.Equal(csm.genesisHash) {
log.Tracef("the most recent unverified block is the genesis block, "+
"which by definition has status: %s", externalapi.StatusUTXOValid)
return externalapi.StatusUTXOValid, nil
@ -173,7 +173,7 @@ func (csm *consensusStateManager) removeAncestorsFromVirtualDiffParentsAndAssign
log.Tracef("removeAncestorsFromVirtualDiffParentsAndAssignDiffChild start for block %s", blockHash)
defer log.Tracef("removeAncestorsFromVirtualDiffParentsAndAssignDiffChild end for block %s", blockHash)
if *blockHash == *csm.genesisHash {
if blockHash.Equal(csm.genesisHash) {
log.Tracef("Genesis block doesn't have ancestors to remove from the virtual diff parents")
return nil
}
@ -184,7 +184,7 @@ func (csm *consensusStateManager) removeAncestorsFromVirtualDiffParentsAndAssign
}
for _, virtualDiffParent := range virtualDiffParents {
if *virtualDiffParent == *blockHash {
if virtualDiffParent.Equal(blockHash) {
log.Tracef("Skipping updating virtual diff parent %s "+
"because it was updated before.", virtualDiffParent)
continue

View File

@ -56,7 +56,7 @@ func TestDoubleSpends(t *testing.T) {
spendingTransaction2.Outputs[0].Value-- // tweak the value to create a different ID
spendingTransaction1ID := consensushashing.TransactionID(spendingTransaction1)
spendingTransaction2ID := consensushashing.TransactionID(spendingTransaction2)
if *spendingTransaction1ID == *spendingTransaction2ID {
if spendingTransaction1ID.Equal(spendingTransaction2ID) {
t.Fatalf("spendingTransaction1 and spendingTransaction2 ids are equal")
}

View File

@ -63,7 +63,7 @@ func (csm *consensusStateManager) updatePruningPoint(newPruningPoint *externalap
log.Debugf("The UTXO commitment of the pruning point: %s",
newPruningPointHeader.UTXOCommitment)
if newPruningPointHeader.UTXOCommitment != *utxoSetMultiSet.Hash() {
if !newPruningPointHeader.UTXOCommitment.Equal(utxoSetMultiSet.Hash()) {
return errors.Wrapf(ruleerrors.ErrBadPruningPointUTXOSet, "the expected multiset hash of the pruning "+
"point UTXO set is %s but got %s", newPruningPointHeader.UTXOCommitment, *utxoSetMultiSet.Hash())
}

View File

@ -13,7 +13,7 @@ func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.Domain
log.Tracef("Saving a reference to the GHOSTDAG data of the old virtual")
var oldVirtualSelectedParent *externalapi.DomainHash
if *newBlockHash != *csm.genesisHash {
if !newBlockHash.Equal(csm.genesisHash) {
oldVirtualGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, model.VirtualBlockHash)
if err != nil {
return nil, err
@ -65,7 +65,7 @@ func (csm *consensusStateManager) updateVirtual(newBlockHash *externalapi.Domain
log.Tracef("Calculating selected parent chain changes")
var selectedParentChainChanges *externalapi.SelectedParentChainChanges
if *newBlockHash != *csm.genesisHash {
if !newBlockHash.Equal(csm.genesisHash) {
newVirtualGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, model.VirtualBlockHash)
if err != nil {
return nil, err

View File

@ -29,7 +29,7 @@ func (csm *consensusStateManager) addToVirtualDiffParents(blockHash *externalapi
defer log.Tracef("addToVirtualDiffParents end for block %s", blockHash)
var oldVirtualDiffParents []*externalapi.DomainHash
if *blockHash != *csm.genesisHash {
if !blockHash.Equal(csm.genesisHash) {
var err error
oldVirtualDiffParents, err = csm.consensusStateStore.VirtualDiffParents(csm.databaseContext)
if err != nil {
@ -39,7 +39,7 @@ func (csm *consensusStateManager) addToVirtualDiffParents(blockHash *externalapi
isInVirtualDiffParents := false
for _, diffParent := range oldVirtualDiffParents {
if *diffParent == *blockHash {
if diffParent.Equal(blockHash) {
isInVirtualDiffParents = true
break
}
@ -67,7 +67,7 @@ func (csm *consensusStateManager) removeFromVirtualDiffParents(blockHash *extern
newVirtualDiffParents := make([]*externalapi.DomainHash, 0, len(oldVirtualDiffParents)-1)
for _, diffParent := range oldVirtualDiffParents {
if *diffParent != *blockHash {
if !diffParent.Equal(blockHash) {
newVirtualDiffParents = append(newVirtualDiffParents, diffParent)
}
}

View File

@ -103,7 +103,7 @@ func (csm *consensusStateManager) validateAcceptedIDMerkleRoot(block *externalap
defer log.Tracef("validateAcceptedIDMerkleRoot end for block %s", blockHash)
calculatedAcceptedIDMerkleRoot := calculateAcceptedIDMerkleRoot(acceptanceData)
if block.Header.AcceptedIDMerkleRoot != *calculatedAcceptedIDMerkleRoot {
if !block.Header.AcceptedIDMerkleRoot.Equal(calculatedAcceptedIDMerkleRoot) {
return errors.Wrapf(ruleerrors.ErrBadMerkleRoot, "block %s accepted ID merkle root is invalid - block "+
"header indicates %s, but calculated value is %s",
blockHash, &block.Header.UTXOCommitment, calculatedAcceptedIDMerkleRoot)
@ -119,7 +119,7 @@ func (csm *consensusStateManager) validateUTXOCommitment(
defer log.Tracef("validateUTXOCommitment end for block %s", blockHash)
multisetHash := multiset.Hash()
if block.Header.UTXOCommitment != *multisetHash {
if !block.Header.UTXOCommitment.Equal(multisetHash) {
return errors.Wrapf(ruleerrors.ErrBadUTXOCommitment, "block %s UTXO commitment is invalid - block "+
"header indicates %s, but calculated value is %s", blockHash, &block.Header.UTXOCommitment, multisetHash)
}
@ -173,7 +173,7 @@ func (csm *consensusStateManager) validateCoinbaseTransaction(blockHash *externa
log.Tracef("given coinbase hash: %s, expected coinbase hash: %s",
coinbaseTransactionHash, expectedCoinbaseTransactionHash)
if *coinbaseTransactionHash != *expectedCoinbaseTransactionHash {
if !coinbaseTransactionHash.Equal(expectedCoinbaseTransactionHash) {
return errors.Wrap(ruleerrors.ErrBadCoinbaseTransaction, "coinbase transaction is not built as expected")
}

View File

@ -99,7 +99,7 @@ func (dtm *dagTopologyManager) IsInSelectedParentChainOf(blockHashA *externalapi
func isHashInSlice(hash *externalapi.DomainHash, hashes []*externalapi.DomainHash) bool {
for _, h := range hashes {
if *h == *hash {
if h.Equal(hash) {
return true
}
}
@ -128,7 +128,7 @@ func (dtm *dagTopologyManager) SetParents(blockHash *externalapi.DomainHash, par
return err
}
for i, parentChild := range parentRelations.Children {
if *parentChild == *blockHash {
if parentChild.Equal(blockHash) {
parentRelations.Children = append(parentRelations.Children[:i], parentRelations.Children[i+1:]...)
dtm.blockRelationStore.StageBlockRelation(currentParent, parentRelations)
break
@ -145,7 +145,7 @@ func (dtm *dagTopologyManager) SetParents(blockHash *externalapi.DomainHash, par
}
isBlockAlreadyInChildren := false
for _, parentChild := range parentRelations.Children {
if *parentChild == *blockHash {
if parentChild.Equal(blockHash) {
isBlockAlreadyInChildren = true
break
}
@ -180,7 +180,7 @@ func (dtm *dagTopologyManager) ChildInSelectedParentChainOf(
selectedParent := ghostdagData.SelectedParent()
// In case where `blockHash` is an immediate parent of `highHash`
if *blockHash == *selectedParent {
if blockHash.Equal(selectedParent) {
return highHash, nil
}
highHash = selectedParent

View File

@ -20,7 +20,7 @@ func (s *selectedChildIterator) Next() bool {
}
for _, child := range children {
if *child == *model.VirtualBlockHash {
if child.Equal(model.VirtualBlockHash) {
continue
}

View File

@ -51,7 +51,7 @@ func (fm *finalityManager) VirtualFinalityPoint() (*externalapi.DomainHash, erro
func (fm *finalityManager) FinalityPoint(blockHash *externalapi.DomainHash) (*externalapi.DomainHash, error) {
log.Tracef("FinalityPoint start")
defer log.Tracef("FinalityPoint end")
if *blockHash == *model.VirtualBlockHash {
if blockHash.Equal(model.VirtualBlockHash) {
return fm.VirtualFinalityPoint()
}
finalityPoint, err := fm.finalityStore.FinalityPoint(fm.databaseContext, blockHash)
@ -88,7 +88,7 @@ func (fm *finalityManager) calculateFinalityPoint(blockHash *externalapi.DomainH
}
selectedParent := ghostdagData.SelectedParent()
if *selectedParent == *fm.genesisHash {
if selectedParent.Equal(fm.genesisHash) {
return fm.genesisHash, nil
}

View File

@ -92,7 +92,7 @@ func (gh *ghostdagHelper) GHOSTDAG(blockCandidate *externalapi.DomainHash) error
}
for _, mergeSetBlock := range mergeSetArr {
if *mergeSetBlock == *selectedParent {
if mergeSetBlock.Equal(selectedParent) {
if !contains(selectedParent, mergeSetBlues) {
mergeSetBlues = append(mergeSetBlues, selectedParent)
blueSet = append(blueSet, selectedParent)
@ -252,7 +252,7 @@ func (gh *ghostdagHelper) validateKCluster(chain *externalapi.DomainHash, checke
/*----------------contains-------------------------- */
func contains(item *externalapi.DomainHash, items []*externalapi.DomainHash) bool {
for _, r := range items {
if *r == *item {
if r.Equal(item) {
return true
}
}
@ -294,7 +294,7 @@ func (gh *ghostdagHelper) findMergeSet(parents []*externalapi.DomainHash, select
for len(blockQueue) > 0 {
block := blockQueue[0]
blockQueue = blockQueue[1:]
if *selectedParent == *block {
if selectedParent.Equal(block) {
if !contains(block, allMergeSet) {
allMergeSet = append(allMergeSet, block)
}

View File

@ -137,7 +137,7 @@ func TestGHOSTDAG(t *testing.T) {
factory.implName, info.Name(), testBlockData.ID, testBlockData.Score, ghostdagData.BlueScore())
}
if *StringToByte(testBlockData.SelectedParent) != *ghostdagData.SelectedParent() {
if !StringToByte(testBlockData.SelectedParent).Equal(ghostdagData.SelectedParent()) {
t.Fatalf("\nTEST FAILED:\n Impl: %s, FileName: %s \nBlock: %s, \nError: expected selected parent %v but got %v.",
factory.implName, info.Name(), testBlockData.ID, testBlockData.SelectedParent, string(ghostdagData.SelectedParent()[:]))
}
@ -267,7 +267,7 @@ func (dt *DAGTopologyManagerImpl) IsAncestorOf(hashBlockA *externalapi.DomainHas
}
for _, parentOfB := range blockBParents {
if *parentOfB == *hashBlockA {
if parentOfB.Equal(hashBlockA) {
return true, nil
}
}

View File

@ -14,7 +14,7 @@ func (gm *ghostdagManager) mergeSetWithoutSelectedParent(selecteParent *external
queue := []*externalapi.DomainHash{}
// Queueing all parents (other than the selected parent itself) for processing.
for _, parent := range blockParents {
if *parent == *selecteParent {
if parent.Equal(selecteParent) {
continue
}
mergeSetMap[*parent] = struct{}{}

View File

@ -46,7 +46,7 @@ func (h *headerTipsManager) AddHeaderTip(hash *externalapi.DomainHash) error {
return err
}
if *newHeadersSelectedTip != *headersSelectedTip {
if !newHeadersSelectedTip.Equal(headersSelectedTip) {
h.headersSelectedTipStore.Stage(newHeadersSelectedTip)
}
}

View File

@ -124,7 +124,7 @@ func (pm *pruningManager) UpdatePruningPointByVirtual() error {
return err
}
if *newPruningPoint != *currentP {
if !newPruningPoint.Equal(currentP) {
err = pm.savePruningPoint(newPruningPoint)
if err != nil {
return err

View File

@ -26,7 +26,7 @@ func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *t
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if *reindexRoot != *params.GenesisHash {
if !reindexRoot.Equal(params.GenesisHash) {
t.Fatalf("reindex root is expected to initially be genesis")
}
@ -52,7 +52,7 @@ func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *t
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if *newReindexRoot == *reindexRoot {
if newReindexRoot.Equal(reindexRoot) {
t.Fatalf("reindex root is expected to change")
}
@ -114,7 +114,7 @@ func TestUpdateReindexRoot(t *testing.T) {
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if *reindexRoot != *params.GenesisHash {
if !reindexRoot.Equal(params.GenesisHash) {
t.Fatalf("reindex root unexpectedly moved")
}
}
@ -131,7 +131,7 @@ func TestUpdateReindexRoot(t *testing.T) {
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if *reindexRoot != *chain1RootBlock {
if !reindexRoot.Equal(chain1RootBlock) {
t.Fatalf("chain1RootBlock is not the reindex root after reindex")
}
@ -207,7 +207,7 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if *reindexRoot != *centerBlock {
if !reindexRoot.Equal(centerBlock) {
t.Fatalf("centerBlock is not the reindex root after reindex")
}

View File

@ -950,7 +950,7 @@ func BenchmarkReindexInterval(b *testing.B) {
currentTreeNode = childTreeNode
}
originalRemainingInterval := *helper.remainingIntervalAfter(root)
originalRemainingInterval := helper.remainingIntervalAfter(root).Clone()
// After we added subTreeSize nodes, adding the next
// node should lead to a reindex from root.
fullReindexTriggeringNode := helper.newNode()
@ -961,7 +961,7 @@ func BenchmarkReindexInterval(b *testing.B) {
b.Fatalf("addChild: %s", err)
}
if *helper.remainingIntervalAfter(root) == originalRemainingInterval {
if helper.remainingIntervalAfter(root).Equal(originalRemainingInterval) {
b.Fatal("Expected a reindex from root, but it didn't happen")
}
}

View File

@ -317,7 +317,7 @@ func (rt *reachabilityManager) countSubtrees(node *externalapi.DomainHash, subTr
// We reached a leaf or a pre-calculated subtree.
// Push information up
for *current != *node {
for !current.Equal(node) {
current, err = rt.parent(current)
if err != nil {
return err
@ -461,7 +461,7 @@ func (rt *reachabilityManager) reclaimIntervalBeforeChosenChild(rtn, commonAnces
return err
}
if currentHasSlackIntervalBefore || *current == *reindexRoot {
if currentHasSlackIntervalBefore || current.Equal(reindexRoot) {
break
}
@ -471,7 +471,7 @@ func (rt *reachabilityManager) reclaimIntervalBeforeChosenChild(rtn, commonAnces
}
}
if *current == *reindexRoot {
if current.Equal(reindexRoot) {
// "Deallocate" an interval of slackReachabilityIntervalForReclaiming
// from this node. This is the interval that we'll use for the new
// node.
@ -505,7 +505,7 @@ func (rt *reachabilityManager) reclaimIntervalBeforeChosenChild(rtn, commonAnces
// current node with an interval that is smaller by
// slackReachabilityIntervalForReclaiming. This is to make room
// for the new node.
for *current != *commonAncestor {
for !current.Equal(commonAncestor) {
currentInterval, err := rt.interval(current)
if err != nil {
return err
@ -583,7 +583,7 @@ func (rt *reachabilityManager) reclaimIntervalAfterChosenChild(node, commonAnces
return err
}
if currentHasSlackIntervalAfter || *current == *reindexRoot {
if currentHasSlackIntervalAfter || current.Equal(reindexRoot) {
break
}
@ -593,7 +593,7 @@ func (rt *reachabilityManager) reclaimIntervalAfterChosenChild(node, commonAnces
}
}
if *current == *reindexRoot {
if current.Equal(reindexRoot) {
// "Deallocate" an interval of slackReachabilityIntervalForReclaiming
// from this node. This is the interval that we'll use for the new
// node.
@ -627,7 +627,7 @@ func (rt *reachabilityManager) reclaimIntervalAfterChosenChild(node, commonAnces
// current node with an interval that is smaller by
// slackReachabilityIntervalForReclaiming. This is to make room
// for the new node.
for *current != *commonAncestor {
for !current.Equal(commonAncestor) {
currentInterval, err := rt.interval(current)
if err != nil {
return err
@ -883,7 +883,7 @@ func (rt *reachabilityManager) splitChildrenAroundChild(node, child *externalapi
}
for i, candidateChild := range nodeChildren {
if *candidateChild == *child {
if candidateChild.Equal(child) {
return nodeChildren[:i], nodeChildren[i+1:], nil
}
}

View File

@ -36,7 +36,7 @@ func (sm *syncManager) isAwaitingUTXOSet() (isAwaitingUTXOSet bool, ibdRootUTXOB
// If the pruning point by headers is different from the current point
// it means we need to request the new pruning point UTXO set.
if *pruningPoint != *pruningPointByHeaders {
if !pruningPoint.Equal(pruningPointByHeaders) {
return true, pruningPointByHeaders, nil
}

View File

@ -128,7 +128,7 @@ func (v *transactionValidator) checkCoinbaseLength(tx *externalapi.DomainTransac
func (v *transactionValidator) checkTransactionPayloadHash(tx *externalapi.DomainTransaction) error {
if tx.SubnetworkID != subnetworks.SubnetworkIDNative {
payloadHash := hashes.PayloadHash(tx.Payload)
if tx.PayloadHash != *payloadHash {
if !tx.PayloadHash.Equal(payloadHash) {
return errors.Wrapf(ruleerrors.ErrInvalidPayloadHash, "invalid payload hash")
}
} else if tx.PayloadHash != (externalapi.DomainHash{}) {
@ -177,7 +177,7 @@ func (v *transactionValidator) checkTransactionSubnetwork(tx *externalapi.Domain
// If we are a partial node, only transactions on built in subnetworks
// or our own subnetwork may have a payload
isLocalNodeFull := localNodeSubnetworkID == nil
shouldTxBeFull := subnetworks.IsBuiltIn(tx.SubnetworkID) || subnetworks.IsEqual(&tx.SubnetworkID, localNodeSubnetworkID)
shouldTxBeFull := subnetworks.IsBuiltIn(tx.SubnetworkID) || tx.SubnetworkID.Equal(localNodeSubnetworkID)
if !isLocalNodeFull && !shouldTxBeFull && len(tx.Payload) > 0 {
return errors.Wrapf(ruleerrors.ErrInvalidPayload,
"transaction that was expected to be partial has a payload "+

View File

@ -10,7 +10,7 @@ import (
func ToBig(hash *externalapi.DomainHash) *big.Int {
// A Hash is in little-endian, but the big package wants the bytes in
// big-endian, so reverse them.
buf := *hash
buf := hash.Clone()
blen := len(buf)
for i := 0; i < blen/2; i++ {
buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]

View File

@ -21,14 +21,3 @@ func cmp(a, b externalapi.DomainSubnetworkID) int {
func Less(a, b externalapi.DomainSubnetworkID) bool {
return cmp(a, b) < 0
}
// IsEqual returns true if a and b are equal or both nil
func IsEqual(a, b *externalapi.DomainSubnetworkID) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
return *a == *b
}

View File

@ -1,6 +1,9 @@
package utxo
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
import (
"bytes"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
)
type utxoEntry struct {
amount uint64
@ -38,3 +41,36 @@ func (u *utxoEntry) BlockBlueScore() uint64 {
func (u *utxoEntry) IsCoinbase() bool {
return u.isCoinbase
}
// Equal returns whether entry equals to other
func (u *utxoEntry) Equal(other externalapi.UTXOEntry) bool {
if u == nil || other == nil {
return u == other
}
// If only the underlying value of other is nil it'll
// make `other == nil` return false, so we check it
// explicitly.
downcastedOther := other.(*utxoEntry)
if u == nil || downcastedOther == nil {
return u == downcastedOther
}
if u.Amount() != other.Amount() {
return false
}
if !bytes.Equal(u.ScriptPublicKey(), other.ScriptPublicKey()) {
return false
}
if u.BlockBlueScore() != other.BlockBlueScore() {
return false
}
if u.IsCoinbase() != other.IsCoinbase() {
return false
}
return true
}

View File

@ -0,0 +1,113 @@
package utxo
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"testing"
)
func TestUTXOEntry_Equal(t *testing.T) {
type testUTXOEntryToCompare struct {
utxoEntry *utxoEntry
expectedResult bool
}
tests := []struct {
baseUTXOEntry *utxoEntry
UTXOEntryToCompareTo []testUTXOEntryToCompare
}{
{
baseUTXOEntry: nil,
UTXOEntryToCompareTo: []testUTXOEntryToCompare{
{
utxoEntry: nil,
expectedResult: true,
},
{
utxoEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA2, 0xA3},
0xFFFF,
false,
},
expectedResult: false,
},
},
}, {
baseUTXOEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA2, 0xA3},
0xFFFF,
true,
},
UTXOEntryToCompareTo: []testUTXOEntryToCompare{
{
utxoEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA2, 0xA3},
0xFFFF,
true,
},
expectedResult: true,
},
{
utxoEntry: nil,
expectedResult: false,
},
{
utxoEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA0, 0xA3}, // Changed
0xFFFF,
true,
},
expectedResult: false,
},
{
utxoEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA2, 0xA3},
0xFFFF,
false, // Changed
},
expectedResult: false,
},
{
utxoEntry: &utxoEntry{
0xFFFF,
[]byte{0xA1, 0xA2, 0xA3},
0xFFF0, // Changed
true,
},
expectedResult: false,
},
{
utxoEntry: nil,
expectedResult: false,
},
{
utxoEntry: &utxoEntry{
0xFFF0, // Changed
[]byte{0xA1, 0xA2, 0xA3},
0xFFFF,
true,
},
expectedResult: false,
},
},
},
}
for i, test := range tests {
for j, subTest := range test.UTXOEntryToCompareTo {
var base externalapi.UTXOEntry = test.baseUTXOEntry
result1 := base.Equal(subTest.utxoEntry)
if result1 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result1)
}
result2 := subTest.utxoEntry.Equal(base)
if result2 != subTest.expectedResult {
t.Fatalf("Test #%d:%d: Expected %t but got %t", i, j, subTest.expectedResult, result2)
}
}
}
}

View File

@ -15,7 +15,7 @@ import (
func TestGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensushashing.BlockHash(MainnetParams.GenesisBlock)
if *MainnetParams.GenesisHash != *hash {
if !MainnetParams.GenesisHash.Equal(hash) {
t.Fatalf("TestGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", hash, MainnetParams.GenesisHash)
}
@ -26,7 +26,7 @@ func TestGenesisBlock(t *testing.T) {
func TestTestnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensushashing.BlockHash(TestnetParams.GenesisBlock)
if *TestnetParams.GenesisHash != *hash {
if !TestnetParams.GenesisHash.Equal(hash) {
t.Fatalf("TestTestnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", hash,
TestnetParams.GenesisHash)
@ -38,7 +38,7 @@ func TestTestnetGenesisBlock(t *testing.T) {
func TestSimnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensushashing.BlockHash(SimnetParams.GenesisBlock)
if *SimnetParams.GenesisHash != *hash {
if !SimnetParams.GenesisHash.Equal(hash) {
t.Fatalf("TestSimnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", hash,
SimnetParams.GenesisHash)
@ -50,7 +50,7 @@ func TestSimnetGenesisBlock(t *testing.T) {
func TestDevnetGenesisBlock(t *testing.T) {
// Check hash of the block against expected hash.
hash := consensushashing.BlockHash(DevnetParams.GenesisBlock)
if *DevnetParams.GenesisHash != *hash {
if !DevnetParams.GenesisHash.Equal(hash) {
t.Fatalf("TestDevnetGenesisBlock: Genesis block hash does "+
"not appear valid - got %v, want %v", hash,
DevnetParams.GenesisHash)

View File

@ -35,7 +35,7 @@ func TestNewHashFromStr(t *testing.T) {
result := newHashFromStr(test.hexStr)
if *result != *test.expectedHash {
if !result.Equal(test.expectedHash) {
t.Errorf("%s: Expected hash: %s, but got %s", test.hexStr, test.expectedHash, result)
}
}()

View File

@ -467,10 +467,10 @@ func (mp *mempool) removeChainTransaction(tx *consensusexternalapi.DomainTransac
//
// This function MUST be called with the mempool lock held (for writes).
func (mp *mempool) removeDoubleSpends(tx *consensusexternalapi.DomainTransaction) error {
txID := *consensushashing.TransactionID(tx)
txID := consensushashing.TransactionID(tx)
for _, txIn := range tx.Inputs {
if txRedeemer, ok := mp.mempoolUTXOSet.poolTransactionBySpendingOutpoint(txIn.PreviousOutpoint); ok {
if !(*consensushashing.TransactionID(txRedeemer) == txID) {
if !consensushashing.TransactionID(txRedeemer).Equal(txID) {
err := mp.removeTransactionAndItsChainedTransactions(txRedeemer)
if err != nil {
return err

View File

@ -25,7 +25,7 @@ func newUTXOIndexStore(database database.Database) *utxoIndexStore {
}
}
func (uis *utxoIndexStore) add(scriptPublicKey []byte, outpoint *externalapi.DomainOutpoint, utxoEntry *externalapi.UTXOEntry) error {
func (uis *utxoIndexStore) add(scriptPublicKey []byte, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error {
key := ConvertScriptPublicKeyToString(scriptPublicKey)
log.Tracef("Adding outpoint %s:%d to scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key)
@ -52,7 +52,7 @@ func (uis *utxoIndexStore) add(scriptPublicKey []byte, outpoint *externalapi.Dom
return errors.Errorf("cannot add outpoint %s because it's being added already", outpoint)
}
toAddPairsOfKey[*outpoint] = *utxoEntry
toAddPairsOfKey[*outpoint] = utxoEntry
log.Tracef("Added outpoint %s:%d to scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key)

View File

@ -126,7 +126,7 @@ func (ui *UTXOIndex) addTransaction(transaction *externalapi.DomainTransaction,
log.Tracef("Adding outpoint %s:%d to UTXO index", transactionID, index)
outpoint := externalapi.NewDomainOutpoint(transactionID, uint32(index))
utxoEntry := utxo.NewUTXOEntry(transactionOutput.Value, transactionOutput.ScriptPublicKey, isCoinbase, blockBlueScore)
err := ui.store.add(transactionOutput.ScriptPublicKey, outpoint, &utxoEntry)
err := ui.store.add(transactionOutput.ScriptPublicKey, outpoint, utxoEntry)
if err != nil {
return err
}
@ -148,7 +148,7 @@ func (ui *UTXOIndex) removeTransaction(transaction *externalapi.DomainTransactio
for _, transactionInput := range transaction.Inputs {
log.Tracef("Adding outpoint %s:%d to UTXO index",
transactionInput.PreviousOutpoint.TransactionID, transactionInput.PreviousOutpoint.Index)
err := ui.store.add(transactionInput.UTXOEntry.ScriptPublicKey(), &transactionInput.PreviousOutpoint, &transactionInput.UTXOEntry)
err := ui.store.add(transactionInput.UTXOEntry.ScriptPublicKey(), &transactionInput.PreviousOutpoint, transactionInput.UTXOEntry)
if err != nil {
return err
}

View File

@ -38,7 +38,7 @@ func TestIntegrationBasicSync(t *testing.T) {
}
blockHash := consensushashing.BlockHash(block)
if *header.BlockHash() != *blockHash {
if !header.BlockHash().Equal(blockHash) {
t.Errorf("Expected block with hash '%s', but got '%s'", blockHash, header.BlockHash())
}
@ -49,7 +49,7 @@ func TestIntegrationBasicSync(t *testing.T) {
}
blockHash = consensushashing.BlockHash(block)
if *header.BlockHash() != *blockHash {
if !header.BlockHash().Equal(blockHash) {
t.Errorf("Expected block with hash '%s', but got '%s'", blockHash, header.BlockHash())
}
}