github.com/decred/dcrlnd@v0.7.6/channeldb/migration21/migration_test.go (about)

     1  package migration21
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/davecgh/go-spew/spew"
    10  	"github.com/decred/dcrd/chaincfg/chainhash"
    11  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    12  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
    13  	"github.com/decred/dcrd/wire"
    14  	lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21"
    15  	"github.com/decred/dcrlnd/channeldb/migration21/common"
    16  	"github.com/decred/dcrlnd/channeldb/migration21/current"
    17  	"github.com/decred/dcrlnd/channeldb/migration21/legacy"
    18  	"github.com/decred/dcrlnd/channeldb/migtest"
    19  	"github.com/decred/dcrlnd/kvdb"
    20  )
    21  
    22  var (
    23  	key = [chainhash.HashSize]byte{
    24  		0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
    25  		0x68, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    26  		0xd, 0xe7, 0x93, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    27  		0x1e, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
    28  	}
    29  
    30  	pubKey = secp256k1.PrivKeyFromBytes(key[:]).PubKey()
    31  
    32  	wireSig, _ = lnwire.NewSigFromSignature(testSig)
    33  
    34  	testSig = ecdsa.NewSignature(
    35  		mustDecodeModNScalar("063724406601629180062774974542967536251589935445068131219452686511677818569431"),
    36  		mustDecodeModNScalar("018801056069249825825291287104931333862866033135609736119018462340006816851118"),
    37  	)
    38  
    39  	testTx = &wire.MsgTx{
    40  		Version: 1,
    41  		TxIn: []*wire.TxIn{
    42  			{
    43  				PreviousOutPoint: wire.OutPoint{
    44  					Hash:  chainhash.Hash{},
    45  					Index: 0xffffffff,
    46  				},
    47  				SignatureScript: []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62},
    48  				Sequence:        0xffffffff,
    49  			},
    50  		},
    51  		TxOut: []*wire.TxOut{
    52  			{
    53  				Value: 5000000000,
    54  				PkScript: []byte{
    55  					0x41, // OP_DATA_65
    56  					0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
    57  					0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
    58  					0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
    59  					0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
    60  					0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
    61  					0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
    62  					0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
    63  					0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
    64  					0xa6, // 65-byte signature
    65  					0xac, // OP_CHECKSIG
    66  				},
    67  			},
    68  		},
    69  		LockTime: 5,
    70  	}
    71  
    72  	testCommitDiff = &common.CommitDiff{
    73  		Commitment: common.ChannelCommitment{
    74  			CommitTx:  testTx,
    75  			CommitSig: make([]byte, 0),
    76  		},
    77  		CommitSig: &lnwire.CommitSig{
    78  			ChanID:    lnwire.ChannelID(key),
    79  			CommitSig: wireSig,
    80  			HtlcSigs: []lnwire.Sig{
    81  				wireSig,
    82  				wireSig,
    83  			},
    84  		},
    85  		LogUpdates: []common.LogUpdate{
    86  			{
    87  				LogIndex: 1,
    88  				UpdateMsg: &lnwire.UpdateAddHTLC{
    89  					ID:     1,
    90  					Amount: lnwire.NewMAtomsFromAtoms(100),
    91  					Expiry: 25,
    92  				},
    93  			},
    94  			{
    95  				LogIndex: 2,
    96  				UpdateMsg: &lnwire.UpdateAddHTLC{
    97  					ID:     2,
    98  					Amount: lnwire.NewMAtomsFromAtoms(200),
    99  					Expiry: 50,
   100  				},
   101  			},
   102  		},
   103  		OpenedCircuitKeys: []common.CircuitKey{},
   104  		ClosedCircuitKeys: []common.CircuitKey{},
   105  	}
   106  
   107  	testNetworkResult = &common.NetworkResult{
   108  		Msg:          testCommitDiff.CommitSig,
   109  		Unencrypted:  true,
   110  		IsResolution: true,
   111  	}
   112  
   113  	testChanCloseSummary = &common.ChannelCloseSummary{
   114  		RemotePub:               pubKey,
   115  		Capacity:                9,
   116  		RemoteCurrentRevocation: pubKey,
   117  		RemoteNextRevocation:    pubKey,
   118  		LastChanSyncMsg: &lnwire.ChannelReestablish{
   119  			LocalUnrevokedCommitPoint: pubKey,
   120  		},
   121  	}
   122  
   123  	netResultKey = []byte{3}
   124  
   125  	chanID = lnwire.NewChanIDFromOutPoint(&wire.OutPoint{})
   126  
   127  	adds = []common.LogUpdate{
   128  		{
   129  			LogIndex: 0,
   130  			UpdateMsg: &lnwire.UpdateAddHTLC{
   131  				ChanID:      chanID,
   132  				ID:          1,
   133  				Amount:      100,
   134  				Expiry:      1000,
   135  				PaymentHash: [32]byte{0},
   136  			},
   137  		},
   138  		{
   139  			LogIndex: 1,
   140  			UpdateMsg: &lnwire.UpdateAddHTLC{
   141  				ChanID:      chanID,
   142  				ID:          1,
   143  				Amount:      101,
   144  				Expiry:      1001,
   145  				PaymentHash: [32]byte{1},
   146  			},
   147  		},
   148  	}
   149  
   150  	settleFails = []common.LogUpdate{
   151  		{
   152  			LogIndex: 2,
   153  			UpdateMsg: &lnwire.UpdateFulfillHTLC{
   154  				ChanID:          chanID,
   155  				ID:              0,
   156  				PaymentPreimage: [32]byte{0},
   157  			},
   158  		},
   159  		{
   160  			LogIndex: 3,
   161  			UpdateMsg: &lnwire.UpdateFailHTLC{
   162  				ChanID: chanID,
   163  				ID:     1,
   164  				Reason: []byte{},
   165  			},
   166  		},
   167  	}
   168  )
   169  
   170  // TestMigrateDatabaseWireMessages tests that we're able to properly migrate
   171  // all the wire messages in the database which are written without a length
   172  // prefix in front of them. At the time this test was written we need to
   173  // migrate three areas: open channel commit diffs, open channel unacked updates,
   174  // and network results in the switch.
   175  func TestMigrateDatabaseWireMessages(t *testing.T) {
   176  
   177  	var pub [33]byte
   178  	copy(pub[:], key[:])
   179  
   180  	migtest.ApplyMigration(
   181  		t,
   182  		func(tx kvdb.RwTx) error {
   183  			t.Helper()
   184  
   185  			// First, we'll insert a new fake channel (well just
   186  			// the commitment diff) at the expected location
   187  			// on-disk.
   188  			openChanBucket, err := tx.CreateTopLevelBucket(
   189  				openChannelBucket,
   190  			)
   191  			if err != nil {
   192  				return err
   193  			}
   194  			nodeBucket, err := openChanBucket.CreateBucket(pub[:])
   195  			if err != nil {
   196  				return err
   197  			}
   198  			chainBucket, err := nodeBucket.CreateBucket(key[:])
   199  			if err != nil {
   200  				return err
   201  			}
   202  			chanBucket, err := chainBucket.CreateBucket(key[:])
   203  			if err != nil {
   204  				return err
   205  			}
   206  
   207  			var b bytes.Buffer
   208  			err = legacy.SerializeCommitDiff(&b, testCommitDiff)
   209  			if err != nil {
   210  				return err
   211  			}
   212  
   213  			err = chanBucket.Put(commitDiffKey, b.Bytes())
   214  			if err != nil {
   215  				return err
   216  			}
   217  
   218  			var logUpdateBuf bytes.Buffer
   219  			err = legacy.SerializeLogUpdates(
   220  				&logUpdateBuf, testCommitDiff.LogUpdates,
   221  			)
   222  			if err != nil {
   223  				return err
   224  			}
   225  
   226  			// We'll re-use the same log updates to insert as a set
   227  			// of un-acked and unsigned pending log updateas as well.
   228  			err = chanBucket.Put(
   229  				unsignedAckedUpdatesKey, logUpdateBuf.Bytes(),
   230  			)
   231  			if err != nil {
   232  				return err
   233  			}
   234  
   235  			err = chanBucket.Put(
   236  				remoteUnsignedLocalUpdatesKey, logUpdateBuf.Bytes(),
   237  			)
   238  			if err != nil {
   239  				return err
   240  			}
   241  
   242  			// Next, we'll insert a sample closed channel summary
   243  			// for the 2nd part of our migration.
   244  			closedChanBucket, err := tx.CreateTopLevelBucket(
   245  				closedChannelBucket,
   246  			)
   247  			if err != nil {
   248  				return err
   249  			}
   250  
   251  			var summaryBuf bytes.Buffer
   252  			err = legacy.SerializeChannelCloseSummary(
   253  				&summaryBuf, testChanCloseSummary,
   254  			)
   255  			if err != nil {
   256  				return err
   257  			}
   258  
   259  			err = closedChanBucket.Put(key[:], summaryBuf.Bytes())
   260  			if err != nil {
   261  				return err
   262  			}
   263  
   264  			// Create a few forwarding packages to migrate.
   265  			for i := uint64(100); i < 200; i++ {
   266  				shortChanID := lnwire.NewShortChanIDFromInt(i)
   267  				packager := legacy.NewChannelPackager(shortChanID)
   268  				fwdPkg := common.NewFwdPkg(shortChanID, 0, adds, settleFails)
   269  
   270  				if err := packager.AddFwdPkg(tx, fwdPkg); err != nil {
   271  					return err
   272  				}
   273  			}
   274  
   275  			// Finally, we need to insert a sample network result
   276  			// as well for the final component of our migration.
   277  			var netResBuf bytes.Buffer
   278  			err = legacy.SerializeNetworkResult(
   279  				&netResBuf, testNetworkResult,
   280  			)
   281  			if err != nil {
   282  				return err
   283  			}
   284  
   285  			networkResults, err := tx.CreateTopLevelBucket(
   286  				networkResultStoreBucketKey,
   287  			)
   288  			if err != nil {
   289  				return err
   290  			}
   291  
   292  			return networkResults.Put(
   293  				netResultKey, netResBuf.Bytes(),
   294  			)
   295  		},
   296  		func(tx kvdb.RwTx) error {
   297  			t.Helper()
   298  
   299  			// We'll now read the commit diff from disk using the
   300  			// _new_ decoding method. This should match the commit
   301  			// diff we inserted in the pre-migration step.
   302  			openChanBucket := tx.ReadWriteBucket(openChannelBucket)
   303  			nodeBucket := openChanBucket.NestedReadWriteBucket(
   304  				pub[:],
   305  			)
   306  			chainBucket := nodeBucket.NestedReadWriteBucket(key[:])
   307  			chanBucket := chainBucket.NestedReadWriteBucket(key[:])
   308  
   309  			commitDiffBytes := chanBucket.Get(commitDiffKey)
   310  			if commitDiffBytes == nil {
   311  				return fmt.Errorf("no commit diff found")
   312  			}
   313  
   314  			newCommitDiff, err := current.DeserializeCommitDiff(
   315  				bytes.NewReader(commitDiffBytes),
   316  			)
   317  			if err != nil {
   318  				return fmt.Errorf("unable to decode commit "+
   319  					"diff: %v", err)
   320  			}
   321  
   322  			if !reflect.DeepEqual(newCommitDiff, testCommitDiff) {
   323  				return fmt.Errorf("diff mismatch: expected "+
   324  					"%v, got %v", spew.Sdump(testCommitDiff),
   325  					spew.Sdump(newCommitDiff))
   326  			}
   327  
   328  			// Next, we'll ensure that the un-acked updates match
   329  			// up as well.
   330  			updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
   331  			if updateBytes == nil {
   332  				return fmt.Errorf("no update bytes found")
   333  			}
   334  
   335  			newUpdates, err := current.DeserializeLogUpdates(
   336  				bytes.NewReader(updateBytes),
   337  			)
   338  			if err != nil {
   339  				return err
   340  			}
   341  
   342  			if !reflect.DeepEqual(
   343  				newUpdates, testCommitDiff.LogUpdates,
   344  			) {
   345  				return fmt.Errorf("updates mismatch: expected "+
   346  					"%v, got %v",
   347  					spew.Sdump(testCommitDiff.LogUpdates),
   348  					spew.Sdump(newUpdates))
   349  			}
   350  
   351  			updateBytes = chanBucket.Get(remoteUnsignedLocalUpdatesKey)
   352  			if updateBytes == nil {
   353  				return fmt.Errorf("no update bytes found")
   354  			}
   355  
   356  			newUpdates, err = current.DeserializeLogUpdates(
   357  				bytes.NewReader(updateBytes),
   358  			)
   359  			if err != nil {
   360  				return err
   361  			}
   362  
   363  			if !reflect.DeepEqual(
   364  				newUpdates, testCommitDiff.LogUpdates,
   365  			) {
   366  				return fmt.Errorf("updates mismatch: expected "+
   367  					"%v, got %v",
   368  					spew.Sdump(testCommitDiff.LogUpdates),
   369  					spew.Sdump(newUpdates))
   370  			}
   371  
   372  			// Next, we'll ensure that the inserted close channel
   373  			// summary bytes also mach up with what we inserted in
   374  			// the prior step.
   375  			closedChanBucket := tx.ReadWriteBucket(
   376  				closedChannelBucket,
   377  			)
   378  			if closedChannelBucket == nil {
   379  				return fmt.Errorf("no closed channels found")
   380  			}
   381  
   382  			chanSummaryBytes := closedChanBucket.Get(key[:])
   383  			newChanCloseSummary, err := current.DeserializeCloseChannelSummary(
   384  				bytes.NewReader(chanSummaryBytes),
   385  			)
   386  			if err != nil {
   387  				return err
   388  			}
   389  
   390  			if !reflect.DeepEqual(
   391  				newChanCloseSummary, testChanCloseSummary,
   392  			) {
   393  				return fmt.Errorf("summary mismatch: expected "+
   394  					"%v, got %v",
   395  					spew.Sdump(testChanCloseSummary),
   396  					spew.Sdump(newChanCloseSummary))
   397  			}
   398  
   399  			// Fetch all forwarding packages.
   400  			for i := uint64(100); i < 200; i++ {
   401  				shortChanID := lnwire.NewShortChanIDFromInt(i)
   402  				packager := current.NewChannelPackager(shortChanID)
   403  
   404  				fwdPkgs, err := packager.LoadFwdPkgs(tx)
   405  				if err != nil {
   406  					return err
   407  				}
   408  
   409  				if len(fwdPkgs) != 1 {
   410  					return fmt.Errorf("expected 1 pkg")
   411  				}
   412  
   413  				og := common.NewFwdPkg(shortChanID, 0, adds, settleFails)
   414  
   415  				// Check that we deserialized the packages correctly.
   416  				if !reflect.DeepEqual(fwdPkgs[0], og) {
   417  					return fmt.Errorf("res mismatch: expected "+
   418  						"%v, got %v",
   419  						spew.Sdump(fwdPkgs[0]),
   420  						spew.Sdump(og))
   421  				}
   422  			}
   423  
   424  			// Finally, we'll check the network results to ensure
   425  			// that was migrated properly as well.
   426  			networkResults := tx.ReadBucket(
   427  				networkResultStoreBucketKey,
   428  			)
   429  			if networkResults == nil {
   430  				return fmt.Errorf("no net results found")
   431  			}
   432  
   433  			netResBytes := networkResults.Get(netResultKey)
   434  			if netResBytes == nil {
   435  				return fmt.Errorf("no network res found")
   436  			}
   437  
   438  			newNetRes, err := current.DeserializeNetworkResult(
   439  				bytes.NewReader(netResBytes),
   440  			)
   441  			if err != nil {
   442  				return err
   443  			}
   444  
   445  			if !reflect.DeepEqual(newNetRes, testNetworkResult) {
   446  				return fmt.Errorf("res mismatch: expected "+
   447  					"%v, got %v",
   448  					spew.Sdump(testNetworkResult),
   449  					spew.Sdump(newNetRes))
   450  			}
   451  
   452  			return nil
   453  		},
   454  		MigrateDatabaseWireMessages,
   455  		false,
   456  	)
   457  }