Skip to content

Headers-first sync never gets going #5138

@gavinandresen

Description

@gavinandresen

I ran into this writing a regression test; it is a weird edge case with the headers-first logic.

The setup:

Create a 200-block blockchain with blocks that have 'old' timestamps
(see https://github.com/gavinandresen/bitcoin-git/tree/chainalerts for code to do that)

Start up two nodes, both of which read in that 200-block chain.
Connect node_b to node_a.
Have node_b generate a new block.
RESULT: node_a ignores it.

Here's -debug=net output from node_b:

UpdateTip: new best=00004900679d6cfbac61afa36cd6fda7f27af0e69e909373b947567d6dcc1d74  height=201
sending: inv (37 bytes) peer=1
received: getheaders (645 bytes) peer=1
getheaders 201 to 00004900679d6cfbac61afa36cd6fda7f27af0e69e909373b947567d6dcc1d74 from peer=1
sending: headers (82 bytes) peer=1

and from node_a:

getheaders 200 to 0000000000000000000000000000000000000000000000000000000000000000 from peer=1
got inv: block 00004900679d6cfbac61afa36cd6fda7f27af0e69e909373b947567d6dcc1d74  new peer=1
received: headers (82 bytes) peer=1

I think the bug is because since both nodes just started up and read blocks from disk, pindexLastCommonBlock is NULL -- it should be block 200. I think.

(lldb) p state
(<anonymous>::CNodeState) $60 = {
  nMisbehavior = 0
  fShouldBan = false
  name = "127.0.0.1:59518"
  rejects = size=0 {}
  pindexBestKnownBlock = 0x0000000105122e10
  hashLastUnknownBlock = {
    base_uint<256> = {
      pn = ([0] = 0, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0)
    }
  }
  pindexLastCommonBlock = 0x0000000000000000
  fSyncStarted = false
  nStallingSince = 0
  vBlocksInFlight = size=0 {}
  nBlocksInFlight = 0
}

Anyway, fFetch is never set to true on line 4422:
-> 4422 bool fFetch = !pto->fInbound || (pindexBestHeader && (state.pindexLastCommonBlock ? state.pindexLastCommonBlock->nHeight : 0) + 144 > pindexBestHeader->nHeight);

... because state.pindexLastCommonBlock is NULL, and 0+144 < 201

Writing this all down... would it make sense to fix this by always fetching when state.pindexLastCommonBlock is NULL ?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions