mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-28 09:47:20 +02:00
channeldb: add custom blobs to RevocationLog+HTLCEntry
This'll be useful for custom channel types that want to store extra information that'll be useful to help handle channel revocation cases.
This commit is contained in:
committed by
Oliver Gugger
parent
61f276856a
commit
669740c84e
@@ -164,22 +164,32 @@ type HTLCEntry struct {
|
||||
//
|
||||
// NOTE: this field is the memory representation of the field amtUint.
|
||||
Amt tlv.RecordT[tlv.TlvType4, tlv.BigSizeT[btcutil.Amount]]
|
||||
|
||||
// CustomBlob is an optional blob that can be used to store information
|
||||
// specific to revocation handling for a custom channel type.
|
||||
CustomBlob tlv.OptionalRecordT[tlv.TlvType5, tlv.Blob]
|
||||
}
|
||||
|
||||
// toTlvStream converts an HTLCEntry record into a tlv representation.
|
||||
func (h *HTLCEntry) toTlvStream() (*tlv.Stream, error) {
|
||||
return tlv.NewStream(
|
||||
records := []tlv.Record{
|
||||
h.RHash.Record(),
|
||||
h.RefundTimeout.Record(),
|
||||
h.OutputIndex.Record(),
|
||||
h.Incoming.Record(),
|
||||
h.Amt.Record(),
|
||||
)
|
||||
}
|
||||
|
||||
h.CustomBlob.WhenSome(func(r tlv.RecordT[tlv.TlvType5, tlv.Blob]) {
|
||||
records = append(records, r.Record())
|
||||
})
|
||||
|
||||
return tlv.NewStream(records...)
|
||||
}
|
||||
|
||||
// NewHTLCEntryFromHTLC creates a new HTLCEntry from an HTLC.
|
||||
func NewHTLCEntryFromHTLC(htlc HTLC) *HTLCEntry {
|
||||
return &HTLCEntry{
|
||||
func NewHTLCEntryFromHTLC(htlc HTLC) (*HTLCEntry, error) {
|
||||
h := &HTLCEntry{
|
||||
RHash: tlv.NewRecordT[tlv.TlvType0](
|
||||
NewSparsePayHash(htlc.RHash),
|
||||
),
|
||||
@@ -194,6 +204,19 @@ func NewHTLCEntryFromHTLC(htlc HTLC) *HTLCEntry {
|
||||
tlv.NewBigSizeT(htlc.Amt.ToSatoshis()),
|
||||
),
|
||||
}
|
||||
|
||||
if len(htlc.CustomRecords) != 0 {
|
||||
blob, err := htlc.CustomRecords.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h.CustomBlob = tlv.SomeRecordT(
|
||||
tlv.NewPrimitiveRecord[tlv.TlvType5, tlv.Blob](blob),
|
||||
)
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// RevocationLog stores the info needed to construct a breach retribution. Its
|
||||
@@ -236,13 +259,19 @@ type RevocationLog struct {
|
||||
// this field, it could be the case that the field is not present for
|
||||
// all revocation logs.
|
||||
TheirBalance tlv.OptionalRecordT[tlv.TlvType4, BigSizeMilliSatoshi]
|
||||
|
||||
// CustomBlob is an optional blob that can be used to store information
|
||||
// specific to a custom channel type. This information is only created
|
||||
// at channel funding time, and after wards is to be considered
|
||||
// immutable.
|
||||
CustomBlob tlv.OptionalRecordT[tlv.TlvType5, tlv.Blob]
|
||||
}
|
||||
|
||||
// NewRevocationLog creates a new RevocationLog from the given parameters.
|
||||
func NewRevocationLog(ourOutputIndex uint16, theirOutputIndex uint16,
|
||||
commitHash [32]byte, ourBalance,
|
||||
theirBalance fn.Option[lnwire.MilliSatoshi],
|
||||
htlcs []*HTLCEntry) RevocationLog {
|
||||
theirBalance fn.Option[lnwire.MilliSatoshi], htlcs []*HTLCEntry,
|
||||
customBlob fn.Option[tlv.Blob]) RevocationLog {
|
||||
|
||||
rl := RevocationLog{
|
||||
OurOutputIndex: tlv.NewPrimitiveRecord[tlv.TlvType0](
|
||||
@@ -267,6 +296,12 @@ func NewRevocationLog(ourOutputIndex uint16, theirOutputIndex uint16,
|
||||
))
|
||||
})
|
||||
|
||||
customBlob.WhenSome(func(blob tlv.Blob) {
|
||||
rl.CustomBlob = tlv.SomeRecordT(
|
||||
tlv.NewPrimitiveRecord[tlv.TlvType5, tlv.Blob](blob),
|
||||
)
|
||||
})
|
||||
|
||||
return rl
|
||||
}
|
||||
|
||||
@@ -298,6 +333,12 @@ func putRevocationLog(bucket kvdb.RwBucket, commit *ChannelCommitment,
|
||||
HTLCEntries: make([]*HTLCEntry, 0, len(commit.Htlcs)),
|
||||
}
|
||||
|
||||
commit.CustomBlob.WhenSome(func(blob tlv.Blob) {
|
||||
rl.CustomBlob = tlv.SomeRecordT(
|
||||
tlv.NewPrimitiveRecord[tlv.TlvType5, tlv.Blob](blob),
|
||||
)
|
||||
})
|
||||
|
||||
if !noAmtData {
|
||||
rl.OurBalance = tlv.SomeRecordT(tlv.NewRecordT[tlv.TlvType3](
|
||||
tlv.NewBigSizeT(commit.LocalBalance),
|
||||
@@ -320,7 +361,10 @@ func putRevocationLog(bucket kvdb.RwBucket, commit *ChannelCommitment,
|
||||
return ErrOutputIndexTooBig
|
||||
}
|
||||
|
||||
entry := NewHTLCEntryFromHTLC(htlc)
|
||||
entry, err := NewHTLCEntryFromHTLC(htlc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rl.HTLCEntries = append(rl.HTLCEntries, entry)
|
||||
}
|
||||
|
||||
@@ -373,6 +417,10 @@ func serializeRevocationLog(w io.Writer, rl *RevocationLog) error {
|
||||
},
|
||||
)
|
||||
|
||||
rl.CustomBlob.WhenSome(func(r tlv.RecordT[tlv.TlvType5, tlv.Blob]) {
|
||||
records = append(records, r.Record())
|
||||
})
|
||||
|
||||
// Create the tlv stream.
|
||||
tlvStream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
@@ -413,6 +461,7 @@ func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
|
||||
|
||||
ourBalance := rl.OurBalance.Zero()
|
||||
theirBalance := rl.TheirBalance.Zero()
|
||||
customBlob := rl.CustomBlob.Zero()
|
||||
|
||||
// Create the tlv stream.
|
||||
tlvStream, err := tlv.NewStream(
|
||||
@@ -421,6 +470,7 @@ func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
|
||||
rl.CommitTxHash.Record(),
|
||||
ourBalance.Record(),
|
||||
theirBalance.Record(),
|
||||
customBlob.Record(),
|
||||
)
|
||||
if err != nil {
|
||||
return rl, err
|
||||
@@ -440,6 +490,10 @@ func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
|
||||
rl.TheirBalance = tlv.SomeRecordT(theirBalance)
|
||||
}
|
||||
|
||||
if t, ok := parsedTypes[customBlob.TlvType()]; ok && t == nil {
|
||||
rl.CustomBlob = tlv.SomeRecordT(customBlob)
|
||||
}
|
||||
|
||||
// Read the HTLC entries.
|
||||
rl.HTLCEntries, err = deserializeHTLCEntries(r)
|
||||
|
||||
@@ -454,14 +508,26 @@ func deserializeHTLCEntries(r io.Reader) ([]*HTLCEntry, error) {
|
||||
for {
|
||||
var htlc HTLCEntry
|
||||
|
||||
customBlob := htlc.CustomBlob.Zero()
|
||||
|
||||
// Create the tlv stream.
|
||||
tlvStream, err := htlc.toTlvStream()
|
||||
records := []tlv.Record{
|
||||
htlc.RHash.Record(),
|
||||
htlc.RefundTimeout.Record(),
|
||||
htlc.OutputIndex.Record(),
|
||||
htlc.Incoming.Record(),
|
||||
htlc.Amt.Record(),
|
||||
customBlob.Record(),
|
||||
}
|
||||
|
||||
tlvStream, err := tlv.NewStream(records...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read the HTLC entry.
|
||||
if _, err := readTlvStream(r, tlvStream); err != nil {
|
||||
parsedTypes, err := readTlvStream(r, tlvStream)
|
||||
if err != nil {
|
||||
// We've reached the end when hitting an EOF.
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
break
|
||||
@@ -469,6 +535,10 @@ func deserializeHTLCEntries(r io.Reader) ([]*HTLCEntry, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if t, ok := parsedTypes[customBlob.TlvType()]; ok && t == nil {
|
||||
htlc.CustomBlob = tlv.SomeRecordT(customBlob)
|
||||
}
|
||||
|
||||
// Append the entry.
|
||||
htlcs = append(htlcs, &htlc)
|
||||
}
|
||||
|
Reference in New Issue
Block a user