Merge pull request #4344 from matheusdtech/lntest-improvs
lntest+itest improvements
This commit is contained in:
commit
26cff10c19
@ -678,6 +678,8 @@ func (w *WalletKit) BumpFee(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Attempting to CPFP outpoint %s", op)
|
||||
|
||||
// Since we're unable to perform a bump through RBF, we'll assume the
|
||||
// user is attempting to bump an unconfirmed transaction's fee rate by
|
||||
// sweeping an output within it under control of the wallet with a
|
||||
|
@ -1128,7 +1128,8 @@ func (n *NetworkHarness) CloseChannel(ctx context.Context,
|
||||
// within the network.
|
||||
closeResp, err := closeRespStream.Recv()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
errChan <- fmt.Errorf("unable to recv() from close "+
|
||||
"stream: %v", err)
|
||||
return
|
||||
}
|
||||
pendingClose, ok := closeResp.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
|
||||
@ -1140,11 +1141,13 @@ func (n *NetworkHarness) CloseChannel(ctx context.Context,
|
||||
|
||||
closeTxid, err := chainhash.NewHash(pendingClose.ClosePending.Txid)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
errChan <- fmt.Errorf("unable to decode closeTxid: "+
|
||||
"%v", err)
|
||||
return
|
||||
}
|
||||
if err := n.WaitForTxBroadcast(ctx, *closeTxid); err != nil {
|
||||
errChan <- err
|
||||
errChan <- fmt.Errorf("error while waiting for "+
|
||||
"broadcast tx: %v", err)
|
||||
return
|
||||
}
|
||||
fin <- closeTxid
|
||||
@ -1153,9 +1156,6 @@ func (n *NetworkHarness) CloseChannel(ctx context.Context,
|
||||
// Wait until either the deadline for the context expires, an error
|
||||
// occurs, or the channel close update is received.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, nil, fmt.Errorf("timeout reached before channel close " +
|
||||
"initiated")
|
||||
case err := <-errChan:
|
||||
return nil, nil, err
|
||||
case closeTxid := <-fin:
|
||||
|
@ -155,6 +155,39 @@ func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash)
|
||||
t.Fatalf("tx was not included in block")
|
||||
}
|
||||
|
||||
func assertWalletUnspent(t *harnessTest, node *lntest.HarnessNode, out *lnrpc.OutPoint) {
|
||||
t.t.Helper()
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
ctxt, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
unspent, err := node.ListUnspent(ctxt, &lnrpc.ListUnspentRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = errors.New("tx with wanted txhash never found")
|
||||
for _, utxo := range unspent.Utxos {
|
||||
if !bytes.Equal(utxo.Outpoint.TxidBytes, out.TxidBytes) {
|
||||
continue
|
||||
}
|
||||
|
||||
err = errors.New("wanted output is not a wallet utxo")
|
||||
if utxo.Outpoint.OutputIndex != out.OutputIndex {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}, defaultTimeout)
|
||||
if err != nil {
|
||||
t.Fatalf("outpoint %s not unspent by %s's wallet: %v", out,
|
||||
node.Name(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func rpcPointToWirePoint(t *harnessTest, chanPoint *lnrpc.ChannelPoint) wire.OutPoint {
|
||||
txid, err := lnd.GetChanPointFundingTxid(chanPoint)
|
||||
if err != nil {
|
||||
@ -9055,6 +9088,29 @@ func testRevokedCloseRetributionAltruistWatchtower(net *lntest.NetworkHarness,
|
||||
|
||||
davePreSweepBalance := daveBalResp.ConfirmedBalance
|
||||
|
||||
// Wait until the backup has been accepted by the watchtower before
|
||||
// shutting down Dave.
|
||||
err = wait.NoError(func() error {
|
||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
||||
defer cancel()
|
||||
bkpStats, err := dave.WatchtowerClient.Stats(ctxt, &wtclientrpc.StatsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
if bkpStats == nil {
|
||||
return errors.New("no active backup sessions")
|
||||
}
|
||||
if bkpStats.NumBackups == 0 {
|
||||
return errors.New("no backups accepted")
|
||||
}
|
||||
|
||||
return nil
|
||||
}, defaultTimeout)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to verify backup task completed: %v", err)
|
||||
}
|
||||
|
||||
// Shutdown Dave to simulate going offline for an extended period of
|
||||
// time. Once he's not watching, Carol will try to breach the channel.
|
||||
restart, err := net.SuspendNode(dave)
|
||||
@ -9083,9 +9139,6 @@ func testRevokedCloseRetributionAltruistWatchtower(net *lntest.NetworkHarness,
|
||||
t.Fatalf("db copy failed: %v", carolChan.NumUpdates)
|
||||
}
|
||||
|
||||
// TODO(conner): add hook for backup completion
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
// Now force Carol to execute a *force* channel closure by unilaterally
|
||||
// broadcasting his current channel state. This is actually the
|
||||
// commitment transaction of a prior *revoked* state, so he'll soon
|
||||
@ -13367,7 +13420,7 @@ func testChannelBackupUpdates(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
numChans := 2
|
||||
chanAmt := btcutil.Amount(1000000)
|
||||
for i := 0; i < numChans; i++ {
|
||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
||||
ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout)
|
||||
chanPoint := openChannelAndAssert(
|
||||
ctxt, t, net, net.Alice, carol,
|
||||
lntest.OpenChannelParams{
|
||||
@ -13501,7 +13554,7 @@ func testExportChannelBackup(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
numChans := 2
|
||||
chanAmt := btcutil.Amount(1000000)
|
||||
for i := 0; i < numChans; i++ {
|
||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
||||
ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout)
|
||||
chanPoint := openChannelAndAssert(
|
||||
ctxt, t, net, net.Alice, carol,
|
||||
lntest.OpenChannelParams{
|
||||
|
@ -86,12 +86,15 @@ func testCPFP(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
t.Fatalf("bob's output was not found within the transaction")
|
||||
}
|
||||
|
||||
// We'll attempt to bump the fee of this transaction by performing a
|
||||
// CPFP from Alice's point of view.
|
||||
// Wait until bob has seen the tx and considers it as owned.
|
||||
op := &lnrpc.OutPoint{
|
||||
TxidBytes: txid[:],
|
||||
OutputIndex: uint32(bobOutputIdx),
|
||||
}
|
||||
assertWalletUnspent(t, net.Bob, op)
|
||||
|
||||
// We'll attempt to bump the fee of this transaction by performing a
|
||||
// CPFP from Alice's point of view.
|
||||
bumpFeeReq := &walletrpc.BumpFeeRequest{
|
||||
Outpoint: op,
|
||||
SatPerByte: uint32(sweep.DefaultMaxFeeRate.FeePerKVByte() / 2000),
|
||||
|
108
lntest/node.go
108
lntest/node.go
@ -625,9 +625,10 @@ func (hn *HarnessNode) initLightningClient(conn *grpc.ClientConn) error {
|
||||
// Launch the watcher that will hook into graph related topology change
|
||||
// from the PoV of this node.
|
||||
hn.wg.Add(1)
|
||||
go hn.lightningNetworkWatcher()
|
||||
subscribed := make(chan error)
|
||||
go hn.lightningNetworkWatcher(subscribed)
|
||||
|
||||
return nil
|
||||
return <-subscribed
|
||||
}
|
||||
|
||||
// FetchNodeInfo queries an unlocked node to retrieve its public key.
|
||||
@ -688,28 +689,26 @@ func (hn *HarnessNode) writePidFile() error {
|
||||
func (hn *HarnessNode) ReadMacaroon(macPath string, timeout time.Duration) (
|
||||
*macaroon.Macaroon, error) {
|
||||
|
||||
// Wait until macaroon file is created before using it.
|
||||
macTimeout := time.After(timeout)
|
||||
for !fileExists(macPath) {
|
||||
select {
|
||||
case <-macTimeout:
|
||||
return nil, fmt.Errorf("timeout waiting for macaroon "+
|
||||
"file %s to be created after %d seconds",
|
||||
macPath, timeout/time.Second)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
// Wait until macaroon file is created and has valid content before
|
||||
// using it.
|
||||
var mac *macaroon.Macaroon
|
||||
err := wait.NoError(func() error {
|
||||
macBytes, err := ioutil.ReadFile(macPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading macaroon file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know the file exists, read it and return the macaroon.
|
||||
macBytes, err := ioutil.ReadFile(macPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mac := &macaroon.Macaroon{}
|
||||
if err = mac.UnmarshalBinary(macBytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mac, nil
|
||||
newMac := &macaroon.Macaroon{}
|
||||
if err = newMac.UnmarshalBinary(macBytes); err != nil {
|
||||
return fmt.Errorf("error unmarshalling macaroon "+
|
||||
"file: %v", err)
|
||||
}
|
||||
mac = newMac
|
||||
|
||||
return nil
|
||||
}, timeout)
|
||||
|
||||
return mac, err
|
||||
}
|
||||
|
||||
// ConnectRPCWithMacaroon uses the TLS certificate and given macaroon to
|
||||
@ -717,34 +716,34 @@ func (hn *HarnessNode) ReadMacaroon(macPath string, timeout time.Duration) (
|
||||
func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
||||
*grpc.ClientConn, error) {
|
||||
|
||||
// Wait until TLS certificate is created before using it, up to 30 sec.
|
||||
tlsTimeout := time.After(DefaultTimeout)
|
||||
for !fileExists(hn.Cfg.TLSCertPath) {
|
||||
select {
|
||||
case <-tlsTimeout:
|
||||
return nil, fmt.Errorf("timeout waiting for TLS cert " +
|
||||
"file to be created")
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
}
|
||||
// Wait until TLS certificate is created and has valid content before
|
||||
// using it, up to 30 sec.
|
||||
var tlsCreds credentials.TransportCredentials
|
||||
err := wait.NoError(func() error {
|
||||
var err error
|
||||
tlsCreds, err = credentials.NewClientTLSFromFile(
|
||||
hn.Cfg.TLSCertPath, "",
|
||||
)
|
||||
return err
|
||||
}, DefaultTimeout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading TLS cert: %v", err)
|
||||
}
|
||||
|
||||
opts := []grpc.DialOption{grpc.WithBlock()}
|
||||
tlsCreds, err := credentials.NewClientTLSFromFile(
|
||||
hn.Cfg.TLSCertPath, "",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithTransportCredentials(tlsCreds),
|
||||
}
|
||||
opts = append(opts, grpc.WithTransportCredentials(tlsCreds))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
if mac == nil {
|
||||
return grpc.Dial(hn.Cfg.RPCAddr(), opts...)
|
||||
return grpc.DialContext(ctx, hn.Cfg.RPCAddr(), opts...)
|
||||
}
|
||||
macCred := macaroons.NewMacaroonCredential(mac)
|
||||
opts = append(opts, grpc.WithPerRPCCredentials(macCred))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||
defer cancel()
|
||||
return grpc.DialContext(ctx, hn.Cfg.RPCAddr(), opts...)
|
||||
}
|
||||
|
||||
@ -873,7 +872,7 @@ func getChanPointFundingTxid(chanPoint *lnrpc.ChannelPoint) ([]byte, error) {
|
||||
// closed or opened within the network. In order to dispatch these
|
||||
// notifications, the GraphTopologySubscription client exposed as part of the
|
||||
// gRPC interface is used.
|
||||
func (hn *HarnessNode) lightningNetworkWatcher() {
|
||||
func (hn *HarnessNode) lightningNetworkWatcher(subscribed chan error) {
|
||||
defer hn.wg.Done()
|
||||
|
||||
graphUpdates := make(chan *lnrpc.GraphTopologyUpdate)
|
||||
@ -883,16 +882,16 @@ func (hn *HarnessNode) lightningNetworkWatcher() {
|
||||
|
||||
req := &lnrpc.GraphTopologySubscription{}
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
topologyClient, err := hn.SubscribeChannelGraph(ctx, req)
|
||||
if err != nil {
|
||||
// We panic here in case of an error as failure to
|
||||
// create the topology client will cause all subsequent
|
||||
// tests to fail.
|
||||
panic(fmt.Errorf("unable to create topology "+
|
||||
"client: %v", err))
|
||||
msg := fmt.Sprintf("%s(%d): unable to create topology "+
|
||||
"client: %v (%s)", hn.Name(), hn.NodeID, err,
|
||||
time.Now().String())
|
||||
subscribed <- fmt.Errorf(msg)
|
||||
return
|
||||
}
|
||||
|
||||
defer cancelFunc()
|
||||
close(subscribed)
|
||||
|
||||
for {
|
||||
update, err := topologyClient.Recv()
|
||||
@ -1157,14 +1156,3 @@ func (hn *HarnessNode) WaitForBalance(expectedBalance btcutil.Amount, confirmed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fileExists reports whether the named file or directory exists.
|
||||
// This function is taken from https://github.com/btcsuite/btcd
|
||||
func fileExists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user