66 "crypto/sha256"
77 "fmt"
88 "io"
9- "sort"
109 "sync"
1110
1211 "github.com/btcsuite/btcd/btcec/v2"
@@ -180,14 +179,37 @@ func generateSharedSecrets(paymentPath []*btcec.PublicKey,
180179 return hopSharedSecrets , lastEphemeralPubKey , nil
181180}
182181
182+ type newOnionPacketCfg struct {
183+ payloadSize int
184+ }
185+
186+ type NewOnionPacketOpt func (cfg * newOnionPacketCfg )
187+
188+ func WithMaxPayloadSize (size int ) NewOnionPacketOpt {
189+ return func (cfg * newOnionPacketCfg ) {
190+ cfg .payloadSize = size
191+ }
192+ }
193+
183194// NewOnionPacket creates a new onion packet which is capable of obliviously
184195// routing a message through the mix-net path outline by 'paymentPath'. The
185196// total size of the onion 'clicks' to the first value in payloadSizes that is
186197// bigger than the total payload size of the path. If no size is given, it
187198// defaults to the maximum routing payload size.
188199func NewOnionPacket (paymentPath * PaymentPath , sessionKey * btcec.PrivateKey ,
189200 assocData []byte , pktFiller PacketFiller ,
190- payloadSizes ... int ) (* OnionPacket , error ) {
201+ opts ... NewOnionPacketOpt ) (* OnionPacket , error ) {
202+
203+ cfg := & newOnionPacketCfg {}
204+ for _ , o := range opts {
205+ o (cfg )
206+ }
207+
208+ // We default to the maximum routing payload size if the caller didn't
209+ // provide any payload sizes.
210+ if cfg .payloadSize == 0 {
211+ cfg .payloadSize = MaxRoutingPayloadSize
212+ }
191213
192214 // If we don't actually have a partially populated route, then we'll
193215 // exit early.
@@ -198,29 +220,9 @@ func NewOnionPacket(paymentPath *PaymentPath, sessionKey *btcec.PrivateKey,
198220
199221 totalPayloadSize := paymentPath .TotalPayloadSize ()
200222
201- // We default to the maximum routing payload size if the caller didn't
202- // provide any payload sizes.
203- if len (payloadSizes ) == 0 {
204- payloadSizes = []int {MaxRoutingPayloadSize }
205- }
206-
207- sort .Ints (payloadSizes )
208-
209- // We'll now select the smallest payload size that is large enough to
210- // fit the entire onion payload. If no such size exists, then we'll
211- // return an error
212- var payloadSize int
213- found := false
214- for _ , size := range payloadSizes {
215- if size >= totalPayloadSize {
216- payloadSize = size
217- found = true
218- break
219- }
220- }
221-
222- // Return an error if we couldn't find a suitable payload size.
223- if ! found {
223+ // Return an error if the actual payload size exceeds the configured
224+ // payload size.
225+ if totalPayloadSize > cfg .payloadSize {
224226 return nil , ErrPayloadSizeExceeded
225227 }
226228
@@ -241,13 +243,13 @@ func NewOnionPacket(paymentPath *PaymentPath, sessionKey *btcec.PrivateKey,
241243
242244 // Generate the padding, called "filler strings" in the paper.
243245 filler := generateHeaderPadding (
244- "rho" , paymentPath , hopSharedSecrets , payloadSize ,
246+ "rho" , paymentPath , hopSharedSecrets , cfg . payloadSize ,
245247 )
246248
247249 // Allocate zero'd out byte slices to store the final mix header packet
248250 // and the hmac for each hop.
249251 var (
250- mixHeader = make ([]byte , payloadSize )
252+ mixHeader = make ([]byte , cfg . payloadSize )
251253 nextHmac [HMACSize ]byte
252254 hopPayloadBuf bytes.Buffer
253255 )
@@ -274,7 +276,9 @@ func NewOnionPacket(paymentPath *PaymentPath, sessionKey *btcec.PrivateKey,
274276 // Next, using the key dedicated for our stream cipher, we'll
275277 // generate enough bytes to obfuscate this layer of the onion
276278 // packet.
277- streamBytes := generateCipherStream (rhoKey , uint (payloadSize ))
279+ streamBytes := generateCipherStream (
280+ rhoKey , uint (cfg .payloadSize ),
281+ )
278282 payload := paymentPath [i ].HopPayload
279283
280284 // Before we assemble the packet, we'll shift the current
0 commit comments