-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rpcclient, integration: Add invalidateblock and reconsiderblock
invalidateblock and reconsiderblock are added to the rpcclient package and an integration test is added to test the added functions.
- Loading branch information
1 parent
cd5e5ba
commit 1cb4d3a
Showing
1 changed file
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
package integration | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/btcsuite/btcd/chaincfg" | ||
"github.com/btcsuite/btcd/integration/rpctest" | ||
) | ||
|
||
func TestInvalidateAndReconsiderBlock(t *testing.T) { | ||
// Set up regtest chain. | ||
r, err := rpctest.New(&chaincfg.RegressionNetParams, nil, nil, "") | ||
if err != nil { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail."+ | ||
"Unable to create primary harness: %v", err) | ||
} | ||
if err := r.SetUp(true, 0); err != nil { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Unable to setup test chain: %v", err) | ||
} | ||
defer r.TearDown() | ||
|
||
// Generate 4 blocks. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 -> 2 -> 3 -> 4 | ||
_, err = r.Client.Generate(4) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Cache the active tip hash. | ||
block4ActiveTipHash, err := r.Client.GetBestBlockHash() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Cache block 1 hash as this will be our chaintip after we invalidate block 2. | ||
block1Hash, err := r.Client.GetBlockHash(1) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Invalidate block 2. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 (active) | ||
// \ -> 2 -> 3 -> 4 (invalid) | ||
block2Hash, err := r.Client.GetBlockHash(2) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
err = r.Client.InvalidateBlock(block2Hash) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Assert that block 1 is the active chaintip. | ||
bestHash, err := r.Client.GetBestBlockHash() | ||
if *bestHash != *block1Hash { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected the "+ | ||
"best block hash to be block 1 with hash %s but got %s", | ||
block1Hash.String(), bestHash.String()) | ||
} | ||
|
||
// Generate 2 blocks. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 -> 2a -> 3a (active) | ||
// \ -> 2 -> 3 -> 4 (invalid) | ||
_, err = r.Client.Generate(2) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Cache the active tip hash for the current active tip. | ||
block3aActiveTipHash, err := r.Client.GetBestBlockHash() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
tips, err := r.Client.GetChainTips() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Assert that there are two branches. | ||
if len(tips) != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected 2 chaintips but got %d", len(tips)) | ||
} | ||
|
||
for _, tip := range tips { | ||
if tip.Hash == block4ActiveTipHash.String() && | ||
tip.Status != "invalid" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"invalidated branch tip of %s to be invalid but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
} | ||
|
||
// Reconsider the invalidated block 2. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 -> 2a -> 3a (valid-fork) | ||
// \ -> 2 -> 3 -> 4 (active) | ||
err = r.Client.ReconsiderBlock(block2Hash) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
tips, err = r.Client.GetChainTips() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
// Assert that there are two branches. | ||
if len(tips) != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected 2 chaintips but got %d", len(tips)) | ||
} | ||
|
||
var checkedTips int | ||
for _, tip := range tips { | ||
if tip.Hash == block4ActiveTipHash.String() { | ||
if tip.Status != "active" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"the reconsidered branch tip of %s to be active but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
|
||
checkedTips++ | ||
} | ||
|
||
if tip.Hash == block3aActiveTipHash.String() { | ||
if tip.Status != "valid-fork" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"invalidated branch tip of %s to be valid-fork but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
checkedTips++ | ||
} | ||
} | ||
|
||
if checkedTips != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected to check %d chaintips, checked %d", 2, checkedTips) | ||
} | ||
|
||
// Invalidate block 3a. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 -> 2a -> 3a (invalid) | ||
// \ -> 2 -> 3 -> 4 (active) | ||
err = r.Client.InvalidateBlock(block3aActiveTipHash) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
tips, err = r.Client.GetChainTips() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Assert that there are two branches. | ||
if len(tips) != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected 2 chaintips but got %d", len(tips)) | ||
} | ||
|
||
checkedTips = 0 | ||
for _, tip := range tips { | ||
if tip.Hash == block4ActiveTipHash.String() { | ||
if tip.Status != "active" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"an active branch tip of %s but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
|
||
checkedTips++ | ||
} | ||
|
||
if tip.Hash == block3aActiveTipHash.String() { | ||
if tip.Status != "invalid" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"the invalidated tip of %s to be invalid but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
checkedTips++ | ||
} | ||
} | ||
|
||
if checkedTips != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected to check %d chaintips, checked %d", 2, checkedTips) | ||
} | ||
|
||
// Reconsider block 3a. | ||
// | ||
// Our chain view looks like so: | ||
// (genesis block) -> 1 -> 2a -> 3a (valid-fork) | ||
// \ -> 2 -> 3 -> 4 (active) | ||
err = r.Client.ReconsiderBlock(block3aActiveTipHash) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
tips, err = r.Client.GetChainTips() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Assert that there are two branches. | ||
if len(tips) != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected 2 chaintips but got %d", len(tips)) | ||
} | ||
|
||
checkedTips = 0 | ||
for _, tip := range tips { | ||
if tip.Hash == block4ActiveTipHash.String() { | ||
if tip.Status != "active" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"an active branch tip of %s but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
|
||
checkedTips++ | ||
} | ||
|
||
if tip.Hash == block3aActiveTipHash.String() { | ||
if tip.Status != "valid-fork" { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ | ||
"the reconsidered tip of %s to be a valid-fork but got %s", | ||
tip.Hash, tip.Status) | ||
} | ||
checkedTips++ | ||
} | ||
} | ||
|
||
if checkedTips != 2 { | ||
t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ | ||
"Expected to check %d chaintips, checked %d", 2, checkedTips) | ||
} | ||
} |