github.com/decred/dcrlnd@v0.7.6/channeldb/migration_01_to_11/migration_11_invoices.go (about) 1 package migration_01_to_11 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 9 "github.com/decred/dcrd/chaincfg/v3" 10 "github.com/decred/dcrd/wire" 11 lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21" 12 "github.com/decred/dcrlnd/channeldb/migration_01_to_11/zpay32" 13 "github.com/decred/dcrlnd/kvdb" 14 ) 15 16 // MigrateInvoices adds invoice htlcs and a separate cltv delta field to the 17 // invoices. 18 func MigrateInvoices(tx kvdb.RwTx) error { 19 log.Infof("Migrating invoices to new invoice format") 20 21 invoiceB := tx.ReadWriteBucket(invoiceBucket) 22 if invoiceB == nil { 23 return nil 24 } 25 26 // Iterate through the entire key space of the top-level invoice bucket. 27 // If key with a non-nil value stores the next invoice ID which maps to 28 // the corresponding invoice. Store those keys first, because it isn't 29 // safe to modify the bucket inside a ForEach loop. 30 var invoiceKeys [][]byte 31 err := invoiceB.ForEach(func(k, v []byte) error { 32 if v == nil { 33 return nil 34 } 35 36 invoiceKeys = append(invoiceKeys, k) 37 38 return nil 39 }) 40 if err != nil { 41 return err 42 } 43 44 nets := []*chaincfg.Params{ 45 chaincfg.MainNetParams(), chaincfg.SimNetParams(), 46 chaincfg.RegNetParams(), chaincfg.TestNet3Params(), 47 } 48 49 // Iterate over all stored keys and migrate the invoices. 50 for _, k := range invoiceKeys { 51 v := invoiceB.Get(k) 52 53 // Deserialize the invoice with the deserializing function that 54 // was in use for this version of the database. 55 invoiceReader := bytes.NewReader(v) 56 invoice, err := deserializeInvoiceLegacy(invoiceReader) 57 if err != nil { 58 return err 59 } 60 61 if invoice.Terms.State == ContractAccepted { 62 return fmt.Errorf("cannot upgrade with invoice(s) " + 63 "in accepted state, see release notes") 64 } 65 66 // Try to decode the payment request for every possible net to 67 // avoid passing a the active network to channeldb. This would 68 // be a layering violation, while this migration is only running 69 // once and will likely be removed in the future. 70 var payReq *zpay32.Invoice 71 for _, net := range nets { 72 payReq, err = zpay32.Decode( 73 string(invoice.PaymentRequest), net, 74 ) 75 if err == nil { 76 break 77 } 78 } 79 if payReq == nil { 80 return fmt.Errorf("cannot decode payreq") 81 } 82 invoice.FinalCltvDelta = int32(payReq.MinFinalCLTVExpiry()) 83 invoice.Expiry = payReq.Expiry() 84 85 // Serialize the invoice in the new format and use it to replace 86 // the old invoice in the database. 87 var buf bytes.Buffer 88 if err := serializeInvoice(&buf, &invoice); err != nil { 89 return err 90 } 91 92 err = invoiceB.Put(k, buf.Bytes()) 93 if err != nil { 94 return err 95 } 96 } 97 98 log.Infof("Migration of invoices completed!") 99 return nil 100 } 101 102 func deserializeInvoiceLegacy(r io.Reader) (Invoice, error) { 103 var err error 104 invoice := Invoice{} 105 106 // TODO(roasbeef): use read full everywhere 107 invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "") 108 if err != nil { 109 return invoice, err 110 } 111 invoice.Receipt, err = wire.ReadVarBytes(r, 0, MaxReceiptSize, "") 112 if err != nil { 113 return invoice, err 114 } 115 116 invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "") 117 if err != nil { 118 return invoice, err 119 } 120 121 birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth") 122 if err != nil { 123 return invoice, err 124 } 125 if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil { 126 return invoice, err 127 } 128 129 settledBytes, err := wire.ReadVarBytes(r, 0, 300, "settled") 130 if err != nil { 131 return invoice, err 132 } 133 if err := invoice.SettleDate.UnmarshalBinary(settledBytes); err != nil { 134 return invoice, err 135 } 136 137 if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil { 138 return invoice, err 139 } 140 var scratch [8]byte 141 if _, err := io.ReadFull(r, scratch[:]); err != nil { 142 return invoice, err 143 } 144 invoice.Terms.Value = lnwire.MilliAtom(byteOrder.Uint64(scratch[:])) 145 146 if err := binary.Read(r, byteOrder, &invoice.Terms.State); err != nil { 147 return invoice, err 148 } 149 150 if err := binary.Read(r, byteOrder, &invoice.AddIndex); err != nil { 151 return invoice, err 152 } 153 if err := binary.Read(r, byteOrder, &invoice.SettleIndex); err != nil { 154 return invoice, err 155 } 156 if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil { 157 return invoice, err 158 } 159 160 return invoice, nil 161 } 162 163 // serializeInvoiceLegacy serializes an invoice in the format of the previous db 164 // version. 165 func serializeInvoiceLegacy(w io.Writer, i *Invoice) error { 166 if err := wire.WriteVarBytes(w, 0, i.Memo[:]); err != nil { 167 return err 168 } 169 if err := wire.WriteVarBytes(w, 0, i.Receipt[:]); err != nil { 170 return err 171 } 172 if err := wire.WriteVarBytes(w, 0, i.PaymentRequest[:]); err != nil { 173 return err 174 } 175 176 birthBytes, err := i.CreationDate.MarshalBinary() 177 if err != nil { 178 return err 179 } 180 181 if err := wire.WriteVarBytes(w, 0, birthBytes); err != nil { 182 return err 183 } 184 185 settleBytes, err := i.SettleDate.MarshalBinary() 186 if err != nil { 187 return err 188 } 189 190 if err := wire.WriteVarBytes(w, 0, settleBytes); err != nil { 191 return err 192 } 193 194 if _, err := w.Write(i.Terms.PaymentPreimage[:]); err != nil { 195 return err 196 } 197 198 var scratch [8]byte 199 byteOrder.PutUint64(scratch[:], uint64(i.Terms.Value)) 200 if _, err := w.Write(scratch[:]); err != nil { 201 return err 202 } 203 204 if err := binary.Write(w, byteOrder, i.Terms.State); err != nil { 205 return err 206 } 207 208 if err := binary.Write(w, byteOrder, i.AddIndex); err != nil { 209 return err 210 } 211 if err := binary.Write(w, byteOrder, i.SettleIndex); err != nil { 212 return err 213 } 214 if err := binary.Write(w, byteOrder, int64(i.AmtPaid)); err != nil { 215 return err 216 } 217 218 return nil 219 }