cba523ae30
This commit modifies the NewPayloadFromReader to apply known presence/omission contraints in the event that the tlv parser returns an unknown required type failure. Now that the parser has been modified to finished parsing the stream to obtain a proper parsed type set, we can accurately apply these higher level validation checks. This overrides required type failures, such that they are only returned if the sender properly abided by the constraints on fields for which we know. The unit tests are updated to create otherwise valid payloads that then return unknown required type failures. In one case, a test which previously returned an unknown required type failure is made to return an included failure for the sid, indicating the unknown required type 0 is being overruled.
151 lines
3.6 KiB
Go
151 lines
3.6 KiB
Go
package hop_test
|
|
|
|
import (
|
|
"bytes"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
|
"github.com/lightningnetwork/lnd/record"
|
|
)
|
|
|
|
type decodePayloadTest struct {
|
|
name string
|
|
payload []byte
|
|
expErr error
|
|
}
|
|
|
|
var decodePayloadTests = []decodePayloadTest{
|
|
{
|
|
name: "final hop valid",
|
|
payload: []byte{0x02, 0x00, 0x04, 0x00},
|
|
},
|
|
{
|
|
name: "intermediate hop valid",
|
|
payload: []byte{0x02, 0x00, 0x04, 0x00, 0x06, 0x08, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
},
|
|
{
|
|
name: "final hop no amount",
|
|
payload: []byte{0x04, 0x00},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: record.AmtOnionType,
|
|
Violation: hop.OmittedViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "intermediate hop no amount",
|
|
payload: []byte{0x04, 0x00, 0x06, 0x08, 0x01, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: record.AmtOnionType,
|
|
Violation: hop.OmittedViolation,
|
|
FinalHop: false,
|
|
},
|
|
},
|
|
{
|
|
name: "final hop no expiry",
|
|
payload: []byte{0x02, 0x00},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: record.LockTimeOnionType,
|
|
Violation: hop.OmittedViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "intermediate hop no expiry",
|
|
payload: []byte{0x02, 0x00, 0x06, 0x08, 0x01, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: record.LockTimeOnionType,
|
|
Violation: hop.OmittedViolation,
|
|
FinalHop: false,
|
|
},
|
|
},
|
|
{
|
|
name: "final hop next sid present",
|
|
payload: []byte{0x02, 0x00, 0x04, 0x00, 0x06, 0x08, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: record.NextHopOnionType,
|
|
Violation: hop.IncludedViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "required type after omitted hop id",
|
|
payload: []byte{0x02, 0x00, 0x04, 0x00, 0x08, 0x00},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: 8,
|
|
Violation: hop.RequiredViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "required type after included hop id",
|
|
payload: []byte{0x02, 0x00, 0x04, 0x00, 0x06, 0x08, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: 8,
|
|
Violation: hop.RequiredViolation,
|
|
FinalHop: false,
|
|
},
|
|
},
|
|
{
|
|
name: "required type zero final hop",
|
|
payload: []byte{0x00, 0x00, 0x02, 0x00, 0x04, 0x00},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: 0,
|
|
Violation: hop.RequiredViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "required type zero final hop zero sid",
|
|
payload: []byte{0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x08,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: 6,
|
|
Violation: hop.IncludedViolation,
|
|
FinalHop: true,
|
|
},
|
|
},
|
|
{
|
|
name: "required type zero intermediate hop",
|
|
payload: []byte{0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x08,
|
|
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
},
|
|
expErr: hop.ErrInvalidPayload{
|
|
Type: 0,
|
|
Violation: hop.RequiredViolation,
|
|
FinalHop: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
// TestDecodeHopPayloadRecordValidation asserts that parsing the payloads in the
|
|
// tests yields the expected errors depending on whether the proper fields were
|
|
// included or omitted.
|
|
func TestDecodeHopPayloadRecordValidation(t *testing.T) {
|
|
for _, test := range decodePayloadTests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
testDecodeHopPayloadValidation(t, test)
|
|
})
|
|
}
|
|
}
|
|
|
|
func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) {
|
|
_, err := hop.NewPayloadFromReader(bytes.NewReader(test.payload))
|
|
if !reflect.DeepEqual(test.expErr, err) {
|
|
t.Fatalf("expected error mismatch, want: %v, got: %v",
|
|
test.expErr, err)
|
|
}
|
|
}
|