diff --git a/lntest/harness_node.go b/lntest/harness_node.go index 3b1e8bebc..74bb544f1 100644 --- a/lntest/harness_node.go +++ b/lntest/harness_node.go @@ -367,6 +367,7 @@ type HarnessNode struct { WatchtowerClient wtclientrpc.WatchtowerClientClient StateClient lnrpc.StateClient ChainClient chainrpc.ChainNotifierClient + ChainKit chainrpc.ChainKitClient } // RPCClients wraps a list of RPC clients into a single struct for easier @@ -385,6 +386,7 @@ type RPCClients struct { WatchtowerClient wtclientrpc.WatchtowerClientClient State lnrpc.StateClient ChainClient chainrpc.ChainNotifierClient + ChainKit chainrpc.ChainKitClient } // Assert *HarnessNode implements the lnrpc.LightningClient interface. @@ -938,6 +940,7 @@ func (hn *HarnessNode) InitRPCClients(c *grpc.ClientConn) { Signer: signrpc.NewSignerClient(c), State: lnrpc.NewStateClient(c), ChainClient: chainrpc.NewChainNotifierClient(c), + ChainKit: chainrpc.NewChainKitClient(c), } } @@ -960,6 +963,7 @@ func (hn *HarnessNode) initLightningClient() error { hn.PeersClient = peersrpc.NewPeersClient(conn) hn.StateClient = lnrpc.NewStateClient(conn) hn.ChainClient = chainrpc.NewChainNotifierClient(conn) + hn.ChainKit = chainrpc.NewChainKitClient(conn) // Wait until the server is fully started. if err := hn.WaitUntilServerActive(); err != nil { diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index c8a2d0266..d08aab674 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -219,4 +219,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "failing link", TestFunc: testFailingChannel, }, + { + Name: "chain kit", + TestFunc: testChainKit, + }, } diff --git a/lntest/itest/lnd_onchain_test.go b/lntest/itest/lnd_onchain_test.go index add35d8a0..31af68363 100644 --- a/lntest/itest/lnd_onchain_test.go +++ b/lntest/itest/lnd_onchain_test.go @@ -12,7 +12,9 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/chainrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" + "github.com/lightningnetwork/lnd/lntemp" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" @@ -20,6 +22,72 @@ import ( "github.com/stretchr/testify/require" ) +// testChainKit tests ChainKit RPC endpoints. +func testChainKit(ht *lntemp.HarnessTest) { + ctx := context.Background() + + // Test functions registered as test cases spin up separate nodes during + // execution. By calling sub-test functions as seen below we avoid the + // need to start separate nodes. + testChainKitGetBlock(ctx, ht) + testChainKitGetBlockHash(ctx, ht) +} + +// testChainKitGetBlock ensures that given a block hash, the RPC endpoint +// returns the correct target block. +func testChainKitGetBlock(ctx context.Context, ht *lntemp.HarnessTest) { + // Get best block hash. + bestBlockRes, err := ht.Alice.RPC.ChainKit.GetBestBlock( + ctx, &chainrpc.GetBestBlockRequest{}, + ) + require.NoError(ht, err) + var bestBlockHash chainhash.Hash + err = bestBlockHash.SetBytes(bestBlockRes.BlockHash) + require.NoError(ht, err) + + // Retrieve the best block by hash. + getBlockRes, err := ht.Alice.RPC.ChainKit.GetBlock( + ctx, &chainrpc.GetBlockRequest{ + BlockHash: bestBlockHash.CloneBytes(), + }, + ) + require.NoError(ht, err) + + // Deserialize the block which was retrieved by hash. + msgBlock := &wire.MsgBlock{} + blockReader := bytes.NewReader(getBlockRes.RawBlock) + err = msgBlock.Deserialize(blockReader) + require.NoError(ht, err) + + // Ensure best block hash is the same as retrieved block hash. + expected := bestBlockHash + actual := msgBlock.BlockHash() + require.Equal(ht, expected, actual) +} + +// testChainKitGetBlockHash ensures that given a block height, the RPC endpoint +// returns the correct target block hash. +func testChainKitGetBlockHash(ctx context.Context, ht *lntemp.HarnessTest) { + // Get best block hash. + bestBlockRes, err := ht.Alice.RPC.ChainKit.GetBestBlock( + ctx, &chainrpc.GetBestBlockRequest{}, + ) + require.NoError(ht, err) + + // Retrieve the block hash at best block height. + getBlockHashRes, err := ht.Alice.RPC.ChainKit.GetBlockHash( + ctx, &chainrpc.GetBlockHashRequest{ + BlockHeight: int64(bestBlockRes.BlockHeight), + }, + ) + require.NoError(ht, err) + + // Ensure best block hash is the same as retrieved block hash. + expected := bestBlockRes.BlockHash + actual := getBlockHashRes.BlockHash + require.Equal(ht, expected, actual) +} + // testCPFP ensures that the daemon can bump an unconfirmed transaction's fee // rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction. //