From b251e044b5a6747cea2933165be0d476466e5852 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Tue, 14 Mar 2023 12:15:13 -0500 Subject: [PATCH] client/asset/dcrd: spv block header confs is -1 for orphan This fixes (*spvWallet).GetBlockHeader so that it correctly considers the main chain status of the block when computing confirmations and retrieving NextHash. The new function matches the behavior of dcrd and dcrwallet's getblockheader handlers. --- client/asset/dcr/spv.go | 29 +++++++++++++++++++---------- client/asset/dcr/spv_test.go | 14 +++++++++++++- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/client/asset/dcr/spv.go b/client/asset/dcr/spv.go index 696e572262..9e4e9abd3e 100644 --- a/client/asset/dcr/spv.go +++ b/client/asset/dcr/spv.go @@ -587,23 +587,32 @@ func (w *spvWallet) GetBlockHeader(ctx context.Context, blockHash *chainhash.Has return nil, err } - _, tipHeight := w.MainChainTip(ctx) - if tipHeight < int32(hdr.Height) { - return nil, errors.New("sumpin's wrong with our tip") - } - + // Get next block hash unless there are none. var nextHash *chainhash.Hash - if tipHeight > int32(hdr.Height) { - nextHash, err = w.GetBlockHash(ctx, int64(hdr.Height)+1) - if err != nil { - return nil, fmt.Errorf("error getting next hash for block %q: %w", blockHash, err) + confirmations := int64(-1) + mainChainHasBlock, _, err := w.BlockInMainChain(ctx, blockHash) + if err != nil { + return nil, fmt.Errorf("error checking if block is in mainchain: %w", err) + } + if mainChainHasBlock { + _, tipHeight := w.MainChainTip(ctx) + if int32(hdr.Height) < tipHeight { + nextHash, err = w.GetBlockHash(ctx, int64(hdr.Height)+1) + if err != nil { + return nil, fmt.Errorf("error getting next hash for block %q: %w", blockHash, err) + } + } + if int32(hdr.Height) <= tipHeight { + confirmations = int64(tipHeight) - int64(hdr.Height) + 1 + } else { // if tip is less, may be rolling back, so just mock dcrd/dcrwallet + confirmations = 0 } } return &BlockHeader{ BlockHeader: hdr, MedianTime: medianTime, - Confirmations: int64(uint32(tipHeight)-hdr.Height) + 1, + Confirmations: confirmations, NextHash: nextHash, }, nil } diff --git a/client/asset/dcr/spv_test.go b/client/asset/dcr/spv_test.go index a738af9cee..1c8bd72a06 100644 --- a/client/asset/dcr/spv_test.go +++ b/client/asset/dcr/spv_test.go @@ -518,6 +518,16 @@ func TestGetBlockHeader(t *testing.T) { t.Fatal("wrong next hash") } + dcrw.mainchainDontHave = true + hdr, err = w.GetBlockHeader(tCtx, &blockHash) + if err != nil { + t.Fatalf("initial success error: %v", err) + } + if hdr.Confirmations != -1 { + t.Fatalf("expected -1 confs for side chain block, got %d", hdr.Confirmations) + } + dcrw.mainchainDontHave = false + // BlockHeader error dcrw.blockHeaderErr[blockHash] = tErr if _, err := w.GetBlockHeader(tCtx, &blockHash); err == nil { @@ -534,8 +544,10 @@ func TestGetBlockHeader(t *testing.T) { // MainChainTip error dcrw.tip.height = 3 - if _, err := w.GetBlockHeader(tCtx, &blockHash); err == nil { + if hdr, err := w.GetBlockHeader(tCtx, &blockHash); err != nil { t.Fatalf("invalid tip height not noticed") + } else if hdr.Confirmations != 0 { + t.Fatalf("confirmations not zero for lower tip height") } dcrw.tip.height = tipHeight