Function createOnionPacket
Create an onion packet for the given path. Each hop will contain an ephemeral public key to derive a common secret with which the hop's payload will be encrypted and may later be decrypted by the hop node which owns their private key.
OnionPacket createOnionPacket
(
in const(Amount) amount,
in const(Hop[]) path,
out Amount total_amount,
out Height use_lock_height,
out agora .crypto .ECC .Point[] shared_secrets
) @safe;
The onion packet is fixed in size, and uses encrypted padding bytes to obfuscate its true size. When a node peels of their layer of the encrypted packet, it adds additional pading to fill the packet size back to its expected fixed length size.
Parameters
Name | Description |
---|---|
lock_height | the initial lock height |
amount | the amount for the payment |
path | the individual hops (including destination hop) |
total_amount | will contain the amount which needs to be paid to the
first channel along the route. Different to amount as it also
includes fees. |
shared_secrets | shared secret used in each hop. (in reverse) |
Returns
the onion packet ready to be routed through the first payment path.
Example
Pair kp1 = Pair .random();
Pair kp2 = Pair .random();
Pair kp3 = Pair .random();
Pair kp4 = Pair .random();
Hop[] hops = [
Hop(kp1 .V, hashFull(1), Amount(100), 1),
Hop(kp2 .V, hashFull(2), Amount(200), 1),
Hop(kp3 .V, hashFull(3), Amount(300), 1),
Hop(kp4 .V, hashFull(4), Amount(400), 1),
];
Amount total_amount;
Height use_lock_height;
Point[] shared_secrets;
auto packet = createOnionPacket(Amount(1000),
hops, total_amount, use_lock_height, shared_secrets);
assert(total_amount == Amount(2000));
assert(use_lock_height == 4);
Point shared_secret;
Payload payload;
assert(!decryptPayload(packet .encrypted_payloads[0],
kp2 .v, packet .ephemeral_pk, payload)); // cannot decrypt with other keys
assert(decryptPayload(packet .encrypted_payloads[0],
kp1 .v, packet .ephemeral_pk, payload, shared_secret));
assert(shared_secrets[3] == shared_secret);
assert(payload == Payload(hashFull(2), Amount(1900)));
assert(!decryptPayload(packet .encrypted_payloads[1],
kp2 .v, packet .ephemeral_pk, payload)); // cannot decrypt with same ephemeral key
packet = nextPacket(packet); // switch ephemeral key
assert(decryptPayload(packet .encrypted_payloads[0],
kp2 .v, packet .ephemeral_pk, payload, shared_secret));
assert(shared_secrets[2] == shared_secret);
assert(payload == Payload(hashFull(3), Amount(1700)));
packet = nextPacket(packet);
assert(decryptPayload(packet .encrypted_payloads[0],
kp3 .v, packet .ephemeral_pk, payload, shared_secret));
assert(shared_secrets[1] == shared_secret);
assert(payload == Payload(hashFull(4), Amount(1400)));
packet = nextPacket(packet);
assert(decryptPayload(packet .encrypted_payloads[0],
kp4 .v, packet .ephemeral_pk, payload, shared_secret));
assert(shared_secrets[0] == shared_secret);
assert(payload == Payload(Hash .init, Amount(1000)));