def add_user(community_signing_key, community_id, user_signing_key, user_verify_key, user_id): """Add a test user to the network.""" new_user_info = storage.Entity() new_user_info.id = user_id new_user_info.verify_key = user_verify_key.encode( encoder=nacl.encoding.RawEncoder) new_user_info.user.display_name = "New User One".encode('utf8') new_user_info.user.home_community_id = community_id new_user_blob = new_user_info.SerializeToString() signature = community_signing_key.sign(new_user_blob).signature add_user_message = handshake.AddUser() add_user_message.new_user = new_user_blob add_user_message.home_signature = signature binary_add_user = add_user_message.SerializeToString() res = requests.post(url="http://localhost:5000/register/user", data=binary_add_user, headers={'Content-Type': 'application/octet-stream'}) if not res.ok: print(res) for line in res.iter_lines(): print(line)
def add_community(entity_id, verify_key): """Add a test community to the network""" new_community_info = storage.Entity() new_community_info.id = entity_id new_community_info.verify_key = verify_key.encode( encoder=nacl.encoding.RawEncoder) new_community_info.server.display_name = "New Community One".encode('utf8') binary_new_community_info = new_community_info.SerializeToString() add_community_message = handshake.AddCommunity() add_community_message.anchor_id = 0 # TODO(matt9j) Figure out how the add signature will work for the first community. add_community_message.anchor_signature = b'' add_community_message.new_community = binary_new_community_info binary_add_community = add_community_message.SerializeToString() res = requests.post(url="http://localhost:5000/register/community", data=binary_add_community, headers={'Content-Type': 'application/octet-stream'}) if not res.ok: print(res) for line in res.iter_lines(): print(line)
def _parse_user_id_from_add_user(add_user_blob): add_user_payload = handshake_pb2.AddUser() add_user_payload.ParseFromString(add_user_blob) new_user_info = storage_pb2.Entity() new_user_info.ParseFromString(add_user_payload.new_user) return new_user_info.id
def _parse_id_from_add_community(action_payload): # Parse outer message add_community_payload = handshake_pb2.AddCommunity() add_community_payload.ParseFromString(action_payload) new_community_info = storage_pb2.Entity() new_community_info.ParseFromString(add_community_payload.new_community) community_id = new_community_info.id return community_id
def _parse_add_user(add_user_blob): """Deserialize the add user payload""" add_user_payload = handshake_pb2.AddUser() add_user_payload.ParseFromString(add_user_blob) blob_sig = add_user_payload.home_signature new_user_info = storage_pb2.Entity() new_user_info.ParseFromString(add_user_payload.new_user) home_id = new_user_info.user.home_community_id user_id = new_user_info.id return home_id, blob_sig, user_id, add_user_payload.new_user
def _parse_add_community(action_payload): # Parse outer message add_community_payload = handshake_pb2.AddCommunity() add_community_payload.ParseFromString(action_payload) anchor_id = add_community_payload.anchor_id message_sig = add_community_payload.anchor_signature new_community_info = storage_pb2.Entity() new_community_info.ParseFromString(add_community_payload.new_community) community_id = new_community_info.id return anchor_id, message_sig, community_id, add_community_payload.new_community
def _add_ledger_crdt(action_payload, context): """Add a crdt record to the on-chain crdt implementation.""" exchange = asterales_parsers.parse_exchange_record(action_payload) # TODO(matt9j) handle gaps in the receive SQN? # TODO(matt9j) Validate that the sequence number has indeed progressed receive_sqn = exchange.receiver_sequence_number_msb * (2 ** 64) + \ exchange.receiver_sequence_number_lsb LOG.debug("Processing id: %d, sqn: %d to the ledger crdt", exchange.receiver_id, receive_sqn) # Validate the exchange signatures receiver_blob = _get_state_data(make_entity_address(exchange.receiver_id), context) receiver_data = storage_pb2.Entity() receiver_data.ParseFromString(receiver_blob) receive_verify_key = nacl.signing.VerifyKey( receiver_data.verify_key, encoder=nacl.encoding.RawEncoder) try: receive_verify_key.verify(exchange.receiver_signed_blob, exchange.receiver_signature, encoder=nacl.encoding.RawEncoder) except nacl.exceptions.BadSignatureError as e: LOG.error(e) raise InvalidTransaction( 'Exchange receive signature invalid sqn:{}'.format(receive_sqn)) sender_blob = _get_state_data(make_entity_address(exchange.sender_id), context) sender_data = storage_pb2.Entity() sender_data.ParseFromString(sender_blob) sender_verify_key = nacl.signing.VerifyKey( sender_data.verify_key, encoder=nacl.encoding.RawEncoder) try: sender_verify_key.verify(exchange.sender_signed_blob, exchange.sender_signature, encoder=nacl.encoding.RawEncoder) except nacl.exceptions.BadSignatureError: raise InvalidTransaction( 'Exchange send signature invalid sqn:{}'.format(receive_sqn)) crdt_address = make_crdt_address(exchange.receiver_id) current_crdt_blob = _get_state_data(crdt_address, context) if current_crdt_blob is not None: crdt_history = cbor.loads(current_crdt_blob) else: crdt_history = [] if receive_sqn in crdt_history: LOG.info("Discarding duplicate upload sqn: %d", receive_sqn) return LOG.info("Record is new, adding id: %d, sqn: %d to the ledger crdt", exchange.receiver_id, receive_sqn) crdt_history.append(receive_sqn) _set_state_data(crdt_address, cbor.dumps(crdt_history), context) receiver_data.balance += exchange.amount _set_state_data(make_entity_address(exchange.receiver_id), receiver_data.SerializeToString(), context) sender_data.balance -= exchange.amount _set_state_data(make_entity_address(exchange.sender_id), sender_data.SerializeToString(), context)
def _flatten_delta_crdt(action_payload, context, crdt_endpoint): """Flattens contiguous local CRDT records into the entity state""" # Parse the request. flatten_request = cbor2.loads(action_payload) # TODO(matt9j) Use the origin as a fallback if deltas are missing. # request_origin = flatten_request['origin'] entity_id = flatten_request['entity_id'] proposed_frontier = flatten_request['sqn'] LOG.info("Attempting to flatten delta crdt for id: %d to frontier_sqn: %d", entity_id, proposed_frontier) # Lookup the current frontier sqn. entity_blob = _get_state_data(make_entity_address(entity_id), context) entity_pb = storage_pb2.Entity() entity_pb.ParseFromString(entity_blob) current_frontier = entity_pb.frontier_sequence_number LOG.debug('requesting endorsement for (%d, %d] for entity %d', current_frontier, proposed_frontier, entity_id) # ask the local CRDT for exchanges up to the new proposed frontier SQN crdt_request = { 'receive_id': entity_id, 'current_frontier': current_frontier, 'proposed_frontier': proposed_frontier, } response = CRDT_SESSION.post( url=crdt_endpoint + "/crdt/endorsingRecords", data=cbor2.dumps(crdt_request), headers={'Content-Type': 'application/octet-stream'}) if not response.ok: LOG.error("Unable to request endorsing crdt records %s", response) raise InvalidTransaction("Unable to request endorsement from CRDT") # Set aside the receiver information receiver_blob = _get_state_data(make_entity_address(entity_id), context) receiver_data = storage_pb2.Entity() receiver_data.ParseFromString(receiver_blob) receive_verify_key = nacl.signing.VerifyKey( receiver_data.verify_key, encoder=nacl.encoding.RawEncoder) # exchanges must be sorted already in ascending order by sequence number exchanges = cbor2.loads(response.content) frontier = current_frontier # TODO(matt9j) Possibly speedup by re-using exchange protobufs # validate all the exchanges for exchange_blob in exchanges: if frontier >= proposed_frontier: LOG.warning("Got too many exchange records or bad frontier req?!") break exchange = asterales_parsers.parse_exchange_record(exchange_blob) receive_sqn = exchange.receiver_sequence_number_msb * (2 ** 64) + \ exchange.receiver_sequence_number_lsb last_valid_receive_sqn = exchange.last_valid_sequence_number_msb * (2**64) + \ exchange.last_valid_sequence_number_lsb # Validate signatures try: receive_verify_key.verify(exchange.receiver_signed_blob, exchange.receiver_signature, encoder=nacl.encoding.RawEncoder) except nacl.exceptions.BadSignatureError as e: LOG.error(e) raise InvalidTransaction( 'Exchange receive signature invalid sqn:{}'.format( receive_sqn)) sender_blob = _get_state_data(make_entity_address(exchange.sender_id), context) sender_data = storage_pb2.Entity() sender_data.ParseFromString(sender_blob) sender_verify_key = nacl.signing.VerifyKey( sender_data.verify_key, encoder=nacl.encoding.RawEncoder) try: sender_verify_key.verify(exchange.sender_signed_blob, exchange.sender_signature, encoder=nacl.encoding.RawEncoder) except nacl.exceptions.BadSignatureError: raise InvalidTransaction( 'Exchange send signature invalid sqn:{}'.format(receive_sqn)) if last_valid_receive_sqn != frontier: LOG.warning("Gap discovered-- in this hacky initial implementation" " state may now be corrupted.") raise InvalidTransaction() receiver_data.balance += exchange.amount # TODO(matt9j) Don't serialize all the send messages until done! Some # may be repeated... sender_data.balance -= exchange.amount _set_state_data(make_entity_address(exchange.sender_id), sender_data.SerializeToString(), context) frontier = receive_sqn # Serialize the common receive buffer at the end of processing. # TODO(matt9j) Fix LSB/MSB precision laziness. frontier_sequence_number_lsb = frontier & 0xFFFFFFFFFFFFFFFF frontier_sequence_number_msb = frontier >> 64 receiver_data.frontier_sequence_number = frontier_sequence_number_lsb _set_state_data(make_entity_address(exchange.receiver_id), receiver_data.SerializeToString(), context)