record/routing: set minimum padding size

This commit is contained in:
Elle Mouton 2024-07-26 10:32:47 +02:00
parent 398623bde5
commit 60a856ab65
No known key found for this signature in database
GPG Key ID: D7D916376026F177
4 changed files with 34 additions and 7 deletions

View File

@ -10,6 +10,13 @@ import (
"github.com/lightningnetwork/lnd/tlv"
)
// AverageDummyHopPayloadSize is the size of a standard blinded path dummy hop
// payload. In most cases, this is larger than the other payload types and so
// to make sure that a sender cannot use this fact to know if a dummy hop is
// present or not, we'll make sure to always pad all payloads to at least this
// size.
const AverageDummyHopPayloadSize = 51
// BlindedRouteData contains the information that is included in a blinded
// route encrypted data blob that is created by the recipient to provide
// forwarding information.

View File

@ -196,6 +196,10 @@ func TestDummyHopBlindedDataEncoding(t *testing.T) {
encoded, err := EncodeBlindedRouteData(routeData)
require.NoError(t, err)
// Assert the size of an average dummy hop payload in case we need to
// update this constant in future.
require.Len(t, encoded, AverageDummyHopPayloadSize)
b := bytes.NewBuffer(encoded)
decodedData, err := DecodeBlindedRouteData(b)
require.NoError(t, err)

View File

@ -257,7 +257,9 @@ func buildBlindedPaymentPath(cfg *BuildBlindedPathCfg, path *candidatePath) (
// Add padding to each route data instance until the encrypted data
// blobs are all the same size.
paymentPath, _, err := padHopInfo(hopDataSet, true)
paymentPath, _, err := padHopInfo(
hopDataSet, true, record.AverageDummyHopPayloadSize,
)
if err != nil {
return nil, err
}
@ -731,9 +733,10 @@ type padStats struct {
// edges. The number of iterations that this function takes is also returned for
// testing purposes. If prePad is true, then zero byte padding is added to each
// payload that does not yet have padding. This will save some iterations for
// the majority of cases.
func padHopInfo(hopInfo []*hopData, prePad bool) ([]*sphinx.HopInfo, *padStats,
error) {
// the majority of cases. minSize can be used to specify a minimum size that all
// payloads should be.
func padHopInfo(hopInfo []*hopData, prePad bool, minSize int) (
[]*sphinx.HopInfo, *padStats, error) {
var (
paymentPath = make([]*sphinx.HopInfo, len(hopInfo))
@ -759,7 +762,7 @@ func padHopInfo(hopInfo []*hopData, prePad bool) ([]*sphinx.HopInfo, *padStats,
// current largest encoded data blob size. This will be the
// size we aim to get the others to match.
var (
maxLen int
maxLen = minSize
minLen = math.MaxInt8
)
for i, hop := range hopInfo {

View File

@ -237,6 +237,10 @@ func TestPadBlindedHopInfo(t *testing.T) {
// prePad is true if all the hop payloads should be pre-padded
// with a zero length TLV Padding field.
prePad bool
// minPayloadSize can be used to set the minimum number of bytes
// that the resulting records should be.
minPayloadSize int
}{
{
// If there is only one entry, then no padding is
@ -250,6 +254,15 @@ func TestPadBlindedHopInfo(t *testing.T) {
// bytes.
expectedFinalSize: 12,
},
{
// Same as the above example but with a minimum final
// size specified.
name: "single entry with min size",
expectedIterations: 2,
pathIDs: []int{10},
minPayloadSize: 500,
expectedFinalSize: 504,
},
{
// All the payloads are the same size from the get go
// meaning that no padding is expected.
@ -376,7 +389,7 @@ func TestPadBlindedHopInfo(t *testing.T) {
}
hopInfo, stats, err := padHopInfo(
hopDataSet, test.prePad,
hopDataSet, test.prePad, test.minPayloadSize,
)
require.NoError(t, err)
require.Equal(t, test.expectedIterations,
@ -400,7 +413,7 @@ func TestPadBlindedHopInfo(t *testing.T) {
// asserts that the resulting padded set always has the same encoded length.
func TestPadBlindedHopInfoBlackBox(t *testing.T) {
fn := func(data hopDataList) bool {
resultList, _, err := padHopInfo(data, true)
resultList, _, err := padHopInfo(data, true, 0)
require.NoError(t, err)
// There should be a resulting sphinx.HopInfo struct for each