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 }