Merge pull request #10532 from spesmilo/variable_trampoline_onions
trampoline: allow trampoline onion packets of arbitrary size
This commit is contained in:
+4
-17
@@ -47,7 +47,6 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
HOPS_DATA_SIZE = 1300 # also sometimes called routingInfoSize in bolt-04
|
||||
TRAMPOLINE_HOPS_DATA_SIZE = 400
|
||||
PER_HOP_HMAC_SIZE = 32
|
||||
ONION_MESSAGE_LARGE_SIZE = 32768
|
||||
|
||||
@@ -134,7 +133,6 @@ class OnionPacket:
|
||||
|
||||
def __post_init__(self):
|
||||
assert len(self.public_key) == 33
|
||||
assert len(self.hops_data) in [HOPS_DATA_SIZE, TRAMPOLINE_HOPS_DATA_SIZE, ONION_MESSAGE_LARGE_SIZE]
|
||||
assert len(self.hmac) == PER_HOP_HMAC_SIZE
|
||||
if not ecc.ECPubkey.is_pubkey_bytes(self.public_key):
|
||||
raise InvalidOnionPubkey()
|
||||
@@ -144,14 +142,10 @@ class OnionPacket:
|
||||
ret += self.public_key
|
||||
ret += self.hops_data
|
||||
ret += self.hmac
|
||||
if len(ret) - 66 not in [HOPS_DATA_SIZE, TRAMPOLINE_HOPS_DATA_SIZE, ONION_MESSAGE_LARGE_SIZE]:
|
||||
raise Exception('unexpected length {}'.format(len(ret)))
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, b: bytes) -> 'OnionPacket':
|
||||
if len(b) - 66 not in [HOPS_DATA_SIZE, TRAMPOLINE_HOPS_DATA_SIZE, ONION_MESSAGE_LARGE_SIZE]:
|
||||
raise Exception('unexpected length {}'.format(len(b)))
|
||||
return OnionPacket(
|
||||
public_key=b[1:34],
|
||||
hops_data=b[34:-32],
|
||||
@@ -217,7 +211,7 @@ def new_onion_packet(
|
||||
# FIXME: serializing here and again below. cache bytes in OnionHopsDataSingle? _raw_bytes_payload?
|
||||
payload_size += PER_HOP_HMAC_SIZE + len(hops_data[i].to_bytes())
|
||||
if trampoline:
|
||||
data_size = TRAMPOLINE_HOPS_DATA_SIZE
|
||||
data_size = payload_size
|
||||
elif onion_message:
|
||||
if payload_size <= HOPS_DATA_SIZE:
|
||||
data_size = HOPS_DATA_SIZE
|
||||
@@ -446,7 +440,7 @@ def process_onion_packet(
|
||||
raise InvalidOnionMac()
|
||||
# peel an onion layer off
|
||||
rho_key = get_bolt04_onion_key(b'rho', shared_secret)
|
||||
data_size = TRAMPOLINE_HOPS_DATA_SIZE if is_trampoline else HOPS_DATA_SIZE
|
||||
data_size = len(onion_packet.hops_data) if is_trampoline else HOPS_DATA_SIZE
|
||||
if is_onion_message and len(onion_packet.hops_data) > HOPS_DATA_SIZE:
|
||||
data_size = ONION_MESSAGE_LARGE_SIZE
|
||||
stream_bytes = generate_cipher_stream(rho_key, 2 * data_size)
|
||||
@@ -459,15 +453,8 @@ def process_onion_packet(
|
||||
if trampoline_onion_packet:
|
||||
if is_trampoline:
|
||||
raise Exception("found nested trampoline inside trampoline")
|
||||
top_version = trampoline_onion_packet.get('version')
|
||||
top_public_key = trampoline_onion_packet.get('public_key')
|
||||
top_hops_data = trampoline_onion_packet.get('hops_data')
|
||||
top_hops_data_fd = io.BytesIO(top_hops_data)
|
||||
top_hmac = trampoline_onion_packet.get('hmac')
|
||||
trampoline_onion_packet = OnionPacket(
|
||||
public_key=top_public_key,
|
||||
hops_data=top_hops_data_fd.read(TRAMPOLINE_HOPS_DATA_SIZE),
|
||||
hmac=top_hmac)
|
||||
trampoline_onion_packet = trampoline_onion_packet['trampoline_onion_packet']
|
||||
trampoline_onion_packet = OnionPacket.from_bytes(trampoline_onion_packet)
|
||||
# calc next ephemeral key
|
||||
blinding_factor = sha256(onion_packet.public_key + shared_secret)
|
||||
blinding_factor_int = int.from_bytes(blinding_factor, byteorder="big")
|
||||
|
||||
@@ -22,10 +22,7 @@ tlvdata,payload,outgoing_node_id,outgoing_node_id,byte,33
|
||||
tlvtype,payload,invoice_routing_info,66099
|
||||
tlvdata,payload,invoice_routing_info,invoice_routing_info,byte,...
|
||||
tlvtype,payload,trampoline_onion_packet,66100
|
||||
tlvdata,payload,trampoline_onion_packet,version,byte,1
|
||||
tlvdata,payload,trampoline_onion_packet,public_key,byte,33
|
||||
tlvdata,payload,trampoline_onion_packet,hops_data,byte,400
|
||||
tlvdata,payload,trampoline_onion_packet,hmac,byte,32
|
||||
tlvdata,payload,trampoline_onion_packet,trampoline_onion_packet,byte,...
|
||||
tlvtype,encrypted_data_tlv,padding,1
|
||||
tlvdata,encrypted_data_tlv,padding,padding,byte,...
|
||||
tlvtype,encrypted_data_tlv,short_channel_id,2
|
||||
|
||||
|
@@ -4093,10 +4093,7 @@ class LNWallet(Logger):
|
||||
self.logger.info(f'adding trampoline onion to final payload')
|
||||
trampoline_payload = dict(hops_data[-1].payload)
|
||||
trampoline_payload["trampoline_onion_packet"] = {
|
||||
"version": trampoline_onion.version,
|
||||
"public_key": trampoline_onion.public_key,
|
||||
"hops_data": trampoline_onion.hops_data,
|
||||
"hmac": trampoline_onion.hmac
|
||||
"trampoline_onion_packet": trampoline_onion.to_bytes()
|
||||
}
|
||||
hops_data[-1] = dataclasses.replace(hops_data[-1], payload=trampoline_payload)
|
||||
if t_hops_data := trampoline_onion._debug_hops_data: # None if trampoline-forwarding
|
||||
|
||||
@@ -7,7 +7,7 @@ from types import MappingProxyType
|
||||
|
||||
from .lnutil import LnFeatures, PaymentFeeBudget, FeeBudgetExceeded
|
||||
from .lnonion import (
|
||||
calc_hops_data_for_payment, new_onion_packet, OnionPacket, TRAMPOLINE_HOPS_DATA_SIZE, PER_HOP_HMAC_SIZE
|
||||
calc_hops_data_for_payment, new_onion_packet, OnionPacket, PER_HOP_HMAC_SIZE
|
||||
)
|
||||
from .lnrouter import TrampolineEdge, is_route_within_budget, LNPaymentTRoute
|
||||
from .lnutil import NoPathFound
|
||||
@@ -40,6 +40,8 @@ TRAMPOLINE_NODES_SIGNET = {
|
||||
|
||||
_TRAMPOLINE_NODES_UNITTESTS = {} # used in unit tests
|
||||
|
||||
TRAMPOLINE_HOPS_MAX_DATA_SIZE = 500
|
||||
|
||||
|
||||
def hardcoded_trampoline_nodes() -> Mapping[str, LNPeerAddr]:
|
||||
if _TRAMPOLINE_NODES_UNITTESTS:
|
||||
@@ -332,7 +334,7 @@ def create_trampoline_onion(
|
||||
payload = dict(hops_data[index].payload)
|
||||
# try different r_tag order on each attempt
|
||||
invoice_routing_info = random_shuffled_copy(route[index].invoice_routing_info)
|
||||
remaining_payload_space = TRAMPOLINE_HOPS_DATA_SIZE \
|
||||
remaining_payload_space = TRAMPOLINE_HOPS_MAX_DATA_SIZE \
|
||||
- sum(len(hop.to_bytes()) + PER_HOP_HMAC_SIZE for hop in hops_data)
|
||||
routing_info_to_use = []
|
||||
for encoded_r_tag in invoice_routing_info:
|
||||
|
||||
@@ -2742,10 +2742,7 @@ class TestPeerForwarding(TestPeer):
|
||||
assert len(hops_data) == 1
|
||||
new_payload = dict(hops_data[0].payload)
|
||||
new_payload['trampoline_onion_packet'] = {
|
||||
"version": modified_trampoline_onion.version,
|
||||
"public_key": modified_trampoline_onion.public_key,
|
||||
"hops_data": modified_trampoline_onion.hops_data,
|
||||
"hmac": modified_trampoline_onion.hmac,
|
||||
"trampoline_onion_packet": modified_trampoline_onion.to_bytes()
|
||||
}
|
||||
hops_data[0] = dataclasses.replace(hops_data[0], payload=MappingProxyType(new_payload))
|
||||
modified_trampoline_onion = None
|
||||
|
||||
Reference in New Issue
Block a user