DHT messages these messages can be either wrapped in a LIDM message or sent anonymously over a path find introduction message (FIM) recursively find an IS. variant 1, by SA { A: "F", R: r_counter, S: "<32 bytes SA>", T: transaction_id_uint64, V: 0 } variant 2, by claimed name { A: "F", N: "service.name.tld", R: r_counter, T: transaction_id_uin64, V: 0 } Transactions will persist until replied to by a GIM or 60 seconds, whichever is reached first. If the timeout is reached before a GIM or the forwarding of the request fails: * close transaction * close linked transactions if R is non-zero and less or equal to than 5: * decrement R by 1 * open a transaction with id T for sender's RC.k * pick random dht capable router, F * generate new transaction id, U * open a transaction with id U for F.k * link transaction U to transaction T * send FIM with transaction id U to F if R is greater than 5 or less than 0: * increment shitlist value of sender's RC.k by 1 * if the shitlist value for sender's RC.k is less than 10 reply with a GIM with an X * if the shitlist value for sender's RC.k is equal to or greater than 10 drop the message if R is zero and we have 1 or more IS at position S in dht keyspace: * reply with a GIM holding the IS who contains the introducer with the highest expiration timestamp if R is zero and we do not have any IS at position S in dht keyspace: * find a router who's RC.k is closest to S, N if N is our router: * reply with a GIM with an empty X value if N is not our router: * open transaction with id T for sender's RC.k * generate new transaction id, U * open transaction with id U for N.k * link transaction U to transaction T * forward request to N using transaction id U got introduction message (GIM) { A: "G", T: transaction_id_uint64, V: 0, X: [ IS, IS, IS, ... ] } if we have a transaction with id T: * forward the GIM to all linked transactions * terminate transaction T when a linked transaction gets a GIM: * set T to the current transaction id * foward the GIM to the requester of T publish introduction message (PIM) publish one or many IM into the dht at once. each IS will be placed in the dht version 0 uses the SA of each IS as the keyspace location. in the future the location will be determined by the dht kdf which uses a shared random source to obfuscate keyspace location. R is currently set to 3 +/- 2 by the sender. { A: "P", R: r_counter, V: 0, X: [ IS, IS, IS, ... ] } The following steps happen in order: first stage: reduction if X's length is divisble by 2: * split X in half as J and K * generate 2 new PIM with the same values as the parent with empty X * put J and K into the new PIM's X values * associate the 2 new PIM with the current PIM batch if X's length is not divisible by 2 and greater than 1: * pop off an IS from X as A * generate a new PIM with the same values as the parent with an X value of A * associate the new PIM with the current PIM batch * associate the old PIM having A removed from X with the current PIM batch if X's length is 1: * associate the PIM with the current PIM batch any other cases for X are ignored. for each PIM in the current batch: if R is greater than 0: * decrement R by 1 * queue the PIM for shuffle (second stage) if R is 0: * queue the PIM for distribution (third stage) if R is less than 0: * drop the message entirely second stage: shuffle * The dht node waits until we have collected 10 or more PIM or for 5 seconds, which ever comes first. * shuffle the list of IS randomly * re-combine the IS into new PIMs * queue each newly shuffled PIM for distribution (third stage) if we collected 10 or more PIM: * X holds 5 IS at most if we collected less than 10 but more than 1 PIM: * X holds 2 IS at most if we only collected 1 PIM: * the single PIM is unmodified third stage: distribution if R is less than 0: * drop message and terminate current transaction, this should never happen but this case is left here in the event of implementation bugs. if R is greater than 0: * pick a random dht capable router, N * forward the PIM to N if R is equal to 0: for each IS in X as A: * find the router closest to the SA in A, N if N is our router: * create dht positon S from SA in A * store A for lookup at S if N is not our router: * send a PIM with X value containing just A to N In the future post random walk keyspace batching may be done here. As of version 0, none is done. find router contact message (FRCM) find a router by long term RC.k public key { A: "R", K: "<32 byte public key of router>", T: transaction_id_uint64, V: 0 } find RC who's RC.k is closest to K: if A.k is equal to K: * reply with a GRCM with an R value of just A if A.k is not equal to K and we are closesr to A.k than anyone we know: * reply with a GRCM with an empty R value find a pending transaction id for K, P if P exists: * link transaction T to P if P does not exist: * generate a new transaction id, U * start transaction U for A.k * link transaction U to transaction T * send FRCM to A.k requesting K got router contact message (GRCM) R is a list containing a single RC if found or is an empty list if not found sent in reply to FRCM only { A: "S", R: [RC], T: transaction_id_uint64, V: 0 } * send a GRCM with R to requesters in all linked transactions * terminate transaction with id T notes: if we get a GRCM with empty R on one Tx and then one with a filled R on another with the same K, the request is terminated by the first message as not found. A backtrack case is needed.