Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lnwire+netann: update structure of g175 messages to be pure TLV #9175

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions lnwire/pure_tlv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package lnwire

import (
"bytes"

"github.com/lightningnetwork/lnd/tlv"
)

const (
pureTLVUnsignedRangeOneStart = 160
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have godoc comments.

pureTLVSignedSecondRangeStart = 1000000000
pureTLVUnsignedRangeTwoStart = 3000000000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we arrive at these values?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think we should try to capture this in the spec, independent of G 1.75.

)

// PureTLVMessage describes an LN message that is a pure TLV stream. If the
// message includes a signature, it will sign all the TLV records in the
// inclusive ranges: 0 to 159 and 1000000000 to 2999999999.
type PureTLVMessage interface {
// AllRecords returns all the TLV records for the message. This will
// include all the records we know about along with any that we don't
// know about but that fall in the signed TLV range.
AllRecords() []tlv.Record
}

// EncodePureTLVMessage encodes the given PureTLVMessage to the given buffer.
func EncodePureTLVMessage(msg PureTLVMessage, buf *bytes.Buffer) error {
return EncodeRecordsTo(buf, msg.AllRecords())
}

// SerialiseFieldsToSign serialises all the records from the given
// PureTLVMessage that fall within the signed TLV range.
func SerialiseFieldsToSign(msg PureTLVMessage) ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to adopt a similar structure for the signed portion of the dyn commit messages @ProofOfKeags. Basically we copied over from the way BOLT 12 works, and we can use the TLV type values, then let this handle how serialization works (does require a message to be pure TLV).

// Filter out all the fields not in the signed ranges.
var signedRecords []tlv.Record
for _, record := range msg.AllRecords() {
if InUnsignedRange(record.Type()) {
continue
}

signedRecords = append(signedRecords, record)
}

var buf bytes.Buffer
if err := EncodeRecordsTo(&buf, signedRecords); err != nil {
return nil, err
}

return buf.Bytes(), nil
}

// InUnsignedRange returns true if the given TLV type falls outside the TLV
// ranges that the signature of a pure TLV message will cover.
func InUnsignedRange(t tlv.Type) bool {
return (t >= pureTLVUnsignedRangeOneStart &&
t < pureTLVSignedSecondRangeStart) ||
t >= pureTLVUnsignedRangeTwoStart
}

// ExtraSignedFieldsFromTypeMap is a helper that can be used alongside calls to
// the tlv.Stream DecodeWithParsedTypesP2P or DecodeWithParsedTypes methods to
// extract the tlv type and value pairs in the defined PureTLVMessage signed
// range which we have not handled with any of our defined Records. These
// methods will return a tlv.TypeMap containing the records that were extracted
// from an io.Reader. If the record was know and handled by a defined record,
// then the value accompanying the record's type in the map will be nil.
// Otherwise, if the record was unhandled, it will be non-nil.
func ExtraSignedFieldsFromTypeMap(m tlv.TypeMap) map[uint64][]byte {
extraFields := make(map[uint64][]byte)
for t, v := range m {
// If the value in the type map is nil, then it indicates that
// we know this type, and it was handled by one of the records
// we passed to the decode function vai the TLV stream.
if v == nil {
continue
}

// No need to keep this field if it is unknown to us and is not
// in the sign range.
if InUnsignedRange(t) {
continue
}

// Otherwise, this is an un-handled type, so we keep track of
// it for signature validation and re-encoding later on.
extraFields[uint64(t)] = v
}

return extraFields
}
Loading