github.com/decred/dcrlnd@v0.7.6/lntest/itest/dcrlnd_assertions.go (about)

     1  package itest
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/wire"
    10  	"github.com/decred/dcrlnd/lnrpc"
    11  	"github.com/decred/dcrlnd/lntest"
    12  	"github.com/decred/dcrlnd/lntest/wait"
    13  )
    14  
    15  // assertCleanStateAliceBob ensures the state of the passed test nodes and the
    16  // mempool are in a clean state (no open channels, no txs in the mempool, etc).
    17  func assertCleanStateAliceBob(h *harnessTest, alice, bob *lntest.HarnessNode, net *lntest.NetworkHarness) {
    18  	_, minerHeight, err := net.Miner.Node.GetBestBlock(context.TODO())
    19  	if err != nil {
    20  		h.Fatalf("unable to get best height: %v", err)
    21  	}
    22  
    23  	net.EnsureConnected(h.t, alice, bob)
    24  	assertNodeBlockHeight(h, alice, int32(minerHeight))
    25  	assertNodeBlockHeight(h, bob, int32(minerHeight))
    26  	assertNodeNumChannels(h, alice, 0)
    27  	assertNumPendingChannels(h, alice, 0, 0, 0, 0)
    28  	assertNodeNumChannels(h, bob, 0)
    29  	assertNumPendingChannels(h, bob, 0, 0, 0, 0)
    30  	assertNumUnminedUnspent(h, alice, 0)
    31  	assertNumUnminedUnspent(h, bob, 0)
    32  	waitForNTxsInMempool(net.Miner.Node, 0, minerMempoolTimeout)
    33  }
    34  
    35  // assertCleanState ensures the state of the main test nodes and the mempool
    36  // are in a clean state (no open channels, no txs in the mempool, etc).
    37  func assertCleanState(h *harnessTest, net *lntest.NetworkHarness) {
    38  	assertCleanStateAliceBob(h, net.Alice, net.Bob, net)
    39  }
    40  
    41  func assertNodeBlockHeight(t *harnessTest, node *lntest.HarnessNode, height int32) {
    42  	t.t.Helper()
    43  
    44  	err := wait.NoError(func() error {
    45  		ctxt, cancel := context.WithTimeout(context.Background(), defaultTimeout)
    46  		defer cancel()
    47  		getInfoReq := &lnrpc.GetInfoRequest{}
    48  		getInfoResp, err := node.GetInfo(ctxt, getInfoReq)
    49  		if err != nil {
    50  			return err
    51  		}
    52  		if int32(getInfoResp.BlockHeight) != height {
    53  			return fmt.Errorf("unexpected block height for node %s: "+
    54  				"want=%d got=%d", node.Name(),
    55  				height, getInfoResp.BlockHeight)
    56  		}
    57  
    58  		return nil
    59  	}, defaultTimeout)
    60  	if err != nil {
    61  		t.Fatalf("failed to assert node block height: %v", err)
    62  	}
    63  }
    64  
    65  // recordedTxFee returns the tx fee recorded in the transaction itself (that
    66  // is, sum(TxOut[].Value) - sum(TxIn[].ValueIn)). While this is not currently
    67  // enforced by consensus rules and cannot be relied upon for validation
    68  // purposes, it's sufficient for testing purposes, assuming the procedure that
    69  // generated the transaction correctly fills the ValueIn (which should be true
    70  // for transactions produced by dcrlnd).
    71  func recordedTxFee(tx *wire.MsgTx) int64 {
    72  	var amountIn, amountOut int64
    73  	for _, in := range tx.TxIn {
    74  		amountIn += in.ValueIn
    75  	}
    76  	for _, out := range tx.TxOut {
    77  		amountOut += out.Value
    78  	}
    79  	return amountIn - amountOut
    80  }
    81  
    82  // waitForPendingHtlcs waits for up to 15 seconds for the given channel in the
    83  // given node to show the specified number of pending HTLCs.
    84  func waitForPendingHtlcs(node *lntest.HarnessNode,
    85  	chanPoint *lnrpc.ChannelPoint, pendingHtlcs int) error {
    86  
    87  	fundingTxID, err := chainhash.NewHash(chanPoint.GetFundingTxidBytes())
    88  	if err != nil {
    89  		return fmt.Errorf("unable to convert funding txid into "+
    90  			"chainhash.Hash: %v", err)
    91  	}
    92  	outPoint := wire.OutPoint{
    93  		Hash:  *fundingTxID,
    94  		Index: chanPoint.OutputIndex,
    95  	}
    96  	targetChan := outPoint.String()
    97  
    98  	req := &lnrpc.ListChannelsRequest{}
    99  	ctxb := context.Background()
   100  
   101  	var predErr error
   102  	wait.Predicate(func() bool {
   103  		ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
   104  		channelInfo, err := node.ListChannels(ctxt, req)
   105  		if err != nil {
   106  			predErr = err
   107  			return false
   108  		}
   109  
   110  		for _, channel := range channelInfo.Channels {
   111  			if channel.ChannelPoint != targetChan {
   112  				continue
   113  			}
   114  
   115  			foundHtlcs := len(channel.PendingHtlcs)
   116  			if foundHtlcs == pendingHtlcs {
   117  				predErr = nil
   118  				return true
   119  			}
   120  
   121  			predErr = fmt.Errorf("found only %d htlcs (wanted %d)",
   122  				foundHtlcs, pendingHtlcs)
   123  			return false
   124  		}
   125  
   126  		predErr = fmt.Errorf("could not find channel %s", targetChan)
   127  		return false
   128  	}, time.Second*15)
   129  	return predErr
   130  }
   131  
   132  func assertNumUnminedUnspent(t *harnessTest, node *lntest.HarnessNode, expected int) {
   133  	err := wait.NoError(func() error {
   134  		ctxb := context.Background()
   135  		ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
   136  		utxoReq := &lnrpc.ListUnspentRequest{}
   137  		utxoResp, err := node.ListUnspent(ctxt, utxoReq)
   138  		if err != nil {
   139  			return fmt.Errorf("unable to query utxos: %v", err)
   140  		}
   141  
   142  		actual := len(utxoResp.Utxos)
   143  		if actual != expected {
   144  			return fmt.Errorf("node %s has wrong number of unmined utxos ("+
   145  				"expected %d actual %d)", node.Name(), expected, actual)
   146  		}
   147  
   148  		return nil
   149  
   150  	}, defaultTimeout)
   151  	if err != nil {
   152  		t.Fatalf("failed asserting nb of unmined unspent: %v", err)
   153  	}
   154  }
   155  
   156  func chanPointFundingToOutpoint(cp *lnrpc.ChannelPoint) wire.OutPoint {
   157  	txId, err := lnrpc.GetChanPointFundingTxid(cp)
   158  	if err != nil {
   159  		panic(err)
   160  	}
   161  	return wire.OutPoint{Hash: *txId, Index: cp.OutputIndex}
   162  }