NNCP has ability to multicast packets: send single packet to multiple recipients, which also can send it further to others. It can also be called echomail (like in FidoNet networks) or newsgroup (like in Usenet networks).
Each multicast group is identified by so-called area. Area consists of private/public Curve25519 keypairs for packets encryption, identity (BLAKE2b-256 hash of the public key) and possible subscribers. Areas are created with nncp-cfgnew command.
You can make either file or exec transmissions to the areas. Those ordinary file/exec packets are double wrapped in:
Area’s message identity (
MsgHash) is the hash of the encrypted
packet header. Because the area packet, containing the encrypted packet,
is relayed as-is without any modifications, that area message’s hash
will be the same on each node it reaches.
Tosser’s algorithm of processing the area packet is following:
AREA). Fail/skip if it is unknown
Expensive signature verification and shared key computation procedures are skipped in the following cycles – only symmetric cryptography will be in use, having negligible CPU resource consumption.
allow-unknownconfiguration option set for that area, then fail
Because outgoing packets creation for each subscriber can be time and
(disk) resource consuming, we can suddenly fail. It would be bad if we
will loose the possibility to retry the multicasting process again. So
we have got to save somehow outgoing area’s message in permanent
storage, while outgoing copies are created. That is why the initial (not
relaying) message to the area is sent to the self and processed
by the tosser to create necessary outgoing message
copies. Because message to myself is also encrypted, area’s message is
encrypted and secured and noone sees plaintext
that you either originated or have that message on the disk.
For example we have got 4 nodes participating in the single area and
let’s send file to that area from the
nodeA -> subs: ["nodeB", "nodeD"] nodeB -> subs: ["nodeC", "nodeD", "nodeA"], no keys nodeC -> subs: ["nodeB"] nodeD -> subs: ["nodeA", "nodeB"]
A -- B -- C \ / \ / D
$ nncp-file nodelist-20210704.rec.zst area:nodelist-updates: $ nncp-toss -node self
nncp-filecreates an encrypted packet with area packet and encrypted packet inside it, with our own
selfnode as a recipient (in the SPOOL/SELF/tx directory). It also creates the SPOOL/SELF/area/AREA/MsgHash file.
nncp-tosssees tx/ file and "opens" it, applying the area message tossing procedure as described above. That will create outgoing packets in SPOOL/nodeB/tx and SPOOL/nodeD/tx directories with SPOOL/nodeB/area/AREA/MsgHash SPOOL/nodeD/area/AREA/MsgHash files. Because we already have SPOOL/SELF/area/AREA/MsgHash, that packet is removed then.
nodeBreceives the encrypted packet, it sees the area one inside. It copies/relays it to the
nodeD. It can not read area’s message because it lacks the keys.
nodeCdoes not relay it to anyone. Just stores nodelist-20210704.rec.zst in the incoming directory.
nodeDreceives packets from both
nodeB. Only one of them processed, and other is ignored because corresponding MsgHash file will exist.
nodeD will receive packet from the
nodeB first, it will
relay it to the
nodeA also, that will silently remove it when
tossing, because it was already seen.
nodeCsends message to the area, then
nodeAwill receive it twice from
nodeD, ignoring one of them during tossing.