Skip to content

Commit

Permalink
chain_bridge: fetch block headers over blocks
Browse files Browse the repository at this point in the history
In this commit, we update the header verifier to use the new
GetBlockHeader RPC when supported, and avoid fetching a full block.
This improves the reliability of proof validation and universe sync for
light clients.
  • Loading branch information
jharveyb committed Nov 7, 2023
1 parent 62668e5 commit 3c4375c
Showing 1 changed file with 38 additions and 1 deletion.
39 changes: 38 additions & 1 deletion chain_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/taproot-assets/tapgarden"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
)

Expand Down Expand Up @@ -79,6 +80,19 @@ func (l *LndRpcChainBridge) GetBlock(ctx context.Context,
return block, nil
}

// GetBlockHeader returns a block header given its hash.
func (l *LndRpcChainBridge) GetBlockHeader(ctx context.Context,
hash chainhash.Hash) (*wire.BlockHeader, error) {

header, err := l.lnd.ChainKit.GetBlockHeader(ctx, hash)
if err != nil {
return nil, fmt.Errorf("unable to retrieve block header: %w",
err)
}

return header, nil
}

// GetBlockHash returns the hash of the block in the best blockchain at the
// given height.
func (l *LndRpcChainBridge) GetBlockHash(ctx context.Context,
Expand All @@ -93,6 +107,22 @@ func (l *LndRpcChainBridge) GetBlockHash(ctx context.Context,
return blockHash, nil
}

// GetBlockHeaderSupported returns true if the chain backend supports the
// `GetBlockHeader` RPC call.
func (l *LndRpcChainBridge) GetBlockHeaderSupported(ctx context.Context) bool {
getBlockHeaderMinimalVersion := &verrpc.Version{
AppMajor: 0,
AppMinor: 17,
AppPatch: 1,
}

getBlockHeaderUnsupported := lndclient.AssertVersionCompatible(
l.lnd.Version, getBlockHeaderMinimalVersion,
)

return getBlockHeaderUnsupported == nil
}

// VerifyBlock returns an error if a block (with given header and height) is not
// present on-chain. It also checks to ensure that block height corresponds to
// the given block header.
Expand Down Expand Up @@ -121,7 +151,14 @@ func (l *LndRpcChainBridge) VerifyBlock(ctx context.Context,
"expectedHash: %s)", height, hash, expectedHash)
}

// Ensure that the block header corresponds to a block on-chain.
// Ensure that the block header corresponds to a block on-chain. Fetch
// only the corresponding block header and not the entire block if
// supported.
if l.GetBlockHeaderSupported(ctx) {
_, err = l.GetBlockHeader(ctx, header.BlockHash())
return err
}

_, err = l.GetBlock(ctx, header.BlockHash())
return err
}
Expand Down

0 comments on commit 3c4375c

Please sign in to comment.