@@ -1514,44 +1514,160 @@ func (k *kidOutput) Encode(w io.Writer) error {
15141514// Decode takes a byte array representation of a kidOutput and converts it to an
15151515// struct. Note that the witnessFunc method isn't added during deserialization
15161516// and must be added later based on the value of the witnessType field.
1517+ //
1518+ // NOTE: We need to support both formats because we did not migrate the database
1519+ // to the new format so the support for the legacy format is still needed.
15171520func (k * kidOutput ) Decode (r io.Reader ) error {
1521+ // Read all available data into a buffer first so we can try both
1522+ // formats.
1523+ //
1524+ // NOTE: We can consume the whole reader here because every kidOutput is
1525+ // saved separately via a key-value pair and we are only decoding them
1526+ // individually so there is no risk of reading multiple kidOutputs.
1527+ var buf bytes.Buffer
1528+ _ , err := io .Copy (& buf , r )
1529+ if err != nil {
1530+ return err
1531+ }
1532+
1533+ data := buf .Bytes ()
1534+ bufReader := bytes .NewReader (data )
1535+
1536+ // Try the new format first. A successful decode must consume all bytes.
1537+ newErr := k .decodeNewFormat (bufReader )
1538+ if newErr == nil && bufReader .Len () == 0 {
1539+ return nil
1540+ }
1541+
1542+ // If that fails, reset the reader and try the legacy format.
1543+ _ , err = bufReader .Seek (0 , io .SeekStart )
1544+ if err != nil {
1545+ return err
1546+ }
1547+
1548+ legacyErr := k .decodeLegacyFormat (bufReader )
1549+ if legacyErr != nil {
1550+ return fmt .Errorf ("failed to decode with both new and " +
1551+ "legacy formats: new=%v, legacy=%v" , newErr , legacyErr )
1552+ }
1553+
1554+ // The legacy format must also consume all bytes.
1555+ if bufReader .Len () > 0 {
1556+ return fmt .Errorf ("legacy decode has %d trailing bytes" ,
1557+ bufReader .Len ())
1558+ }
1559+
1560+ return nil
1561+ }
1562+
1563+ // decodeNewFormat decodes using the new format with variable-length outpoint
1564+ // encoding.
1565+ func (k * kidOutput ) decodeNewFormat (r * bytes.Reader ) error {
15181566 var scratch [8 ]byte
15191567
1520- if _ , err := r . Read ( scratch [:]); err != nil {
1568+ if _ , err := io . ReadFull ( r , scratch [:]); err != nil {
15211569 return err
15221570 }
15231571 k .amt = btcutil .Amount (byteOrder .Uint64 (scratch [:]))
15241572
1525- err := graphdb . ReadOutpoint ( io . LimitReader ( r , 40 ), & k . outpoint )
1526- if err != nil {
1573+ // The outpoint does use the new format without a preceding varint.
1574+ if err := graphdb . ReadOutpoint ( r , & k . outpoint ); err != nil {
15271575 return err
15281576 }
15291577
1530- err = graphdb .ReadOutpoint (io .LimitReader (r , 40 ), & k .originChanPoint )
1531- if err != nil {
1578+ // The origin chan point does use the new format without a preceding
1579+ // varint..
1580+ if err := graphdb .ReadOutpoint (r , & k .originChanPoint ); err != nil {
1581+ return err
1582+ }
1583+
1584+ if err := binary .Read (r , byteOrder , & k .isHtlc ); err != nil {
1585+ return err
1586+ }
1587+
1588+ if _ , err := io .ReadFull (r , scratch [:4 ]); err != nil {
1589+ return err
1590+ }
1591+ k .blocksToMaturity = byteOrder .Uint32 (scratch [:4 ])
1592+
1593+ if _ , err := io .ReadFull (r , scratch [:4 ]); err != nil {
1594+ return err
1595+ }
1596+ k .absoluteMaturity = byteOrder .Uint32 (scratch [:4 ])
1597+
1598+ if _ , err := io .ReadFull (r , scratch [:4 ]); err != nil {
1599+ return err
1600+ }
1601+ k .confHeight = byteOrder .Uint32 (scratch [:4 ])
1602+
1603+ if _ , err := io .ReadFull (r , scratch [:2 ]); err != nil {
1604+ return err
1605+ }
1606+ k .witnessType = input .StandardWitnessType (byteOrder .Uint16 (scratch [:2 ]))
1607+
1608+ if err := input .ReadSignDescriptor (r , & k .signDesc ); err != nil {
1609+ return err
1610+ }
1611+
1612+ // If there's anything left in the reader, then this is a taproot
1613+ // output that also wrote a control block.
1614+ ctrlBlock , err := wire .ReadVarBytes (r , 0 , 1000 , "control block" )
1615+ switch {
1616+ // If there're no bytes remaining, then we'll return early.
1617+ case errors .Is (err , io .EOF ):
1618+ fallthrough
1619+ case errors .Is (err , io .ErrUnexpectedEOF ):
1620+ return nil
1621+
1622+ case err != nil :
1623+ return err
1624+ }
1625+
1626+ k .signDesc .ControlBlock = ctrlBlock
1627+
1628+ return nil
1629+ }
1630+
1631+ // decodeLegacyFormat decodes using the legacy format with fixed-length outpoint
1632+ // encoding.
1633+ func (k * kidOutput ) decodeLegacyFormat (r * bytes.Reader ) error {
1634+ var scratch [8 ]byte
1635+
1636+ if _ , err := io .ReadFull (r , scratch [:]); err != nil {
1637+ return err
1638+ }
1639+ k .amt = btcutil .Amount (byteOrder .Uint64 (scratch [:]))
1640+
1641+ // Outpoint uses the legacy format with a preceding varint.
1642+ if err := readOutpointVarBytes (r , & k .outpoint ); err != nil {
1643+ return err
1644+ }
1645+
1646+ // Origin chan point uses the legacy format with a preceding varint.
1647+ if err := readOutpointVarBytes (r , & k .originChanPoint ); err != nil {
15321648 return err
15331649 }
15341650
15351651 if err := binary .Read (r , byteOrder , & k .isHtlc ); err != nil {
15361652 return err
15371653 }
15381654
1539- if _ , err := r . Read ( scratch [:4 ]); err != nil {
1655+ if _ , err := io . ReadFull ( r , scratch [:4 ]); err != nil {
15401656 return err
15411657 }
15421658 k .blocksToMaturity = byteOrder .Uint32 (scratch [:4 ])
15431659
1544- if _ , err := r . Read ( scratch [:4 ]); err != nil {
1660+ if _ , err := io . ReadFull ( r , scratch [:4 ]); err != nil {
15451661 return err
15461662 }
15471663 k .absoluteMaturity = byteOrder .Uint32 (scratch [:4 ])
15481664
1549- if _ , err := r . Read ( scratch [:4 ]); err != nil {
1665+ if _ , err := io . ReadFull ( r , scratch [:4 ]); err != nil {
15501666 return err
15511667 }
15521668 k .confHeight = byteOrder .Uint32 (scratch [:4 ])
15531669
1554- if _ , err := r . Read ( scratch [:2 ]); err != nil {
1670+ if _ , err := io . ReadFull ( r , scratch [:2 ]); err != nil {
15551671 return err
15561672 }
15571673 k .witnessType = input .StandardWitnessType (byteOrder .Uint16 (scratch [:2 ]))
@@ -1579,6 +1695,24 @@ func (k *kidOutput) Decode(r io.Reader) error {
15791695 return nil
15801696}
15811697
1698+ // readOutpointVarBytes reads an outpoint using the variable-length encoding.
1699+ func readOutpointVarBytes (r io.Reader , o * wire.OutPoint ) error {
1700+ scratch := make ([]byte , 4 )
1701+
1702+ txid , err := wire .ReadVarBytes (r , 0 , 32 , "prevout" )
1703+ if err != nil {
1704+ return err
1705+ }
1706+ copy (o .Hash [:], txid )
1707+
1708+ if _ , err := r .Read (scratch ); err != nil {
1709+ return err
1710+ }
1711+ o .Index = byteOrder .Uint32 (scratch )
1712+
1713+ return nil
1714+ }
1715+
15821716// Compile-time constraint to ensure kidOutput implements the
15831717// Input interface.
15841718
0 commit comments