Fix channel manager race panic
authorMax Fang <protonmail.com@maxfa.ng>
Tue, 18 Oct 2022 01:57:58 +0000 (18:57 -0700)
committerMax Fang <protonmail.com@maxfa.ng>
Wed, 2 Nov 2022 20:16:26 +0000 (13:16 -0700)
commit2d9247696647e3e7ad5737164b82d6eabcd648ab
tree4ba075e174d98babc242d5d9403155d3a3f053d1
parente747233c70ca640124e34fdacb6f8609af1d9360
Fix channel manager race panic

The race:
- (1) If a channel manager is starting for the first time, it gets its
  initial block hash by calling BlockSource::get_blockchain_info() and
  constructing a BestBlock out of that.
- (2) During the initial chain sync, if chain_tip.is_none() then the
  best chain_tip is retrieved using
  lightning_block_sync::init::validate_best_block_header() which
  similarly uses BlockSource::get_best_block()
- If blocks were mined between (1) and (2), the channel manager’s block
  hash will be at a lower height than that of the block hash contained
  inside the chain_tip fed to the SpvClient. Suppose that this results
  in the channel manager being at block 1 and the SpvClient being at
  block 2. Once block 3 comes in and the SpvClient detects it via
  poll_best_tip(), the SpvClient computes the ChainDifference between
  its saved chain_tip value and block 3, concluding that it just needs
  to connect block 3. However, when Listen::filtered_block_connected is
  called using the data in block 3, the channel manager panics with
  “Blocks must be connected in chain-order - the connected header must
  build on the last connected header” - because block 3’s prev block
  hash is block 2’s block hash, rather than block 1’s block hash which
  the channel manager expects

This commit fixes it by removing the fresh channel manager's query to
the block source, instead deriving its best block from the validated
block header using a new `.to_best_block()` method.
src/main.rs