github.com/decred/dcrlnd@v0.7.6/contractcourt/utxonursery_test.go (about)

     1  //go:build !rpctest
     2  // +build !rpctest
     3  
     4  package contractcourt
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"math"
    10  	"os"
    11  	"reflect"
    12  	"runtime/pprof"
    13  	"sync"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    19  	"github.com/decred/dcrd/dcrutil/v4"
    20  	"github.com/decred/dcrd/txscript/v4"
    21  	"github.com/decred/dcrd/wire"
    22  	"github.com/decred/dcrlnd/channeldb"
    23  	"github.com/decred/dcrlnd/input"
    24  	"github.com/decred/dcrlnd/lntest/mock"
    25  	"github.com/decred/dcrlnd/lnwallet"
    26  	"github.com/decred/dcrlnd/sweep"
    27  )
    28  
    29  var (
    30  	outPoints = []wire.OutPoint{
    31  		{
    32  			Hash: [chainhash.HashSize]byte{
    33  				0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
    34  				0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    35  				0x2d, 0xe7, 0x93, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    36  				0x1f, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
    37  			},
    38  			Index: 9,
    39  		},
    40  		{
    41  			Hash: [chainhash.HashSize]byte{
    42  				0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
    43  				0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
    44  				0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
    45  				0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
    46  			},
    47  			Index: 49,
    48  		},
    49  		{
    50  			Hash: [chainhash.HashSize]byte{
    51  				0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
    52  				0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    53  				0x0d, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    54  				0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
    55  			},
    56  			Index: 23,
    57  		},
    58  		{
    59  			Hash: [chainhash.HashSize]byte{
    60  				0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
    61  				0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
    62  				0x0d, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    63  				0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    64  			},
    65  			Index: 30,
    66  		},
    67  		{
    68  			Hash: [chainhash.HashSize]byte{
    69  				0x0d, 0xe7, 0x95, 0xe4, 0xfc, 0xd2, 0xc6, 0xda,
    70  				0xb7, 0x25, 0xb8, 0x4d, 0x63, 0x59, 0xe6, 0x96,
    71  				0x31, 0x13, 0xa1, 0x17, 0x81, 0xb6, 0x37, 0xd8,
    72  				0x1e, 0x0b, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
    73  			},
    74  			Index: 2,
    75  		},
    76  		{
    77  			Hash: [chainhash.HashSize]byte{
    78  				0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    79  				0x51, 0xb6, 0x37, 0xd8, 0x1f, 0x0b, 0x4c, 0xf9,
    80  				0x9e, 0xc5, 0x8c, 0xe9, 0xfc, 0xd2, 0xc6, 0xda,
    81  				0x2d, 0xe7, 0x93, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    82  			},
    83  			Index: 9,
    84  		},
    85  	}
    86  
    87  	keys = [][]byte{
    88  		{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
    89  			0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
    90  			0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
    91  			0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
    92  			0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
    93  			0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
    94  			0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
    95  			0xb4, 0x12, 0xa3,
    96  		},
    97  		{0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a,
    98  			0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e,
    99  			0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca,
   100  			0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0,
   101  			0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64,
   102  			0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9,
   103  			0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56,
   104  			0xb4, 0x12, 0xa3,
   105  		},
   106  		{0x02, 0xce, 0x0b, 0x14, 0xfb, 0x84, 0x2b, 0x1b,
   107  			0xa5, 0x49, 0xfd, 0xd6, 0x75, 0xc9, 0x80, 0x75, 0xf1,
   108  			0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21,
   109  			0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d,
   110  		},
   111  	}
   112  
   113  	signDescriptors = []input.SignDescriptor{
   114  		{
   115  			SingleTweak: []byte{
   116  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   117  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   118  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   119  				0x02, 0x02, 0x02, 0x02, 0x02,
   120  			},
   121  			WitnessScript: []byte{
   122  				0x00, 0x14, 0xee, 0x91, 0x41, 0x7e, 0x85, 0x6c, 0xde,
   123  				0x10, 0xa2, 0x91, 0x1e, 0xdc, 0xbd, 0xbd, 0x69, 0xe2,
   124  				0xef, 0xb5, 0x71, 0x48,
   125  			},
   126  			Output: &wire.TxOut{
   127  				Value: 5000000000,
   128  				PkScript: []byte{
   129  					0x41, // OP_DATA_65
   130  					0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
   131  					0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
   132  					0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
   133  					0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
   134  					0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
   135  					0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
   136  					0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
   137  					0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
   138  					0xa6, // 65-byte signature
   139  					0xac, // OP_CHECKSIG
   140  				},
   141  			},
   142  			HashType: txscript.SigHashAll,
   143  		},
   144  		{
   145  			SingleTweak: []byte{
   146  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   147  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   148  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   149  				0x02, 0x02, 0x02, 0x02, 0x02,
   150  			},
   151  			WitnessScript: []byte{
   152  				0x00, 0x14, 0xee, 0x91, 0x41, 0x7e, 0x85, 0x6c, 0xde,
   153  				0x10, 0xa2, 0x91, 0x1e, 0xdc, 0xbd, 0xbd, 0x69, 0xe2,
   154  				0xef, 0xb5, 0x71, 0x48,
   155  			},
   156  			Output: &wire.TxOut{
   157  				Value: 5000000000,
   158  				PkScript: []byte{
   159  					0x41, // OP_DATA_65
   160  					0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
   161  					0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
   162  					0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
   163  					0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
   164  					0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
   165  					0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
   166  					0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
   167  					0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
   168  					0xa6, // 65-byte signature
   169  					0xac, // OP_CHECKSIG
   170  				},
   171  			},
   172  			HashType: txscript.SigHashAll,
   173  		},
   174  		{
   175  			SingleTweak: []byte{
   176  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   177  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   178  				0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
   179  				0x02, 0x02, 0x02, 0x02, 0x02,
   180  			},
   181  			WitnessScript: []byte{
   182  				0x00, 0x14, 0xee, 0x91, 0x41, 0x7e, 0x85, 0x6c, 0xde,
   183  				0x10, 0xa2, 0x91, 0x1e, 0xdc, 0xbd, 0xbd, 0x69, 0xe2,
   184  				0xef, 0xb5, 0x71, 0x48,
   185  			},
   186  			Output: &wire.TxOut{
   187  				Value: 5000000000,
   188  				PkScript: []byte{
   189  					0x41, // OP_DATA_65
   190  					0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
   191  					0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
   192  					0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
   193  					0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
   194  					0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
   195  					0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
   196  					0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
   197  					0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
   198  					0xa6, // 65-byte signature
   199  					0xac, // OP_CHECKSIG
   200  				},
   201  			},
   202  			HashType: txscript.SigHashAll,
   203  		},
   204  	}
   205  
   206  	kidOutputs = []kidOutput{
   207  		{
   208  			breachedOutput: breachedOutput{
   209  				amt:         dcrutil.Amount(13e7),
   210  				outpoint:    outPoints[1],
   211  				witnessType: input.CommitmentTimeLock,
   212  				confHeight:  uint32(1000),
   213  			},
   214  			originChanPoint:  outPoints[0],
   215  			blocksToMaturity: uint32(42),
   216  		},
   217  
   218  		{
   219  			breachedOutput: breachedOutput{
   220  				amt:         dcrutil.Amount(24e7),
   221  				outpoint:    outPoints[2],
   222  				witnessType: input.CommitmentTimeLock,
   223  				confHeight:  uint32(1000),
   224  			},
   225  			originChanPoint:  outPoints[0],
   226  			blocksToMaturity: uint32(42),
   227  		},
   228  
   229  		{
   230  			breachedOutput: breachedOutput{
   231  				amt:         dcrutil.Amount(2e5),
   232  				outpoint:    outPoints[3],
   233  				witnessType: input.CommitmentTimeLock,
   234  				confHeight:  uint32(500),
   235  			},
   236  			originChanPoint:  outPoints[0],
   237  			blocksToMaturity: uint32(28),
   238  		},
   239  
   240  		{
   241  			breachedOutput: breachedOutput{
   242  				amt:         dcrutil.Amount(10e6),
   243  				outpoint:    outPoints[4],
   244  				witnessType: input.CommitmentTimeLock,
   245  				confHeight:  uint32(500),
   246  			},
   247  			originChanPoint:  outPoints[0],
   248  			blocksToMaturity: uint32(28),
   249  		},
   250  	}
   251  
   252  	babyOutputs = []babyOutput{
   253  		{
   254  			kidOutput: kidOutputs[1],
   255  			expiry:    3829,
   256  			timeoutTx: timeoutTx,
   257  		},
   258  		{
   259  			kidOutput: kidOutputs[2],
   260  			expiry:    4,
   261  			timeoutTx: timeoutTx,
   262  		},
   263  		{
   264  			kidOutput: kidOutputs[3],
   265  			expiry:    4,
   266  			timeoutTx: timeoutTx,
   267  		},
   268  	}
   269  
   270  	// Dummy timeout tx used to test serialization, borrowed from dcrd
   271  	// msgtx_test
   272  	timeoutTx = &wire.MsgTx{
   273  		Version: 1,
   274  		TxIn: []*wire.TxIn{
   275  			{
   276  				PreviousOutPoint: wire.OutPoint{
   277  					Hash: chainhash.Hash{
   278  						0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0,
   279  						0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2,
   280  						0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8,
   281  						0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd,
   282  					},
   283  					Index: 19,
   284  				},
   285  				SignatureScript: []byte{
   286  					// OP_DATA_70
   287  					0x46,
   288  
   289  					// 70-byte signature
   290  					0x30, 0x43, 0x02, 0x1f, 0x4d, 0x23, 0x81, 0xdc,
   291  					0x97, 0xf1, 0x82, 0xab, 0xd8, 0x18, 0x5f, 0x51,
   292  					0x75, 0x30, 0x18, 0x52, 0x32, 0x12, 0xf5, 0xdd,
   293  					0xc0, 0x7c, 0xc4, 0xe6, 0x3a, 0x8d, 0xc0, 0x36,
   294  					0x58, 0xda, 0x19, 0x02, 0x20, 0x60, 0x8b, 0x5c,
   295  					0x4d, 0x92, 0xb8, 0x6b, 0x6d, 0xe7, 0xd7, 0x8e,
   296  					0xf2, 0x3a, 0x2f, 0xa7, 0x35, 0xbc, 0xb5, 0x9b,
   297  					0x91, 0x4a, 0x48, 0xb0, 0xe1, 0x87, 0xc5, 0xe7,
   298  					0x56, 0x9a, 0x18, 0x19, 0x70, 0x01,
   299  
   300  					// OP_DATA_33
   301  					0x21,
   302  
   303  					// 33-byte serialize pub key
   304  					0x03, 0x07, 0xea, 0xd0, 0x84, 0x80, 0x7e, 0xb7,
   305  					0x63, 0x46, 0xdf, 0x69, 0x77, 0x00, 0x0c, 0x89,
   306  					0x39, 0x2f, 0x45, 0xc7, 0x64, 0x25, 0xb2, 0x61,
   307  					0x81, 0xf5, 0x21, 0xd7, 0xf3, 0x70, 0x06, 0x6a,
   308  					0x8f,
   309  				},
   310  				Sequence: 0xffffffff,
   311  			},
   312  		},
   313  		TxOut: []*wire.TxOut{
   314  			{
   315  				Value: 395019,
   316  				PkScript: []byte{ // p2wkh output
   317  					0x00, // Version 0 witness program
   318  					0x14, // OP_DATA_20
   319  					0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39,
   320  					0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89,
   321  					0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash
   322  				},
   323  			},
   324  		},
   325  	}
   326  
   327  	testChanPoint      = wire.OutPoint{}
   328  	defaultTestTimeout = 5 * time.Second
   329  )
   330  
   331  func init() {
   332  	// Finish initializing our test vectors by parsing the desired public keys and
   333  	// properly populating the sign descriptors of all baby and kid outputs.
   334  	for i := range signDescriptors {
   335  		pk, err := secp256k1.ParsePubKey(keys[i])
   336  		if err != nil {
   337  			panic(fmt.Sprintf("unable to parse pub key during init: %v", err))
   338  		}
   339  		signDescriptors[i].KeyDesc.PubKey = pk
   340  
   341  	}
   342  	for i := range kidOutputs {
   343  		isd := i % len(signDescriptors)
   344  		kidOutputs[i].signDesc = signDescriptors[isd]
   345  	}
   346  
   347  	for i := range babyOutputs {
   348  		isd := i % len(signDescriptors)
   349  		babyOutputs[i].kidOutput.signDesc = signDescriptors[isd]
   350  	}
   351  
   352  	initIncubateTests()
   353  }
   354  
   355  func TestKidOutputSerialization(t *testing.T) {
   356  	t.Parallel()
   357  
   358  	for i, kid := range kidOutputs {
   359  		var b bytes.Buffer
   360  		if err := kid.Encode(&b); err != nil {
   361  			t.Fatalf("Encode #%d: unable to serialize "+
   362  				"kid output: %v", i, err)
   363  		}
   364  
   365  		var deserializedKid kidOutput
   366  		if err := deserializedKid.Decode(&b); err != nil {
   367  			t.Fatalf("Decode #%d: unable to deserialize "+
   368  				"kid output: %v", i, err)
   369  		}
   370  
   371  		if !reflect.DeepEqual(kid, deserializedKid) {
   372  			t.Fatalf("DeepEqual #%d: unexpected kidOutput, "+
   373  				"want %+v, got %+v",
   374  				i, kid, deserializedKid)
   375  		}
   376  	}
   377  }
   378  
   379  func TestBabyOutputSerialization(t *testing.T) {
   380  	t.Parallel()
   381  
   382  	for i, baby := range babyOutputs {
   383  		var b bytes.Buffer
   384  		if err := baby.Encode(&b); err != nil {
   385  			t.Fatalf("Encode #%d: unable to serialize "+
   386  				"baby output: %v", i, err)
   387  		}
   388  
   389  		var deserializedBaby babyOutput
   390  		if err := deserializedBaby.Decode(&b); err != nil {
   391  			t.Fatalf("Decode #%d: unable to deserialize "+
   392  				"baby output: %v", i, err)
   393  		}
   394  
   395  		if !reflect.DeepEqual(baby, deserializedBaby) {
   396  			t.Fatalf("DeepEqual #%d: unexpected babyOutput, "+
   397  				"want %+v, got %+v",
   398  				i, baby, deserializedBaby)
   399  		}
   400  
   401  	}
   402  }
   403  
   404  type nurseryTestContext struct {
   405  	nursery     *UtxoNursery
   406  	notifier    *sweep.MockNotifier
   407  	chainIO     *mock.ChainIO
   408  	publishChan chan wire.MsgTx
   409  	store       *nurseryStoreInterceptor
   410  	restart     func() bool
   411  	receiveTx   func() wire.MsgTx
   412  	sweeper     *mockSweeperFull
   413  	timeoutChan chan chan time.Time
   414  	t           *testing.T
   415  	dbCleanup   func()
   416  }
   417  
   418  func createNurseryTestContext(t *testing.T,
   419  	checkStartStop func(func()) bool) *nurseryTestContext {
   420  
   421  	// Create a temporary database and connect nurseryStore to it. The
   422  	// alternative, mocking nurseryStore, is not chosen because there is
   423  	// still considerable logic in the store.
   424  
   425  	cdb, cleanup, err := channeldb.MakeTestDB()
   426  	if err != nil {
   427  		t.Fatalf("unable to open channeldb: %v", err)
   428  	}
   429  
   430  	store, err := NewNurseryStore(&chainhash.Hash{}, cdb)
   431  	if err != nil {
   432  		t.Fatal(err)
   433  	}
   434  
   435  	// Wrap the store in an inceptor to be able to wait for events in this
   436  	// test.
   437  	storeIntercepter := newNurseryStoreInterceptor(store)
   438  
   439  	notifier := sweep.NewMockNotifier(t)
   440  
   441  	publishChan := make(chan wire.MsgTx, 1)
   442  	publishFunc := func(tx *wire.MsgTx, source string) error {
   443  		log.Tracef("Publishing tx %v by %v", tx.TxHash(), source)
   444  		publishChan <- *tx
   445  		return nil
   446  	}
   447  
   448  	timeoutChan := make(chan chan time.Time)
   449  
   450  	chainIO := &mock.ChainIO{
   451  		BestHeight: 0,
   452  	}
   453  
   454  	sweeper := newMockSweeperFull(t)
   455  
   456  	nurseryCfg := NurseryConfig{
   457  		Notifier: notifier,
   458  		FetchClosedChannels: func(pendingOnly bool) (
   459  			[]*channeldb.ChannelCloseSummary, error) {
   460  			return []*channeldb.ChannelCloseSummary{}, nil
   461  		},
   462  		FetchClosedChannel: func(chanID *wire.OutPoint) (
   463  			*channeldb.ChannelCloseSummary, error) {
   464  			return &channeldb.ChannelCloseSummary{
   465  				CloseHeight: 0,
   466  			}, nil
   467  		},
   468  		Store:      storeIntercepter,
   469  		ChainIO:    chainIO,
   470  		SweepInput: sweeper.sweepInput,
   471  		PublishTransaction: func(tx *wire.MsgTx, _ string) error {
   472  			return publishFunc(tx, "nursery")
   473  		},
   474  	}
   475  
   476  	nursery := NewUtxoNursery(&nurseryCfg)
   477  	nursery.Start()
   478  
   479  	ctx := &nurseryTestContext{
   480  		nursery:     nursery,
   481  		notifier:    notifier,
   482  		chainIO:     chainIO,
   483  		store:       storeIntercepter,
   484  		publishChan: publishChan,
   485  		sweeper:     sweeper,
   486  		timeoutChan: timeoutChan,
   487  		t:           t,
   488  		dbCleanup:   cleanup,
   489  	}
   490  
   491  	ctx.receiveTx = func() wire.MsgTx {
   492  		var tx wire.MsgTx
   493  		select {
   494  		case tx = <-ctx.publishChan:
   495  			log.Debugf("Published tx %v", tx.TxHash())
   496  			return tx
   497  		case <-time.After(defaultTestTimeout):
   498  			pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
   499  
   500  			t.Fatalf("tx not published")
   501  		}
   502  		return tx
   503  	}
   504  
   505  	ctx.restart = func() bool {
   506  		return checkStartStop(func() {
   507  			log.Tracef("Restart sweeper and nursery")
   508  			// Simulate lnd restart.
   509  			ctx.nursery.Stop()
   510  
   511  			// Restart sweeper.
   512  			ctx.sweeper = newMockSweeperFull(t)
   513  
   514  			/// Restart nursery.
   515  			nurseryCfg.SweepInput = ctx.sweeper.sweepInput
   516  			ctx.nursery = NewUtxoNursery(&nurseryCfg)
   517  			ctx.nursery.Start()
   518  
   519  		})
   520  	}
   521  
   522  	// Start with testing an immediate restart.
   523  	ctx.restart()
   524  
   525  	return ctx
   526  }
   527  
   528  func (ctx *nurseryTestContext) notifyEpoch(height int32) {
   529  	ctx.t.Helper()
   530  
   531  	ctx.chainIO.BestHeight = height
   532  	ctx.notifier.NotifyEpoch(height)
   533  }
   534  
   535  func (ctx *nurseryTestContext) finish() {
   536  	defer ctx.dbCleanup()
   537  
   538  	// Add a final restart point in this state
   539  	ctx.restart()
   540  
   541  	// We assume that when finish is called, nursery has finished all its
   542  	// goroutines. This implies that the waitgroup is empty.
   543  	signalChan := make(chan struct{})
   544  	go func() {
   545  		ctx.nursery.wg.Wait()
   546  		close(signalChan)
   547  	}()
   548  
   549  	// The only goroutine that is still expected to be running is
   550  	// incubator(). Simulate exit of this goroutine.
   551  	ctx.nursery.wg.Done()
   552  
   553  	// We now expect the Wait to succeed.
   554  	select {
   555  	case <-signalChan:
   556  	case <-time.After(time.Second):
   557  		ctx.t.Fatalf("lingering goroutines detected after test " +
   558  			"is finished")
   559  	}
   560  
   561  	// Restore waitgroup state to what it was before.
   562  	ctx.nursery.wg.Add(1)
   563  
   564  	ctx.nursery.Stop()
   565  
   566  	// We should have consumed and asserted all published transactions in
   567  	// our unit tests.
   568  	select {
   569  	case <-ctx.publishChan:
   570  		ctx.t.Fatalf("unexpected transactions published")
   571  	default:
   572  	}
   573  
   574  	// Assert that the database is empty. All channels removed and height
   575  	// index cleared.
   576  	nurseryChannels, err := ctx.nursery.cfg.Store.ListChannels()
   577  	if err != nil {
   578  		ctx.t.Fatal(err)
   579  	}
   580  	if len(nurseryChannels) > 0 {
   581  		ctx.t.Fatalf("Expected all channels to be removed from store")
   582  	}
   583  
   584  	activeHeights, err := ctx.nursery.cfg.Store.HeightsBelowOrEqual(
   585  		math.MaxUint32)
   586  	if err != nil {
   587  		ctx.t.Fatal(err)
   588  	}
   589  	if len(activeHeights) > 0 {
   590  		ctx.t.Fatalf("Expected height index to be empty")
   591  	}
   592  }
   593  
   594  func createOutgoingRes(onLocalCommitment bool) *lnwallet.OutgoingHtlcResolution {
   595  	// Set up an outgoing htlc resolution to hand off to nursery.
   596  	closeTx := &wire.MsgTx{}
   597  
   598  	htlcOp := wire.OutPoint{
   599  		Hash:  closeTx.TxHash(),
   600  		Index: 0,
   601  	}
   602  
   603  	outgoingRes := lnwallet.OutgoingHtlcResolution{
   604  		Expiry: 125,
   605  		SweepSignDesc: input.SignDescriptor{
   606  			Output: &wire.TxOut{
   607  				Value: 10000,
   608  			},
   609  		},
   610  	}
   611  
   612  	if onLocalCommitment {
   613  		timeoutTx := &wire.MsgTx{
   614  			TxIn: []*wire.TxIn{
   615  				{
   616  					PreviousOutPoint: htlcOp,
   617  					SignatureScript:  []byte{},
   618  				},
   619  			},
   620  			TxOut: []*wire.TxOut{
   621  				{},
   622  			},
   623  		}
   624  
   625  		outgoingRes.SignedTimeoutTx = timeoutTx
   626  		outgoingRes.CsvDelay = 2
   627  	} else {
   628  		outgoingRes.ClaimOutpoint = htlcOp
   629  		outgoingRes.CsvDelay = 0
   630  	}
   631  
   632  	return &outgoingRes
   633  }
   634  
   635  func incubateTestOutput(t *testing.T, nursery *UtxoNursery,
   636  	onLocalCommitment bool) *lnwallet.OutgoingHtlcResolution {
   637  
   638  	outgoingRes := createOutgoingRes(onLocalCommitment)
   639  
   640  	// Hand off to nursery.
   641  	err := nursery.IncubateOutputs(
   642  		testChanPoint,
   643  		[]lnwallet.OutgoingHtlcResolution{*outgoingRes},
   644  		nil, 0,
   645  	)
   646  	if err != nil {
   647  		t.Fatal(err)
   648  	}
   649  
   650  	// IncubateOutputs is executing synchronously and we expect the output
   651  	// to immediately show up in the report.
   652  	expectedStage := uint32(2)
   653  	if onLocalCommitment {
   654  		expectedStage = 1
   655  	}
   656  	assertNurseryReport(t, nursery, 1, expectedStage, 10000)
   657  
   658  	return outgoingRes
   659  }
   660  
   661  func assertNurseryReport(t *testing.T, nursery *UtxoNursery,
   662  	expectedNofHtlcs int, expectedStage uint32,
   663  	expectedLimboBalance dcrutil.Amount) {
   664  	report, err := nursery.NurseryReport(&testChanPoint)
   665  	if err != nil {
   666  		t.Fatal(err)
   667  	}
   668  
   669  	if len(report.Htlcs) != expectedNofHtlcs {
   670  		t.Fatalf("expected %v outputs to be reported, but report "+
   671  			"only contains %v", expectedNofHtlcs, len(report.Htlcs))
   672  	}
   673  
   674  	if expectedNofHtlcs != 0 {
   675  		htlcReport := report.Htlcs[0]
   676  		if htlcReport.Stage != expectedStage {
   677  			t.Fatalf("expected htlc be advanced to stage %v, but "+
   678  				"it is reported in stage %v",
   679  				expectedStage, htlcReport.Stage)
   680  		}
   681  	}
   682  
   683  	if report.LimboBalance != expectedLimboBalance {
   684  		t.Fatalf("expected limbo balance to be %v, but it is %v instead",
   685  			expectedLimboBalance, report.LimboBalance)
   686  	}
   687  }
   688  
   689  func assertNurseryReportUnavailable(t *testing.T, nursery *UtxoNursery) {
   690  	_, err := nursery.NurseryReport(&testChanPoint)
   691  	if err != ErrContractNotFound {
   692  		t.Fatal("expected report to be unavailable")
   693  	}
   694  }
   695  
   696  // testRestartLoop runs the specified test multiple times and in every run it
   697  // will attempt to execute a restart action in a different location. This is to
   698  // assert that the unit under test is recovering correctly from restarts.
   699  func testRestartLoop(t *testing.T, test func(*testing.T,
   700  	func(func()) bool)) {
   701  
   702  	// Start with running the test without any restarts (index zero)
   703  	restartIdx := 0
   704  
   705  	for {
   706  		currentStartStopIdx := 0
   707  
   708  		// checkStartStop is called at every point in the test where a
   709  		// restart should be exercised. When this function is called as
   710  		// many times as the current value of currentStartStopIdx, it
   711  		// will execute startStopFunc.
   712  		checkStartStop := func(startStopFunc func()) bool {
   713  			currentStartStopIdx++
   714  			if restartIdx == currentStartStopIdx {
   715  				startStopFunc()
   716  
   717  				return true
   718  			}
   719  			log.Debugf("Skipping restart point %v",
   720  				currentStartStopIdx)
   721  			return false
   722  		}
   723  
   724  		var subTestName string
   725  		if restartIdx == 0 {
   726  			subTestName = "no_restart"
   727  		} else {
   728  			subTestName = fmt.Sprintf("restart_%v", restartIdx)
   729  		}
   730  		t.Run(subTestName,
   731  			func(t *testing.T) {
   732  				test(t, checkStartStop)
   733  			})
   734  
   735  		// Exit the loop when all restart points have been tested.
   736  		if currentStartStopIdx == restartIdx {
   737  			return
   738  		}
   739  		restartIdx++
   740  	}
   741  }
   742  
   743  func TestNurseryOutgoingHtlcSuccessOnLocal(t *testing.T) {
   744  	testRestartLoop(t, testNurseryOutgoingHtlcSuccessOnLocal)
   745  }
   746  
   747  func testNurseryOutgoingHtlcSuccessOnLocal(t *testing.T,
   748  	checkStartStop func(func()) bool) {
   749  
   750  	ctx := createNurseryTestContext(t, checkStartStop)
   751  
   752  	outgoingRes := incubateTestOutput(t, ctx.nursery, true)
   753  
   754  	ctx.restart()
   755  
   756  	// Notify arrival of block where HTLC CLTV expires.
   757  	ctx.notifyEpoch(125)
   758  
   759  	// This should trigger nursery to publish the timeout tx.
   760  	ctx.receiveTx()
   761  
   762  	if ctx.restart() {
   763  		// Restart should retrigger broadcast of timeout tx.
   764  		ctx.receiveTx()
   765  	}
   766  
   767  	// Confirm the timeout tx. This should promote the HTLC to KNDR state.
   768  	timeoutTxHash := outgoingRes.SignedTimeoutTx.TxHash()
   769  	if err := ctx.notifier.ConfirmTx(&timeoutTxHash, 126); err != nil {
   770  		t.Fatal(err)
   771  	}
   772  
   773  	// Wait for output to be promoted in store to KNDR.
   774  	select {
   775  	case <-ctx.store.cribToKinderChan:
   776  	case <-time.After(defaultTestTimeout):
   777  		t.Fatalf("output not promoted to KNDR")
   778  	}
   779  
   780  	ctx.restart()
   781  
   782  	// Notify arrival of block where second level HTLC unlocks.
   783  	ctx.notifyEpoch(128)
   784  
   785  	// Check final sweep into wallet.
   786  	testSweepHtlc(t, ctx)
   787  
   788  	ctx.finish()
   789  }
   790  
   791  func TestNurseryOutgoingHtlcSuccessOnRemote(t *testing.T) {
   792  	testRestartLoop(t, testNurseryOutgoingHtlcSuccessOnRemote)
   793  }
   794  
   795  func testNurseryOutgoingHtlcSuccessOnRemote(t *testing.T,
   796  	checkStartStop func(func()) bool) {
   797  
   798  	ctx := createNurseryTestContext(t, checkStartStop)
   799  
   800  	outgoingRes := incubateTestOutput(t, ctx.nursery, false)
   801  
   802  	ctx.restart()
   803  
   804  	// Notify confirmation of the commitment tx. Is only listened to when
   805  	// resolving remote commitment tx.
   806  	//
   807  	// TODO(joostjager): This is probably not correct?
   808  	err := ctx.notifier.ConfirmTx(&outgoingRes.ClaimOutpoint.Hash, 124)
   809  	if err != nil {
   810  		t.Fatal(err)
   811  	}
   812  
   813  	// Wait for output to be promoted from PSCL to KNDR.
   814  	select {
   815  	case <-ctx.store.preschoolToKinderChan:
   816  	case <-time.After(defaultTestTimeout):
   817  		t.Fatalf("output not promoted to KNDR")
   818  	}
   819  
   820  	ctx.restart()
   821  
   822  	// Notify arrival of block where HTLC CLTV expires.
   823  	ctx.notifyEpoch(125)
   824  
   825  	// Check final sweep into wallet.
   826  	testSweepHtlc(t, ctx)
   827  
   828  	ctx.finish()
   829  }
   830  
   831  func testSweepHtlc(t *testing.T, ctx *nurseryTestContext) {
   832  	testSweep(t, ctx, func() {
   833  		// Verify stage in nursery report. HTLCs should now both still
   834  		// be in stage two.
   835  		assertNurseryReport(t, ctx.nursery, 1, 2, 10000)
   836  	})
   837  }
   838  
   839  func testSweep(t *testing.T, ctx *nurseryTestContext,
   840  	afterPublishAssert func()) {
   841  
   842  	// Wait for nursery to publish the sweep tx.
   843  	ctx.sweeper.expectSweep()
   844  
   845  	if ctx.restart() {
   846  		// Nursery reoffers its input after a restart.
   847  		ctx.sweeper.expectSweep()
   848  	}
   849  
   850  	afterPublishAssert()
   851  
   852  	// Confirm the sweep tx.
   853  	ctx.sweeper.sweepAll()
   854  
   855  	// Wait for output to be promoted in store to GRAD.
   856  	select {
   857  	case <-ctx.store.graduateKinderChan:
   858  	case <-time.After(defaultTestTimeout):
   859  		pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
   860  		t.Fatalf("output not graduated")
   861  	}
   862  
   863  	ctx.restart()
   864  
   865  	// As there only was one output to graduate, we expect the channel to be
   866  	// closed and no report available anymore.
   867  	assertNurseryReportUnavailable(t, ctx.nursery)
   868  }
   869  
   870  type nurseryStoreInterceptor struct {
   871  	ns NurseryStorer
   872  
   873  	// TODO(joostjager): put more useful info through these channels.
   874  	cribToKinderChan      chan struct{}
   875  	cribToRemoteSpendChan chan struct{}
   876  	graduateKinderChan    chan struct{}
   877  	preschoolToKinderChan chan struct{}
   878  }
   879  
   880  func newNurseryStoreInterceptor(ns NurseryStorer) *nurseryStoreInterceptor {
   881  	return &nurseryStoreInterceptor{
   882  		ns:                    ns,
   883  		cribToKinderChan:      make(chan struct{}),
   884  		cribToRemoteSpendChan: make(chan struct{}),
   885  		graduateKinderChan:    make(chan struct{}),
   886  		preschoolToKinderChan: make(chan struct{}),
   887  	}
   888  }
   889  
   890  func (i *nurseryStoreInterceptor) Incubate(kidOutputs []kidOutput,
   891  	babyOutputs []babyOutput) error {
   892  
   893  	return i.ns.Incubate(kidOutputs, babyOutputs)
   894  }
   895  
   896  func (i *nurseryStoreInterceptor) CribToKinder(babyOutput *babyOutput) error {
   897  	err := i.ns.CribToKinder(babyOutput)
   898  
   899  	i.cribToKinderChan <- struct{}{}
   900  
   901  	return err
   902  }
   903  
   904  func (i *nurseryStoreInterceptor) PreschoolToKinder(kidOutput *kidOutput,
   905  	lastGradHeight uint32) error {
   906  
   907  	err := i.ns.PreschoolToKinder(kidOutput, lastGradHeight)
   908  
   909  	i.preschoolToKinderChan <- struct{}{}
   910  
   911  	return err
   912  }
   913  
   914  func (i *nurseryStoreInterceptor) GraduateKinder(height uint32, kid *kidOutput) error {
   915  	err := i.ns.GraduateKinder(height, kid)
   916  
   917  	i.graduateKinderChan <- struct{}{}
   918  
   919  	return err
   920  }
   921  
   922  func (i *nurseryStoreInterceptor) FetchPreschools() ([]kidOutput, error) {
   923  	return i.ns.FetchPreschools()
   924  }
   925  
   926  func (i *nurseryStoreInterceptor) FetchClass(height uint32) (
   927  	[]kidOutput, []babyOutput, error) {
   928  
   929  	return i.ns.FetchClass(height)
   930  }
   931  
   932  func (i *nurseryStoreInterceptor) HeightsBelowOrEqual(height uint32) (
   933  	[]uint32, error) {
   934  
   935  	return i.ns.HeightsBelowOrEqual(height)
   936  }
   937  
   938  func (i *nurseryStoreInterceptor) ForChanOutputs(chanPoint *wire.OutPoint,
   939  	callback func([]byte, []byte) error, reset func()) error {
   940  
   941  	return i.ns.ForChanOutputs(chanPoint, callback, reset)
   942  }
   943  
   944  func (i *nurseryStoreInterceptor) ListChannels() ([]wire.OutPoint, error) {
   945  	return i.ns.ListChannels()
   946  }
   947  
   948  func (i *nurseryStoreInterceptor) IsMatureChannel(chanPoint *wire.OutPoint) (
   949  	bool, error) {
   950  
   951  	return i.ns.IsMatureChannel(chanPoint)
   952  }
   953  
   954  func (i *nurseryStoreInterceptor) RemoveChannel(chanPoint *wire.OutPoint) error {
   955  	return i.ns.RemoveChannel(chanPoint)
   956  }
   957  
   958  type mockSweeperFull struct {
   959  	lock sync.Mutex
   960  
   961  	resultChans map[wire.OutPoint]chan sweep.Result
   962  	t           *testing.T
   963  
   964  	sweepChan chan input.Input
   965  }
   966  
   967  func newMockSweeperFull(t *testing.T) *mockSweeperFull {
   968  	return &mockSweeperFull{
   969  		resultChans: make(map[wire.OutPoint]chan sweep.Result),
   970  		sweepChan:   make(chan input.Input, 1),
   971  		t:           t,
   972  	}
   973  }
   974  
   975  func (s *mockSweeperFull) sweepInput(input input.Input,
   976  	_ sweep.Params) (chan sweep.Result, error) {
   977  
   978  	log.Debugf("mockSweeperFull sweepInput called for %v", *input.OutPoint())
   979  
   980  	select {
   981  	case s.sweepChan <- input:
   982  	case <-time.After(defaultTestTimeout):
   983  		s.t.Fatal("signal result timeout")
   984  	}
   985  
   986  	s.lock.Lock()
   987  	defer s.lock.Unlock()
   988  
   989  	c := make(chan sweep.Result, 1)
   990  	s.resultChans[*input.OutPoint()] = c
   991  
   992  	return c, nil
   993  }
   994  
   995  func (s *mockSweeperFull) expectSweep() {
   996  	s.t.Helper()
   997  
   998  	select {
   999  	case <-s.sweepChan:
  1000  	case <-time.After(defaultTestTimeout):
  1001  		s.t.Fatal("signal result timeout")
  1002  	}
  1003  }
  1004  
  1005  func (s *mockSweeperFull) sweepAll() {
  1006  	s.t.Helper()
  1007  
  1008  	s.lock.Lock()
  1009  	currentChans := s.resultChans
  1010  	s.resultChans = make(map[wire.OutPoint]chan sweep.Result)
  1011  	s.lock.Unlock()
  1012  
  1013  	for o, c := range currentChans {
  1014  		log.Debugf("mockSweeperFull signal swept for %v", o)
  1015  
  1016  		select {
  1017  		case c <- sweep.Result{}:
  1018  		case <-time.After(defaultTestTimeout):
  1019  			s.t.Fatal("signal result timeout")
  1020  		}
  1021  	}
  1022  }