|
| 1 | +package lnwire |
| 2 | + |
| 3 | +import ( |
| 4 | + "bytes" |
| 5 | + |
| 6 | + "github.com/lightningnetwork/lnd/tlv" |
| 7 | +) |
| 8 | + |
| 9 | +const ( |
| 10 | + // pureTLVUnsignedRangeOneStart defines the start of the first unsigned |
| 11 | + // TLV range used for pure TLV messages. The range is inclusive of this |
| 12 | + // number. |
| 13 | + pureTLVUnsignedRangeOneStart = 160 |
| 14 | + |
| 15 | + // pureTLVSignedSecondRangeStart defines the start of the second signed |
| 16 | + // TLV range used for pure TLV messages. The range is inclusive of this |
| 17 | + // number. Note that the first range is the inclusive range of 0-159. |
| 18 | + pureTLVSignedSecondRangeStart = 1000000000 |
| 19 | + |
| 20 | + // pureTLVUnsignedRangeTwoStart defines the start of the second unsigned |
| 21 | + // TLV range used for pure TLV message. |
| 22 | + pureTLVUnsignedRangeTwoStart = 3000000000 |
| 23 | +) |
| 24 | + |
| 25 | +// PureTLVMessage describes an LN message that is a pure TLV stream. If the |
| 26 | +// message includes a signature, it will sign all the TLV records in the |
| 27 | +// inclusive ranges: 0 to 159 and 1000000000 to 2999999999. |
| 28 | +type PureTLVMessage interface { |
| 29 | + // AllRecords returns all the TLV records for the message. This will |
| 30 | + // include all the records we know about along with any that we don't |
| 31 | + // know about but that fall in the signed TLV range. |
| 32 | + AllRecords() []tlv.Record |
| 33 | +} |
| 34 | + |
| 35 | +// EncodePureTLVMessage encodes the given PureTLVMessage to the given buffer. |
| 36 | +func EncodePureTLVMessage(msg PureTLVMessage, buf *bytes.Buffer) error { |
| 37 | + return EncodeRecordsTo(buf, msg.AllRecords()) |
| 38 | +} |
| 39 | + |
| 40 | +// SerialiseFieldsToSign serialises all the records from the given |
| 41 | +// PureTLVMessage that fall within the signed TLV range. |
| 42 | +func SerialiseFieldsToSign(msg PureTLVMessage) ([]byte, error) { |
| 43 | + // Filter out all the fields not in the signed ranges. |
| 44 | + var signedRecords []tlv.Record |
| 45 | + for _, record := range msg.AllRecords() { |
| 46 | + if InUnsignedRange(record.Type()) { |
| 47 | + continue |
| 48 | + } |
| 49 | + |
| 50 | + signedRecords = append(signedRecords, record) |
| 51 | + } |
| 52 | + |
| 53 | + var buf bytes.Buffer |
| 54 | + if err := EncodeRecordsTo(&buf, signedRecords); err != nil { |
| 55 | + return nil, err |
| 56 | + } |
| 57 | + |
| 58 | + return buf.Bytes(), nil |
| 59 | +} |
| 60 | + |
| 61 | +// InUnsignedRange returns true if the given TLV type falls outside the TLV |
| 62 | +// ranges that the signature of a pure TLV message will cover. |
| 63 | +func InUnsignedRange(t tlv.Type) bool { |
| 64 | + return (t >= pureTLVUnsignedRangeOneStart && |
| 65 | + t < pureTLVSignedSecondRangeStart) || |
| 66 | + t >= pureTLVUnsignedRangeTwoStart |
| 67 | +} |
| 68 | + |
| 69 | +// ExtraSignedFields is a type that stores a map from TLV types in the signed |
| 70 | +// range (for PureMessages) to their corresponding serialised values. This type |
| 71 | +// can be used to keep around data that we don't yet understand but that we need |
| 72 | +// for re-composing the wire message since the signature covers these fields. |
| 73 | +type ExtraSignedFields map[uint64][]byte |
| 74 | + |
| 75 | +// ExtraSignedFieldsFromTypeMap is a helper that can be used alongside calls to |
| 76 | +// the tlv.Stream DecodeWithParsedTypesP2P or DecodeWithParsedTypes methods to |
| 77 | +// extract the tlv type and value pairs in the defined PureTLVMessage signed |
| 78 | +// range which we have not handled with any of our defined Records. These |
| 79 | +// methods will return a tlv.TypeMap containing the records that were extracted |
| 80 | +// from an io.Reader. If the record was know and handled by a defined record, |
| 81 | +// then the value accompanying the record's type in the map will be nil. |
| 82 | +// Otherwise, if the record was unhandled, it will be non-nil. |
| 83 | +func ExtraSignedFieldsFromTypeMap(m tlv.TypeMap) ExtraSignedFields { |
| 84 | + extraFields := make(ExtraSignedFields) |
| 85 | + for t, v := range m { |
| 86 | + // If the value in the type map is nil, then it indicates that |
| 87 | + // we know this type, and it was handled by one of the records |
| 88 | + // we passed to the decode function vai the TLV stream. |
| 89 | + if v == nil { |
| 90 | + continue |
| 91 | + } |
| 92 | + |
| 93 | + // No need to keep this field if it is unknown to us and is not |
| 94 | + // in the sign range. |
| 95 | + if InUnsignedRange(t) { |
| 96 | + continue |
| 97 | + } |
| 98 | + |
| 99 | + // Otherwise, this is an un-handled type, so we keep track of |
| 100 | + // it for signature validation and re-encoding later on. |
| 101 | + extraFields[uint64(t)] = v |
| 102 | + } |
| 103 | + |
| 104 | + return extraFields |
| 105 | +} |
0 commit comments