Stamp validation on incoming propagation node transfers
This commit is contained in:
parent
ebc8bb33c2
commit
9c646aead7
2 changed files with 48 additions and 52 deletions
|
|
@ -2000,10 +2000,13 @@ class LXMRouter:
|
||||||
#######################################
|
#######################################
|
||||||
# TODO: Check propagation stamps here #
|
# TODO: Check propagation stamps here #
|
||||||
#######################################
|
#######################################
|
||||||
stamps_valid = False
|
target_cost = max(0, self.propagation_stamp_cost-self.propagation_stamp_cost_flexibility)
|
||||||
|
validated_messages = LXStamper.validate_pn_stamps(messages, target_cost)
|
||||||
|
|
||||||
for lxmf_data in messages:
|
for validated_entry in validated_messages:
|
||||||
self.lxmf_propagation(lxmf_data)
|
lxmf_data = validated_entry[1]
|
||||||
|
stamp_value = validated_entry[2]
|
||||||
|
self.lxmf_propagation(lxmf_data, stamp_value=stamp_value)
|
||||||
self.client_propagation_messages_received += 1
|
self.client_propagation_messages_received += 1
|
||||||
|
|
||||||
if stamps_valid: packet.prove()
|
if stamps_valid: packet.prove()
|
||||||
|
|
@ -2093,10 +2096,14 @@ class LXMRouter:
|
||||||
#######################################
|
#######################################
|
||||||
# TODO: Check propagation stamps here #
|
# TODO: Check propagation stamps here #
|
||||||
#######################################
|
#######################################
|
||||||
|
target_cost = max(0, self.propagation_stamp_cost-self.propagation_stamp_cost_flexibility)
|
||||||
|
validated_messages = LXStamper.validate_pn_stamps(messages, target_cost)
|
||||||
|
|
||||||
for lxmf_data in messages:
|
for validated_entry in validated_messages:
|
||||||
peer = None
|
transient_id = validated_entry[0]
|
||||||
transient_id = RNS.Identity.full_hash(lxmf_data)
|
lxmf_data = validated_entry[1]
|
||||||
|
stamp_value = validated_entry[2]
|
||||||
|
peer = None
|
||||||
|
|
||||||
if remote_hash != None and remote_hash in self.peers:
|
if remote_hash != None and remote_hash in self.peers:
|
||||||
peer = self.peers[remote_hash]
|
peer = self.peers[remote_hash]
|
||||||
|
|
@ -2109,7 +2116,7 @@ class LXMRouter:
|
||||||
else:
|
else:
|
||||||
self.client_propagation_messages_received += 1
|
self.client_propagation_messages_received += 1
|
||||||
|
|
||||||
self.lxmf_propagation(lxmf_data, from_peer=peer)
|
self.lxmf_propagation(lxmf_data, from_peer=peer, stamp_value=stamp_value)
|
||||||
if peer != None: peer.queue_handled_message(transient_id)
|
if peer != None: peer.queue_handled_message(transient_id)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import RNS.vendor.umsgpack as msgpack
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import math
|
import math
|
||||||
|
import itertools
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
WORKBLOCK_EXPAND_ROUNDS = 3000
|
WORKBLOCK_EXPAND_ROUNDS = 3000
|
||||||
|
|
@ -43,46 +44,42 @@ def stamp_valid(stamp, target_cost, workblock):
|
||||||
if int.from_bytes(result, byteorder="big") > target: return False
|
if int.from_bytes(result, byteorder="big") > target: return False
|
||||||
else: return True
|
else: return True
|
||||||
|
|
||||||
def validate_pn_stamp(transient_id, stamp):
|
def validate_pn_stamp(transient_data, target_cost):
|
||||||
target_cost = 8
|
from .LXMessage import LXMessage
|
||||||
workblock = stamp_workblock(transient_id, expand_rounds=WORKBLOCK_EXPAND_ROUNDS_PN)
|
if len(transient_data) <= LXMessage.LXMF_OVERHEAD+STAMP_SIZE: return False, None, None
|
||||||
if stamp_valid(stamp, target_cost, workblock):
|
else:
|
||||||
RNS.log(f"Stamp on {RNS.prettyhexrep(transient_id)} validated", RNS.LOG_DEBUG)
|
lxm_data = transient_data[:-STAMP_SIZE]
|
||||||
value = stamp_value(workblock, stamp)
|
stamp = transient_data[-STAMP_SIZE:]
|
||||||
return True
|
transient_id = RNS.Identity.full_hash(lxm_data)
|
||||||
|
workblock = stamp_workblock(transient_id, expand_rounds=WORKBLOCK_EXPAND_ROUNDS_PN)
|
||||||
|
|
||||||
return False
|
if not stamp_valid(stamp, target_cost, workblock): return False, None, None
|
||||||
|
else:
|
||||||
|
value = stamp_value(workblock, stamp)
|
||||||
|
return True, transient_id, value
|
||||||
|
|
||||||
def validate_pn_stamps_job_simple(transient_stamps):
|
def validate_pn_stamps_job_simple(transient_list, target_cost):
|
||||||
for entry in transient_stamps:
|
validated_messages = []
|
||||||
# Get transient ID and stamp for validation
|
for transient_data in transient_list:
|
||||||
transient_id = transient_stamps[0]
|
stamp_valid, transient_id, value = validate_pn_stamp(transient_data, target_cost)
|
||||||
stamp = transient_stamps[1]
|
if stamp_valid: validated_messages.append([transient_id, transient_data, value])
|
||||||
|
|
||||||
# Store validation result back into list
|
return validated_messages
|
||||||
transient_stamps[2] = validate_pn_stamp(transient_id, stamp)
|
|
||||||
|
|
||||||
return transient_stamps
|
def validate_pn_stamps_job_multip(transient_list, target_cost):
|
||||||
|
|
||||||
def _validate_single_pn_stamp_entry(entry):
|
|
||||||
transient_id = entry[0]
|
|
||||||
stamp = entry[1]
|
|
||||||
entry[2] = validate_pn_stamp(transient_id, stamp)
|
|
||||||
return entry
|
|
||||||
|
|
||||||
def validate_pn_stamps_job_multip(transient_stamps):
|
|
||||||
cores = multiprocessing.cpu_count()
|
cores = multiprocessing.cpu_count()
|
||||||
pool_count = min(cores, math.ceil(len(transient_stamps) / PN_VALIDATION_POOL_MIN_SIZE))
|
pool_count = min(cores, math.ceil(len(transient_list) / PN_VALIDATION_POOL_MIN_SIZE))
|
||||||
|
|
||||||
RNS.log(f"Validating {len(transient_stamps)} stamps using {pool_count} processes...", RNS.LOG_VERBOSE)
|
RNS.log(f"Validating {len(transient_list)} stamps using {pool_count} processes...", RNS.LOG_VERBOSE)
|
||||||
with multiprocessing.Pool(pool_count) as p: validated_entries = p.map(_validate_single_pn_stamp_entry, transient_stamps)
|
with multiprocessing.Pool(pool_count) as p:
|
||||||
|
validated_entries = p.starmap(validate_pn_stamp, zip(transient_list, itertools.repeat(target_cost)))
|
||||||
|
|
||||||
return validated_entries
|
return [e for e in validated_entries if e[0] == True]
|
||||||
|
|
||||||
def validate_pn_stamps(transient_stamps):
|
def validate_pn_stamps(transient_list, target_cost):
|
||||||
non_mp_platform = RNS.vendor.platformutils.is_android()
|
non_mp_platform = RNS.vendor.platformutils.is_android()
|
||||||
if len(transient_stamps) <= PN_VALIDATION_POOL_MIN_SIZE or non_mp_platform: validate_pn_stamps_job_simple(transient_stamps)
|
if len(transient_list) <= PN_VALIDATION_POOL_MIN_SIZE or non_mp_platform: return validate_pn_stamps_job_simple(transient_list, target_cost)
|
||||||
else: validate_pn_stamps_job_multip(transient_stamps)
|
else: return validate_pn_stamps_job_multip(transient_list, target_cost)
|
||||||
|
|
||||||
def generate_stamp(message_id, stamp_cost):
|
def generate_stamp(message_id, stamp_cost):
|
||||||
RNS.log(f"Generating stamp with cost {stamp_cost} for {RNS.prettyhexrep(message_id)}...", RNS.LOG_DEBUG)
|
RNS.log(f"Generating stamp with cost {stamp_cost} for {RNS.prettyhexrep(message_id)}...", RNS.LOG_DEBUG)
|
||||||
|
|
@ -93,19 +90,13 @@ def generate_stamp(message_id, stamp_cost):
|
||||||
rounds = 0
|
rounds = 0
|
||||||
value = 0
|
value = 0
|
||||||
|
|
||||||
if RNS.vendor.platformutils.is_windows() or RNS.vendor.platformutils.is_darwin():
|
if RNS.vendor.platformutils.is_windows() or RNS.vendor.platformutils.is_darwin(): stamp, rounds = job_simple(stamp_cost, workblock, message_id)
|
||||||
stamp, rounds = job_simple(stamp_cost, workblock, message_id)
|
elif RNS.vendor.platformutils.is_android(): stamp, rounds = job_android(stamp_cost, workblock, message_id)
|
||||||
|
else: stamp, rounds = job_linux(stamp_cost, workblock, message_id)
|
||||||
elif RNS.vendor.platformutils.is_android():
|
|
||||||
stamp, rounds = job_android(stamp_cost, workblock, message_id)
|
|
||||||
|
|
||||||
else:
|
|
||||||
stamp, rounds = job_linux(stamp_cost, workblock, message_id)
|
|
||||||
|
|
||||||
duration = time.time() - start_time
|
duration = time.time() - start_time
|
||||||
speed = rounds/duration
|
speed = rounds/duration
|
||||||
if stamp != None:
|
if stamp != None: value = stamp_value(workblock, stamp)
|
||||||
value = stamp_value(workblock, stamp)
|
|
||||||
|
|
||||||
RNS.log(f"Stamp with value {value} generated in {RNS.prettytime(duration)}, {rounds} rounds, {int(speed)} rounds per second", RNS.LOG_DEBUG)
|
RNS.log(f"Stamp with value {value} generated in {RNS.prettytime(duration)}, {rounds} rounds, {int(speed)} rounds per second", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
|
|
@ -161,10 +152,8 @@ def job_simple(stamp_cost, workblock, message_id):
|
||||||
def sv(s, c, w):
|
def sv(s, c, w):
|
||||||
target = 0b1<<256-c; m = w+s
|
target = 0b1<<256-c; m = w+s
|
||||||
result = RNS.Identity.full_hash(m)
|
result = RNS.Identity.full_hash(m)
|
||||||
if int.from_bytes(result, byteorder="big") > target:
|
if int.from_bytes(result, byteorder="big") > target: return False
|
||||||
return False
|
else: return True
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
while not sv(pstamp, stamp_cost, workblock) and not active_jobs[message_id]:
|
while not sv(pstamp, stamp_cost, workblock) and not active_jobs[message_id]:
|
||||||
pstamp = os.urandom(256//8); rounds += 1
|
pstamp = os.urandom(256//8); rounds += 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue