diff --git a/blockdag/accept_test.go b/blockdag/accept_test.go index c1c4bf3e0..452f73083 100644 --- a/blockdag/accept_test.go +++ b/blockdag/accept_test.go @@ -1,18 +1,19 @@ package blockdag import ( - "bou.ke/monkey" "errors" + "strings" + "testing" + + "bou.ke/monkey" "github.com/daglabs/btcd/dagconfig" "github.com/daglabs/btcd/database" "github.com/daglabs/btcd/util" - "strings" - "testing" ) func TestMaybeAcceptBlockErrors(t *testing.T) { // Create a new database and DAG instance to run tests against. - dag, teardownFunc, err := DAGSetup("TestMaybeAcceptBlockErrors", &dagconfig.MainNetParams) + dag, teardownFunc, err := DAGSetup("TestMaybeAcceptBlockErrors", &dagconfig.SimNetParams) if err != nil { t.Fatalf("TestMaybeAcceptBlockErrors: Failed to setup DAG instance: %v", err) } @@ -24,22 +25,22 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { orphanBlockFile := "blk_3B.dat" loadedBlocks, err := loadBlocks(orphanBlockFile) if err != nil { - t.Fatalf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: " + + t.Fatalf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: "+ "Error loading file '%s': %s\n", orphanBlockFile, err) } block := loadedBlocks[0] err = dag.maybeAcceptBlock(block, BFNone) if err == nil { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: "+ "Expected: %s, got: ", ErrPreviousBlockUnknown) } ruleErr, ok := err.(RuleError) if !ok { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: "+ "Expected RuleError but got %s", err) } else if ruleErr.ErrorCode != ErrPreviousBlockUnknown { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are missing: "+ "Unexpected error code. Want: %s, got: %s", ErrPreviousBlockUnknown, ruleErr.ErrorCode) } @@ -47,7 +48,7 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { blocksFile := "blk_0_to_4.dat" blocks, err := loadBlocks(blocksFile) if err != nil { - t.Fatalf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: " + + t.Fatalf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: "+ "Error loading file '%s': %s\n", blocksFile, err) } @@ -63,15 +64,15 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { block2 := blocks[2] err = dag.maybeAcceptBlock(block2, BFNone) if err == nil { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: "+ "Expected: %s, got: ", ErrInvalidAncestorBlock) } ruleErr, ok = err.(RuleError) if !ok { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: "+ "Expected RuleError but got %s", err) } else if ruleErr.ErrorCode != ErrInvalidAncestorBlock { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block if its parents are invalid: "+ "Unexpected error. Want: %s, got: %s", ErrInvalidAncestorBlock, ruleErr.ErrorCode) } @@ -83,15 +84,15 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { block2.MsgBlock().Header.Bits = 0 err = dag.maybeAcceptBlock(block2, BFNone) if err == nil { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: "+ "Expected: %s, got: ", ErrUnexpectedDifficulty) } ruleErr, ok = err.(RuleError) if !ok { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: "+ "Expected RuleError but got %s", err) } else if ruleErr.ErrorCode != ErrUnexpectedDifficulty { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the block due to bad context: "+ "Unexpected error. Want: %s, got: %s", ErrUnexpectedDifficulty, ruleErr.ErrorCode) } @@ -105,11 +106,11 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { }) err = dag.maybeAcceptBlock(block2, BFNone) if err == nil { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to database error: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to database error: "+ "Expected: %s, got: ", databaseErrorMessage) } if !strings.Contains(err.Error(), databaseErrorMessage) { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to database error: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to database error: "+ "Unexpected error. Want: %s, got: %s", databaseErrorMessage, err) } monkey.Unpatch(dbStoreBlock) @@ -121,11 +122,11 @@ func TestMaybeAcceptBlockErrors(t *testing.T) { }) err = dag.maybeAcceptBlock(block2, BFNone) if err == nil { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to index error: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to index error: "+ "Expected %s, got: ", indexErrorMessage) } if !strings.Contains(err.Error(), indexErrorMessage) { - t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to index error: " + + t.Errorf("TestMaybeAcceptBlockErrors: rejecting the node due to index error: "+ "Unexpected error. Want: %s, got: %s", indexErrorMessage, err) } monkey.Unpatch((*blockIndex).flushToDB) diff --git a/blockdag/blockindex_test.go b/blockdag/blockindex_test.go index 2e71387cf..ce270d430 100644 --- a/blockdag/blockindex_test.go +++ b/blockdag/blockindex_test.go @@ -1,17 +1,18 @@ package blockdag import ( - "github.com/bouk/monkey" - "github.com/daglabs/btcd/dagconfig" - "github.com/daglabs/btcd/database" - "github.com/pkg/errors" "strings" "testing" "time" + + "bou.ke/monkey" + "github.com/daglabs/btcd/dagconfig" + "github.com/daglabs/btcd/database" + "github.com/pkg/errors" ) func TestAncestorErrors(t *testing.T) { - node := newTestNode(newSet(), int32(0x10000000), 0, time.Unix(0,0), dagconfig.MainNetParams.K) + node := newTestNode(newSet(), int32(0x10000000), 0, time.Unix(0, 0), dagconfig.MainNetParams.K) node.height = 2 ancestor := node.Ancestor(3) if ancestor != nil { @@ -21,7 +22,7 @@ func TestAncestorErrors(t *testing.T) { func TestFlushToDBErrors(t *testing.T) { // Create a new database and DAG instance to run tests against. - dag, teardownFunc, err := DAGSetup("TestMaybeAcceptBlockErrors", &dagconfig.MainNetParams) + dag, teardownFunc, err := DAGSetup("TestFlushToDBErrors", &dagconfig.MainNetParams) if err != nil { t.Fatalf("TestFlushToDBErrors: Failed to setup DAG instance: %s", err) } @@ -30,7 +31,7 @@ func TestFlushToDBErrors(t *testing.T) { // Call flushToDB without anything to flush. This should succeed err = dag.index.flushToDB() if err != nil { - t.Errorf("TestFlushToDBErrors: flushToDB without anything to flush: " + + t.Errorf("TestFlushToDBErrors: flushToDB without anything to flush: "+ "Unexpected flushToDB error: %s", err) } @@ -39,17 +40,17 @@ func TestFlushToDBErrors(t *testing.T) { // Test flushToDB failure due to database error databaseErrorMessage := "database error" - monkey.Patch(dbStoreBlockNode, func (_ database.Tx, _ *blockNode) error{ + monkey.Patch(dbStoreBlockNode, func(_ database.Tx, _ *blockNode) error { return errors.New(databaseErrorMessage) }) err = dag.index.flushToDB() if err == nil { - t.Errorf("TestFlushToDBErrors: flushToDB failure due to database error: " + + t.Errorf("TestFlushToDBErrors: flushToDB failure due to database error: "+ "Expected: %s, got: ", databaseErrorMessage) } if !strings.Contains(err.Error(), databaseErrorMessage) { - t.Errorf("TestFlushToDBErrors: flushToDB failure due to database error: " + + t.Errorf("TestFlushToDBErrors: flushToDB failure due to database error: "+ "Unexpected flushToDB error. Expected: %s, got: %s", databaseErrorMessage, err) } monkey.Unpatch(dbStoreBlockNode) -} \ No newline at end of file +} diff --git a/blockdag/dag_test.go b/blockdag/dag_test.go index 3e818c776..50aad9e84 100644 --- a/blockdag/dag_test.go +++ b/blockdag/dag_test.go @@ -36,18 +36,16 @@ func TestHaveBlock(t *testing.T) { for _, file := range testFiles { blockTmp, err := loadBlocks(file) if err != nil { - t.Errorf("Error loading file: %v\n", err) - return + t.Fatalf("Error loading file: %v\n", err) } blocks = append(blocks, blockTmp...) } // Create a new database and chain instance to run tests against. dag, teardownFunc, err := DAGSetup("haveblock", - &dagconfig.MainNetParams) + &dagconfig.SimNetParams) if err != nil { - t.Errorf("Failed to setup chain instance: %v", err) - return + t.Fatalf("Failed to setup chain instance: %v", err) } defer teardownFunc() @@ -58,16 +56,15 @@ func TestHaveBlock(t *testing.T) { for i := 1; i < len(blocks); i++ { isOrphan, err := dag.ProcessBlock(blocks[i], BFNone) if err != nil { - t.Errorf("ProcessBlock fail on block %v: %v\n", i, err) - return + t.Fatalf("ProcessBlock fail on block %v: %v\n", i, err) } if isOrphan { - t.Errorf("ProcessBlock incorrectly returned block %v "+ + t.Fatalf("ProcessBlock incorrectly returned block %v "+ "is an orphan\n", i) - return } } + // Test a block with related parents testFiles = []string{ "blk_3C.dat", } @@ -75,35 +72,60 @@ func TestHaveBlock(t *testing.T) { for _, file := range testFiles { blockTmp, err := loadBlocks(file) if err != nil { - t.Errorf("Error loading file: %v\n", err) - return + t.Fatalf("Error loading file: %v\n", err) } blocks = append(blocks, blockTmp...) } isOrphan, err := dag.ProcessBlock(blocks[6], BFNone) - // Block 3c should fail to connect since its parents are related. (It points to 1 and 2, and 1 is the parent of 2) + // Block 3C should fail to connect since its parents are related. (It points to 1 and 2, and 1 is the parent of 2) if err == nil { - t.Errorf("ProcessBlock for block 3c has no error when expected to have an error\n") - return + t.Fatalf("ProcessBlock for block 3C has no error when expected to have an error\n") } if isOrphan { - t.Errorf("ProcessBlock incorrectly returned block 3c " + + t.Fatalf("ProcessBlock incorrectly returned block 3C " + + "is an orphan\n") + } + + // Test a block with the same input twice + testFiles = []string{ + "blk_3D.dat", + } + + for _, file := range testFiles { + blockTmp, err := loadBlocks(file) + if err != nil { + t.Fatalf("Error loading file: %v\n", err) + } + blocks = append(blocks, blockTmp...) + } + isOrphan, err = dag.ProcessBlock(blocks[7], BFNone) + + // Block 3D should fail to connect since it has a transaction with the same input twice + if err == nil { + t.Fatalf("ProcessBlock for block 3D has no error when expected to have an error\n") + } + rErr, ok := err.(RuleError) + if !ok { + t.Fatalf("ProcessBlock for block 3D expected a RuleError, but got something else\n") + } + if !ok || rErr.ErrorCode != ErrDuplicateTxInputs { + t.Fatalf("ProcessBlock for block 3D expected error code %s but got %s\n", ErrDuplicateTxInputs, rErr.ErrorCode) + } + if isOrphan { + t.Fatalf("ProcessBlock incorrectly returned block 3D " + "is an orphan\n") - return } // Insert an orphan block. isOrphan, err = dag.ProcessBlock(util.NewBlock(&Block100000), BFNone) if err != nil { - t.Errorf("Unable to process block: %v", err) - return + t.Fatalf("Unable to process block: %v", err) } if !isOrphan { - t.Errorf("ProcessBlock indicated block is an not orphan when " + + t.Fatalf("ProcessBlock indicated block is an not orphan when " + "it should be\n") - return } tests := []struct { @@ -111,13 +133,13 @@ func TestHaveBlock(t *testing.T) { want bool }{ // Genesis block should be present. - {hash: dagconfig.MainNetParams.GenesisHash.String(), want: true}, + {hash: dagconfig.SimNetParams.GenesisHash.String(), want: true}, // Block 3b should be present (as a second child of Block 2). - {hash: "00000093c8f2ab3444502da0754fc8149d738701aef9b2e0f32f32c078039295", want: true}, + {hash: "00cd35debc62fd60b6fbda1925894db5996c02bcd575a4130fdb4d6071537152", want: true}, // Block 100000 should be present (as an orphan). - {hash: "000000e46b5f4f7bfecff77f2f30f2ab90d08e3c5a55784080f97689bcd92786", want: true}, + {hash: "66cdaddc8884c99ccc46c2f34f579903a223cc12b44c239938af47ee0c7193b4", want: true}, // Random hashes should not be available. {hash: "123", want: false}, @@ -126,19 +148,16 @@ func TestHaveBlock(t *testing.T) { for i, test := range tests { hash, err := daghash.NewHashFromStr(test.hash) if err != nil { - t.Errorf("NewHashFromStr: %v", err) - continue + t.Fatalf("NewHashFromStr: %v", err) } result, err := dag.HaveBlock(hash) if err != nil { - t.Errorf("HaveBlock #%d unexpected error: %v", i, err) - return + t.Fatalf("HaveBlock #%d unexpected error: %v", i, err) } if result != test.want { - t.Errorf("HaveBlock #%d got %v want %v", i, result, + t.Fatalf("HaveBlock #%d got %v want %v", i, result, test.want) - continue } } } @@ -745,7 +764,7 @@ func testErrorThroughPatching(t *testing.T, expectedErrorMessage string, targetF } // Create a new database and dag instance to run tests against. - dag, teardownFunc, err := DAGSetup("testErrorThroughPatching", &dagconfig.MainNetParams) + dag, teardownFunc, err := DAGSetup("testErrorThroughPatching", &dagconfig.SimNetParams) if err != nil { t.Fatalf("Failed to setup dag instance: %v", err) } @@ -759,7 +778,12 @@ func testErrorThroughPatching(t *testing.T, expectedErrorMessage string, targetF err = nil for i := 1; i < len(blocks); i++ { - _, err = dag.ProcessBlock(blocks[i], BFNone) + var isOrphan bool + isOrphan, err = dag.ProcessBlock(blocks[i], BFNone) + if isOrphan { + t.Fatalf("ProcessBlock incorrectly returned block %v "+ + "is an orphan\n", i) + } if err != nil { break } diff --git a/blockdag/notifications_test.go b/blockdag/notifications_test.go index aeb5bc1ae..857dd7cca 100644 --- a/blockdag/notifications_test.go +++ b/blockdag/notifications_test.go @@ -17,11 +17,11 @@ func TestNotifications(t *testing.T) { t.Fatalf("Error loading file: %v\n", err) } - // Create a new database and chain instance to run tests against. - chain, teardownFunc, err := DAGSetup("notifications", - &dagconfig.MainNetParams) + // Create a new database and dag instance to run tests against. + dag, teardownFunc, err := DAGSetup("notifications", + &dagconfig.SimNetParams) if err != nil { - t.Fatalf("Failed to setup chain instance: %v", err) + t.Fatalf("Failed to setup dag instance: %v", err) } defer teardownFunc() @@ -36,10 +36,14 @@ func TestNotifications(t *testing.T) { // times. const numSubscribers = 3 for i := 0; i < numSubscribers; i++ { - chain.Subscribe(callback) + dag.Subscribe(callback) } - _, err = chain.ProcessBlock(blocks[1], BFNone) + isOrphan, err := dag.ProcessBlock(blocks[1], BFNone) + if isOrphan { + t.Fatalf("ProcessBlock incorrectly returned block " + + "is an orphan\n") + } if err != nil { t.Fatalf("ProcessBlock fail on block 1: %v\n", err) } diff --git a/blockdag/testdata/blk_0_to_4.dat b/blockdag/testdata/blk_0_to_4.dat index 1a6e481d9..8f48ac941 100644 Binary files a/blockdag/testdata/blk_0_to_4.dat and b/blockdag/testdata/blk_0_to_4.dat differ diff --git a/blockdag/testdata/blk_3A.dat b/blockdag/testdata/blk_3A.dat index 39e8340f9..b683b1512 100644 Binary files a/blockdag/testdata/blk_3A.dat and b/blockdag/testdata/blk_3A.dat differ diff --git a/blockdag/testdata/blk_3B.dat b/blockdag/testdata/blk_3B.dat index 0c949f54c..2b0261528 100644 Binary files a/blockdag/testdata/blk_3B.dat and b/blockdag/testdata/blk_3B.dat differ diff --git a/blockdag/testdata/blk_3C.dat b/blockdag/testdata/blk_3C.dat index 83bb7285a..34468ae51 100644 Binary files a/blockdag/testdata/blk_3C.dat and b/blockdag/testdata/blk_3C.dat differ diff --git a/blockdag/testdata/blk_3D.dat b/blockdag/testdata/blk_3D.dat new file mode 100644 index 000000000..eb91b23cb Binary files /dev/null and b/blockdag/testdata/blk_3D.dat differ diff --git a/blockdag/validate.go b/blockdag/validate.go index 9d365047c..8cac2ac2c 100644 --- a/blockdag/validate.go +++ b/blockdag/validate.go @@ -435,7 +435,7 @@ func checkBlockParentsOrder(header *wire.BlockHeader) error { sortedHashes = append(sortedHashes, hash) } sort.Slice(sortedHashes, func(i, j int) bool { - return daghash.Less(&sortedHashes[j], &sortedHashes[i]) + return daghash.Less(&sortedHashes[i], &sortedHashes[j]) }) if !daghash.AreEqual(header.PrevBlocks, sortedHashes) { return ruleError(ErrWrongParentsOrder, "block parents are not ordered by hash") diff --git a/blockdag/validate_test.go b/blockdag/validate_test.go index bb980ec1d..271eb258b 100644 --- a/blockdag/validate_test.go +++ b/blockdag/validate_test.go @@ -68,7 +68,7 @@ func TestSequenceLocksActive(t *testing.T) { func TestCheckConnectBlockTemplate(t *testing.T) { // Create a new database and chain instance to run tests against. dag, teardownFunc, err := DAGSetup("checkconnectblocktemplate", - &dagconfig.MainNetParams) + &dagconfig.SimNetParams) if err != nil { t.Errorf("Failed to setup chain instance: %v", err) return @@ -190,9 +190,9 @@ func TestCheckBlockSanity(t *testing.T) { 0x6f, 0xff, 0xfb, 0xb7, 0xdc, 0x39, 0x9d, 0x76, 0x8d, 0xb0, 0xe1, 0x9c, 0x2e, 0x6d, 0x22, 0xd9, }), // f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 - Timestamp: time.Unix(0x5b7142b4, 0), // 2018-07-19 15:11:10 +0000 UTC + Timestamp: time.Unix(0x5bbc64c9, 0), // 2018-10-09 08:17:35 +0000 UTC Bits: 0x1e00ffff, // 503382015 - Nonce: 0xa05433ab, // 2148280951 + Nonce: 0xe00edcf9, // 3759070457 }, Transactions: []*wire.MsgTx{ { @@ -551,17 +551,17 @@ var Block100000 = wire.MsgBlock{ NumPrevBlocks: 2, PrevBlocks: []daghash.Hash{ [32]byte{ // Make go vet happy. - 0xa5, 0x60, 0xe4, 0x59, 0x61, 0x5d, 0xbb, 0x4e, - 0xae, 0x33, 0x40, 0x2a, 0xc0, 0xb8, 0x8a, 0xb6, - 0x53, 0xc5, 0x11, 0xe3, 0x35, 0xd0, 0xa6, 0x1e, - 0x0a, 0xc4, 0x06, 0x96, 0x97, 0x00, 0x00, 0x00, - }, // MainNet genesis + 0x16, 0x5e, 0x38, 0xe8, 0xb3, 0x91, 0x45, 0x95, + 0xd9, 0xc6, 0x41, 0xf3, 0xb8, 0xee, 0xc2, 0xf3, + 0x46, 0x11, 0x89, 0x6b, 0x82, 0x1a, 0x68, 0x3b, + 0x7a, 0x4e, 0xde, 0xfe, 0x2c, 0x00, 0x00, 0x00, + }, [32]byte{ // Make go vet happy. - 0x2a, 0x9a, 0x2a, 0xe4, 0x3b, 0xc1, 0x6b, 0x55, - 0x06, 0x39, 0xc2, 0xe6, 0xbb, 0x4a, 0xec, 0xeb, - 0x7a, 0x49, 0x7c, 0xe9, 0xf3, 0x60, 0x20, 0x7d, - 0x63, 0xc7, 0x26, 0x89, 0xf6, 0x00, 0x00, 0x00, - }, // SimNet genesis + 0x4b, 0xb0, 0x75, 0x35, 0xdf, 0xd5, 0x8e, 0x0b, + 0x3c, 0xd6, 0x4f, 0xd7, 0x15, 0x52, 0x80, 0x87, + 0x2a, 0x04, 0x71, 0xbc, 0xf8, 0x30, 0x95, 0x52, + 0x6a, 0xce, 0x0e, 0x38, 0xc6, 0x00, 0x00, 0x00, + }, }, MerkleRoot: daghash.Hash([32]byte{ // Make go vet happy. 0xc0, 0x92, 0x53, 0x8f, 0x6f, 0xf7, 0xf5, 0x24, @@ -569,9 +569,9 @@ var Block100000 = wire.MsgBlock{ 0x6f, 0xff, 0xfb, 0xb7, 0xdc, 0x39, 0x9d, 0x76, 0x8d, 0xb0, 0xe1, 0x9c, 0x2e, 0x6d, 0x22, 0xd9, }), // f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 - Timestamp: time.Unix(0x5bb9f3b4, 0), // 2018-07-19 15:11:10 +0000 UTC - Bits: 0x1e00ffff, // 503382015 - Nonce: 0x203602e3, // 2148280951 + Timestamp: time.Unix(0x5bbc7588, 0), // 2018-10-09 07:49:35 +0000 UTC + Bits: 0x207fffff, // 503382015 + Nonce: 0xdffffff9, }, Transactions: []*wire.MsgTx{ {