github.com/decred/dcrlnd@v0.7.6/channeldb/migration12/migration_test.go (about) 1 package migration12_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 8 "github.com/decred/dcrlnd/channeldb/migration12" 9 "github.com/decred/dcrlnd/channeldb/migtest" 10 "github.com/decred/dcrlnd/kvdb" 11 "github.com/decred/dcrlnd/lntypes" 12 ) 13 14 var ( 15 // invoiceBucket is the name of the bucket within the database that 16 // stores all data related to invoices no matter their final state. 17 // Within the invoice bucket, each invoice is keyed by its invoice ID 18 // which is a monotonically increasing uint32. 19 invoiceBucket = []byte("invoices") 20 21 preimage = lntypes.Preimage{ 22 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 23 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 24 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 25 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 26 } 27 28 hash = preimage.Hash() 29 30 beforeInvoice0Htlcs = []byte{ 31 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 32 0x6c, 0x64, 0x09, 0x62, 0x79, 0x65, 0x20, 0x77, 0x6f, 0x72, 33 0x6c, 0x64, 0x06, 0x70, 0x61, 0x79, 0x72, 0x65, 0x71, 0x00, 34 0x00, 0x00, 0x20, 0x00, 0x00, 0x4e, 0x94, 0x91, 0x4f, 0x00, 35 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x77, 0xc4, 0xd3, 36 0xd5, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x0f, 0x01, 0x00, 37 0x00, 0x00, 0x0e, 0x77, 0xd5, 0xc8, 0x1c, 0x00, 0x00, 0x00, 38 0x00, 0xfe, 0x20, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 39 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 40 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 41 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 42 0x00, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa4, 45 } 46 47 afterInvoice0Htlcs = []byte{ 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x0b, 49 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 50 0x64, 0x01, 0x06, 0x70, 0x61, 0x79, 0x72, 0x65, 0x71, 0x02, 51 0x0f, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x77, 0xc4, 0xd3, 0xd5, 52 0x00, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x03, 0x0f, 0x01, 0x00, 53 0x00, 0x00, 0x0e, 0x77, 0xd5, 0xc8, 0x1c, 0x00, 0x00, 0x00, 54 0x00, 0xfe, 0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 55 0x00, 0x00, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 56 0x00, 0x00, 0x06, 0x06, 0x20, 0x42, 0x42, 0x42, 0x42, 0x42, 57 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 58 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 59 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x07, 0x08, 0x00, 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8, 0x08, 0x04, 0x00, 61 0x00, 0x00, 0x20, 0x09, 0x08, 0x00, 0x00, 0x4e, 0x94, 0x91, 62 0x4f, 0x00, 0x00, 0x0a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0c, 66 0x01, 0x03, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x01, 0xa4, 68 } 69 70 testHtlc = []byte{ 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 72 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 73 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 74 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 75 0x07, 0x04, 0x00, 0x00, 0x00, 0x58, 0x09, 0x08, 0x00, 0x13, 76 0xbc, 0xbf, 0x72, 0x4e, 0x1e, 0x00, 0x0b, 0x08, 0x00, 0x17, 77 0xaf, 0x4c, 0x22, 0xc4, 0x24, 0x00, 0x0d, 0x04, 0x00, 0x00, 78 0x23, 0x1d, 0x0f, 0x01, 0x02, 79 } 80 81 beforeInvoice1Htlc = append([]byte{ 82 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 83 0x6c, 0x64, 0x09, 0x62, 0x79, 0x65, 0x20, 0x77, 0x6f, 0x72, 84 0x6c, 0x64, 0x06, 0x70, 0x61, 0x79, 0x72, 0x65, 0x71, 0x00, 85 0x00, 0x00, 0x20, 0x00, 0x00, 0x4e, 0x94, 0x91, 0x4f, 0x00, 86 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x77, 0xc4, 0xd3, 87 0xd5, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x0f, 0x01, 0x00, 88 0x00, 0x00, 0x0e, 0x77, 0xd5, 0xc8, 0x1c, 0x00, 0x00, 0x00, 89 0x00, 0xfe, 0x20, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 90 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 91 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 92 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 93 0x00, 0x03, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa4, 96 }, testHtlc...) 97 98 afterInvoice1Htlc = append([]byte{ 99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x0b, 100 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 101 0x64, 0x01, 0x06, 0x70, 0x61, 0x79, 0x72, 0x65, 0x71, 0x02, 102 0x0f, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x77, 0xc4, 0xd3, 0xd5, 103 0x00, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x03, 0x0f, 0x01, 0x00, 104 0x00, 0x00, 0x0e, 0x77, 0xd5, 0xc8, 0x1c, 0x00, 0x00, 0x00, 105 0x00, 0xfe, 0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 106 0x00, 0x00, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 107 0x00, 0x00, 0x06, 0x06, 0x20, 0x42, 0x42, 0x42, 0x42, 0x42, 108 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 109 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 110 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x07, 0x08, 0x00, 111 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8, 0x08, 0x04, 0x00, 112 0x00, 0x00, 0x20, 0x09, 0x08, 0x00, 0x00, 0x4e, 0x94, 0x91, 113 0x4f, 0x00, 0x00, 0x0a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0c, 117 0x01, 0x03, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 0x01, 0xa4, 119 }, testHtlc...) 120 ) 121 122 type migrationTest struct { 123 name string 124 beforeMigration func(kvdb.RwTx) error 125 afterMigration func(kvdb.RwTx) error 126 } 127 128 var migrationTests = []migrationTest{ 129 { 130 name: "no invoices", 131 beforeMigration: func(kvdb.RwTx) error { return nil }, 132 afterMigration: func(kvdb.RwTx) error { return nil }, 133 }, 134 { 135 name: "zero htlcs", 136 beforeMigration: genBeforeMigration(beforeInvoice0Htlcs), 137 afterMigration: genAfterMigration(afterInvoice0Htlcs), 138 }, 139 { 140 name: "one htlc", 141 beforeMigration: genBeforeMigration(beforeInvoice1Htlc), 142 afterMigration: genAfterMigration(afterInvoice1Htlc), 143 }, 144 } 145 146 // genBeforeMigration creates a closure that inserts an invoice serialized under 147 // the old format under the test payment hash. 148 func genBeforeMigration(beforeBytes []byte) func(kvdb.RwTx) error { 149 return func(tx kvdb.RwTx) error { 150 invoices, err := tx.CreateTopLevelBucket( 151 invoiceBucket, 152 ) 153 if err != nil { 154 return err 155 } 156 157 return invoices.Put(hash[:], beforeBytes) 158 } 159 } 160 161 // genAfterMigration creates a closure that verifies the tlv invoice migration 162 // succeeded, but comparing the resulting encoding of the invoice to the 163 // expected serialization. In addition, the decoded invoice is compared against 164 // the expected invoice for equality. 165 func genAfterMigration(afterBytes []byte) func(kvdb.RwTx) error { 166 return func(tx kvdb.RwTx) error { 167 invoices := tx.ReadWriteBucket(invoiceBucket) 168 if invoices == nil { 169 return fmt.Errorf("invoice bucket not found") 170 } 171 172 // Fetch the new invoice bytes and check that they match our 173 // expected serialization. 174 invoiceBytes := invoices.Get(hash[:]) 175 if !bytes.Equal(invoiceBytes, afterBytes) { 176 return fmt.Errorf("invoice bytes mismatch, "+ 177 "want: %x, got: %x", 178 invoiceBytes, afterBytes) 179 } 180 181 return nil 182 } 183 } 184 185 // TestTLVInvoiceMigration executes a suite of migration tests for moving 186 // invoices to use TLV for their bodies. In the process, feature bits and 187 // payment addresses are added to the invoice while the receipt field is 188 // dropped. We test a few different invoices with a varying number of HTLCs, as 189 // well as the case where there are no invoices present. 190 // 191 // NOTE: The test vectors each include a receipt that is not present on the 192 // final struct, but verifies that the field is properly removed. 193 func TestTLVInvoiceMigration(t *testing.T) { 194 for _, test := range migrationTests { 195 test := test 196 t.Run(test.name, func(t *testing.T) { 197 migtest.ApplyMigration( 198 t, 199 test.beforeMigration, 200 test.afterMigration, 201 migration12.MigrateInvoiceTLV, 202 false, 203 ) 204 }) 205 } 206 }