Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chainkit: expose getblockheader #8111

Merged
merged 5 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions cmd/lncli/chainrpc_active.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func chainCommands() []cli.Command {
getBlockCommand,
getBestBlockCommand,
getBlockHashCommand,
getBlockHeaderCommand,
},
},
}
Expand Down Expand Up @@ -113,6 +114,45 @@ func getBlock(ctx *cli.Context) error {
return nil
}

var getBlockHeaderCommand = cli.Command{
Name: "getblockheader",
Usage: "Get a block header.",
Category: "On-chain",
Description: "Returns a block header with a particular block hash.",
ArgsUsage: "hash",
Action: actionDecorator(getBlockHeader),
}

func getBlockHeader(ctx *cli.Context) error {
ctxc := getContext()
args := ctx.Args()

// Display the command's help message if we do not have the expected
// number of arguments/flags.
if !args.Present() {
return cli.ShowCommandHelp(ctx, "getblockheader")
}

blockHash, err := chainhash.NewHashFromStr(args.First())
if err != nil {
return err
}

req := &chainrpc.GetBlockHeaderRequest{BlockHash: blockHash[:]}

client, cleanUp := getChainClient(ctx)
defer cleanUp()

resp, err := client.GetBlockHeader(ctxc, req)
if err != nil {
return err
}

printRespJSON(resp)

return nil
}

var getBestBlockCommand = cli.Command{
Name: "getbestblock",
Category: "On-chain",
Expand Down
8 changes: 4 additions & 4 deletions cmd/lncli/neutrino_active.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,16 @@ func isBanned(ctx *cli.Context) error {
return nil
}

var getBlockHeaderCommand = cli.Command{
var getBlockHeaderNeutrinoCommand = cli.Command{
jharveyb marked this conversation as resolved.
Show resolved Hide resolved
Name: "getblockheader",
Usage: "Get a block header.",
Category: "Neutrino",
Description: "Returns a block header with a particular block hash.",
ArgsUsage: "hash",
Action: actionDecorator(getBlockHeader),
Action: actionDecorator(getBlockHeaderNeutrino),
}

func getBlockHeader(ctx *cli.Context) error {
func getBlockHeaderNeutrino(ctx *cli.Context) error {
ctxc := getContext()
args := ctx.Args()

Expand Down Expand Up @@ -239,7 +239,7 @@ func neutrinoCommands() []cli.Command {
addPeerCommand,
disconnectPeerCommand,
isBannedCommand,
getBlockHeaderCommand,
getBlockHeaderNeutrinoCommand,
getCFilterCommand,
},
},
Expand Down
4 changes: 4 additions & 0 deletions contractcourt/channel_arbitrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ func (*mockChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
return nil, nil
}

func (*mockChainIO) GetBlockHeader(*chainhash.Hash) (*wire.BlockHeader, error) {
return nil, nil
}

type chanArbTestCtx struct {
t *testing.T

Expand Down
4 changes: 4 additions & 0 deletions docs/release-notes/release-notes-0.17.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
instead.

## RPC Additions

* [`chainrpc` `GetBlockHeader`](https://github.com/lightningnetwork/lnd/pull/8111)
can be used to get block headers with any chain backend.

## lncli Additions

# Improvements
Expand Down
44 changes: 44 additions & 0 deletions itest/lnd_onchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func testChainKit(ht *lntest.HarnessTest) {
// during execution. By calling sub-test functions as seen below we
// avoid the need to start separate nodes.
testChainKitGetBlock(ht)
testChainKitGetBlockHeader(ht)
testChainKitGetBlockHash(ht)
testChainKitSendOutputsAnchorReserve(ht)
}
Expand Down Expand Up @@ -58,6 +59,49 @@ func testChainKitGetBlock(ht *lntest.HarnessTest) {
require.Equal(ht, expected, actual)
}

// testChainKitGetBlockHeader ensures that given a block hash, the RPC endpoint
// returns the correct target block header.
func testChainKitGetBlockHeader(ht *lntest.HarnessTest) {
// Get best block hash.
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)

var (
bestBlockHash chainhash.Hash
bestBlockHeader wire.BlockHeader
msgBlock = &wire.MsgBlock{}
)
err := bestBlockHash.SetBytes(bestBlockRes.BlockHash)
require.NoError(ht, err)

// Retrieve the best block by hash.
getBlockReq := &chainrpc.GetBlockRequest{
BlockHash: bestBlockHash[:],
}
getBlockRes := ht.Alice.RPC.GetBlock(getBlockReq)

// Deserialize the block which was retrieved by hash.
blockReader := bytes.NewReader(getBlockRes.RawBlock)
err = msgBlock.Deserialize(blockReader)
require.NoError(ht, err)

// Retrieve the block header for the best block.
getBlockHeaderReq := &chainrpc.GetBlockHeaderRequest{
BlockHash: bestBlockHash[:],
}
getBlockHeaderRes := ht.Alice.RPC.GetBlockHeader(getBlockHeaderReq)

// Deserialize the block header which was retrieved by hash.
blockHeaderReader := bytes.NewReader(getBlockHeaderRes.RawBlockHeader)
err = bestBlockHeader.Deserialize(blockHeaderReader)
require.NoError(ht, err)

// Ensure the header of the best block is the same as retrieved block
// header.
expected := bestBlockHeader
actual := msgBlock.Header
require.Equal(ht, expected, actual)
}

// testChainKitGetBlockHash ensures that given a block height, the RPC endpoint
// returns the correct target block hash.
func testChainKitGetBlockHash(ht *lntest.HarnessTest) {
Expand Down
29 changes: 29 additions & 0 deletions lnrpc/chainrpc/chain_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ var (
Entity: "onchain",
Action: "read",
}},
"/chainrpc.ChainKit/GetBlockHeader": {{
Entity: "onchain",
Action: "read",
}},
"/chainrpc.ChainKit/GetBestBlock": {{
Entity: "onchain",
Action: "read",
Expand Down Expand Up @@ -293,6 +297,31 @@ func (s *Server) GetBlock(_ context.Context,
return &GetBlockResponse{RawBlock: rawBlock}, nil
}

// GetBlockHeader returns a block header given the corresponding block hash.
func (s *Server) GetBlockHeader(_ context.Context,
jharveyb marked this conversation as resolved.
Show resolved Hide resolved
in *GetBlockHeaderRequest) (*GetBlockHeaderResponse, error) {

// We'll start by reconstructing the RPC request into what the
// underlying chain functionality expects.
var blockHash chainhash.Hash
copy(blockHash[:], in.BlockHash)

blockHeader, err := s.cfg.Chain.GetBlockHeader(&blockHash)
if err != nil {
return nil, err
}

// Serialize block header for RPC response.
var headerBuf bytes.Buffer
err = blockHeader.Serialize(&headerBuf)
if err != nil {
return nil, err
}
rawHeader := headerBuf.Bytes()

return &GetBlockHeaderResponse{RawBlockHeader: rawHeader}, nil
}

// GetBestBlock returns the latest block hash and current height of the valid
// most-work chain.
func (s *Server) GetBestBlock(_ context.Context,
Expand Down
Loading
Loading