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  }