mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-05 21:56:50 +00:00
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:
parent
c2cec2f170
commit
cb9d7e313d
@ -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{}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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 .
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
809
domain/consensus/model/acceptancedata_equal_clone_test.go
Normal file
809
domain/consensus/model/acceptancedata_equal_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
115
domain/consensus/model/blockrelations_equal_clone_test.go
Normal file
115
domain/consensus/model/blockrelations_equal_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
375
domain/consensus/model/externalapi/block_equal_clone_test.go
Normal file
375
domain/consensus/model/externalapi/block_equal_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
45
domain/consensus/model/externalapi/blockinfo_clone_test.go
Normal file
45
domain/consensus/model/externalapi/blockinfo_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
59
domain/consensus/model/externalapi/coinbase_clone_test.go
Normal file
59
domain/consensus/model/externalapi/coinbase_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
238
domain/consensus/model/externalapi/equal_test.go
Normal file
238
domain/consensus/model/externalapi/equal_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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))
|
||||
|
119
domain/consensus/model/externalapi/hash_clone_equal_test.go
Normal file
119
domain/consensus/model/externalapi/hash_clone_equal_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
126
domain/consensus/model/externalapi/sync_equal_clone_test.go
Normal file
126
domain/consensus/model/externalapi/sync_equal_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
1133
domain/consensus/model/externalapi/transaction_equal_clone_test.go
Normal file
1133
domain/consensus/model/externalapi/transaction_equal_clone_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
296
domain/consensus/model/reachabilitydata_equal_clone_test.go
Normal file
296
domain/consensus/model/reachabilitydata_equal_clone_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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!")
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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])
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -20,7 +20,7 @@ func (s *selectedChildIterator) Next() bool {
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
if *child == *model.VirtualBlockHash {
|
||||
if child.Equal(model.VirtualBlockHash) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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{}{}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 "+
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
113
domain/consensus/utils/utxo/utxo_entry_test.go
Normal file
113
domain/consensus/utils/utxo/utxo_entry_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user