Skip to content

Commit

Permalink
rpcclient, integration: Add invalidateblock and reconsiderblock
Browse files Browse the repository at this point in the history
invalidateblock and reconsiderblock are added to the rpcclient package
and an integration test is added to test the added functions.
  • Loading branch information
kcalvinalvin authored and Crypt-iQ committed Jun 7, 2024
1 parent 68f0be8 commit ec2ecf0
Showing 1 changed file with 244 additions and 0 deletions.
244 changes: 244 additions & 0 deletions integration/invalidate_reconsider_block_test.go
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)
}
}

0 comments on commit ec2ecf0

Please sign in to comment.