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 19, 2024
1 parent cd5e5ba commit 1cb4d3a
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 1cb4d3a

Please sign in to comment.