def test_addressing_key(): """Tests making a blockchain address for a public key and that it: 1. is a 35-byte non-zero hexadecimal string 2. is unique - a different public key yields a different address 3. is deterministic - same public key yields same address 4. the addresser recognizes the address as a public key 5. the addresser can parse the address into its components 6. the identifier is a hash of the public key""" key = helper.user.key().public_key address = addresser.key.address(key) assert assert_is_address(address) assert address != addresser.key.address(helper.user.key().public_key) assert address == addresser.key.address(key) assert address == addresser.key.address(key.upper()) assert addresser.get_address_type(address) == addresser.AddressSpace.KEY assert addresser.get_address_type(address) == addresser.AddressSpace.KEY parsed = addresser.parse(address) assert parsed.object_type == addresser.ObjectType.KEY assert parsed.related_type == addresser.ObjectType.NONE assert parsed.relationship_type == addresser.RelationshipType.NONE assert assert_is_identifier(parsed.object_id) assert not parsed.related_id assert parsed.object_id == addresser.key.hash(key)
def test_addressing_user_key(): """Tests making a blockchain address that is a user-key assignment: 1. is a 35-byte non-zero hexadecimal string 2. is unique - a different public user-key yields a different address 3. is deterministic - same public user-key yields same address 4. the addresser recognizes the address as a user-key 5. the addresser can parse the address into its components 6. the identifier is a hash of the user id 7. the related identifier is a hash of the public key """ key = helper.user.key().public_key user_id = helper.user.id() address = addresser.user.key.address(user_id, key) assert assert_is_address(address) assert address != addresser.user.key.address(user_id, helper.user.key().public_key) assert address != addresser.user.key.address(helper.user.id(), key) assert address == addresser.user.key.address(user_id, key) assert addresser.get_address_type( address) == addresser.AddressSpace.USER_KEY assert addresser.get_address_type( address) == addresser.AddressSpace.USER_KEY parsed = addresser.parse(address) assert parsed.object_type == addresser.ObjectType.USER assert parsed.related_type == addresser.ObjectType.KEY assert parsed.relationship_type == addresser.RelationshipType.OWNER assert assert_is_identifier(parsed.object_id) assert parsed.object_id == addresser.user.hash(user_id) assert parsed.related_id == addresser.key.hash(key)
def _remove_state(conn, address): """ Update the state, state_history and metadata tables """ try: # update state table address_parts = addresser.parse(address) address_binary = bytes_from_hex(address) bytes_from_hex(address_parts.object_id) related_id = bytes_from_hex(address_parts.related_id) query = r.table("state").get(address_binary).delete( return_changes=True) result = query.run(conn) if result["errors"] > 0: LOGGER.warning("error deleting from state table:\n%s\n%s", result, query) if result["deleted"] and "changes" in result and result["changes"]: result = (r.table("state_history").insert( result["changes"][0]["old_val"]).run(conn)) if result["errors"] > 0: LOGGER.warning( "error inserting into state_history table:\n%s\n%s", result, query) if not related_id: query = r.table("metadata").get(address_binary).delete() result = query.run(conn) if result["errors"] > 0: LOGGER.warning("error removing metadata record:\n%s\n%s", result, query) except Exception as err: # pylint: disable=broad-except LOGGER.warning("remove_state %s error:", type(err)) LOGGER.warning(err)
def test_addressing_user(): """Tests making a blockchain address for an next_id and that it: 1. is a 35-byte non-zero hexadecimal string 2. is unique - a different next_id yields a different address 3. is deterministic - same next_id yields same address, even if different case 4. the addresser recognizes the address as an next_id 5. the addresser can parse the address into its components 6. the identifier is a hash of the next_id""" next_id = helper.user.id() address = addresser.user.address(next_id) assert assert_is_address(address) assert address != addresser.user.address(helper.user.id()) assert address == addresser.user.address(next_id) assert address == addresser.user.address(next_id.upper()) assert addresser.get_address_type(address) == addresser.AddressSpace.USER parsed = addresser.parse(address) assert parsed.object_type == addresser.ObjectType.USER assert parsed.related_type == addresser.ObjectType.NONE assert parsed.relationship_type == addresser.RelationshipType.ATTRIBUTES assert assert_is_identifier(parsed.object_id) assert not parsed.related_id assert parsed.object_id == addresser.user.hash(next_id)
def test_addressing_email(): """Tests making a blockchain address for an email and that it: 1. is a 35-byte non-zero hexadecimal string 2. is unique - a different email yields a different address 3. is deterministic - same email yields same address, even if different case 4. the addresser recognizes the address as an email 5. the addresser can parse the address into its components 6. the identifier is a hash of the email""" email = helper.user.email() address = addresser.email.address(email) assert assert_is_address(address) assert address != addresser.email.address(helper.user.email()) assert address == addresser.email.address(email) assert address == addresser.email.address(email.upper()) assert addresser.get_address_type(address) == addresser.AddressSpace.EMAIL parsed = addresser.parse(address) assert parsed.object_type == addresser.ObjectType.EMAIL assert parsed.related_type == addresser.ObjectType.NONE assert parsed.relationship_type == addresser.RelationshipType.NONE assert assert_is_identifier(parsed.object_id) assert not parsed.related_id assert parsed.object_id == addresser.email.hash(email)
def _update_state(database, block_num, address, resource): try: # update state table address_parts = addresser.parse(address) address_binary = bytes_from_hex(address) key = address_binary keys = {"address": address_binary} object_id = bytes_from_hex(address_parts.object_id) object_type = address_parts.object_type.value related_id = bytes_from_hex(address_parts.related_id) related_type = address_parts.related_type.value relationship_type = address_parts.relationship_type.value data = { "block_updated": int(block_num), "updated_at": r.now(), "object_type": object_type, "object_id": object_id, "related_type": related_type, "relationship_type": relationship_type, "related_id": related_id, **resource, } table_query = database.get_table("state") query = table_query.get(key).replace( lambda doc: r.branch( # pylint: disable=singleton-comparison (doc == None), # noqa r.expr(data).merge( { "address": key, "block_created": int(block_num), "created_at": r.now(), } ), doc.merge(data), ) ) result = database.run_query(query) if not result["inserted"] == 1 and not result["replaced"]: LOGGER.warning("error updating state table:\n%s\n%s", result, query) key = [address_binary, int(block_num)] data["address"] = key if result["inserted"] == 1: data["block_created"] = int(block_num) data["created_at"] = r.now() elif result["replaced"] == 1: LOGGER.warning(result) table_query = database.get_table("state_history") query = table_query.get(key).replace(data) result = database.run_query(query) if not result["inserted"] == 1 and not result["replaced"]: LOGGER.warning("error updating state_history table:\n%s\n%s", result, query) except Exception as err: # pylint: disable=broad-except LOGGER.warning("update_state %s error:", type(err)) LOGGER.warning(err)
def set_state(self, context, message, outputs, object_id, related_id=None): """Creates a new address in the blockchain state""" store = self.message_to_storage(message=message) # pylint: disable=no-member,not-callable container = self._state_container() getattr(container, self._state_container_list_name).extend([store]) address = self.address(object_id=object_id, related_id=related_id) if address not in outputs: raise ValueError( "Address {} not in listed outputs".format(addresser.parse(address)) ) state_client.set_address(context=context, address=address, container=container)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" user_id = addresser.user.unique_id() user_address = addresser.user.address(user_id) parsed = addresser.parse(user_address) self.assertEqual(parsed.object_type, addresser.ObjectType.USER) self.assertEqual(parsed.related_type, addresser.ObjectType.NONE) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.ATTRIBUTES) self.assertEqual(parsed.address_type, addresser.AddressSpace.USER) self.assertEqual(parsed.object_id, user_id) self.assertEqual(parsed.related_id, None)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" role_id = addresser.sysadmin.address() user_id = addresser.user.unique_id() rel_address = addresser.sysadmin.admin.address(user_id) parsed = addresser.parse(rel_address) self.assertEqual(parsed.object_type, addresser.ObjectType.SYSADMIN) self.assertEqual(parsed.related_type, addresser.ObjectType.USER) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.ADMIN) self.assertEqual(parsed.address_type, addresser.AddressSpace.SYSADMIN_ADMINS) self.assertEqual(parsed.object_id, user_id) self.assertEqual(parsed.related_id, None)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" task_id = addresser.task.unique_id() user_id = addresser.user.unique_id() rel_address = addresser.task.owner.address(task_id, user_id) parsed = addresser.parse(rel_address) self.assertEqual(parsed.object_type, addresser.ObjectType.TASK) self.assertEqual(parsed.related_type, addresser.ObjectType.USER) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.OWNER) self.assertEqual(parsed.address_type, addresser.AddressSpace.TASKS_OWNERS) self.assertEqual(parsed.object_id, task_id) self.assertEqual(parsed.related_id, user_id)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" proposal_id = addresser.proposal.unique_id() proposal_address = addresser.proposal.address(proposal_id) parsed = addresser.parse(proposal_address) self.assertEqual(parsed.object_type, addresser.ObjectType.PROPOSAL) self.assertEqual(parsed.related_type, addresser.ObjectType.NONE) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.ATTRIBUTES) self.assertEqual(parsed.address_type, addresser.AddressSpace.PROPOSALS) self.assertEqual(parsed.object_id, proposal_id) self.assertEqual(parsed.related_id, None)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" role_id = addresser.role.unique_id() role_address = addresser.role.address(role_id) parsed = addresser.parse(role_address) self.assertEqual(parsed.object_type, addresser.ObjectType.ROLE) self.assertEqual(parsed.related_type, addresser.ObjectType.NONE) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.ATTRIBUTES) self.assertEqual(parsed.address_type, addresser.AddressSpace.ROLES_ATTRIBUTES) self.assertEqual(parsed.object_id, role_id) self.assertEqual(parsed.related_id, None)
def save_state(self, context, outputs, output_state): """Save the output state to the blockchain""" changed = [ address for address in output_state.keys() if address in output_state["changed"] ] entries = {} for address in changed: if address not in outputs: raise ValueError( "Address {} not in listed outputs".format(addresser.parse(address)) ) entries[address] = output_state[address].SerializeToString() state_client.set_state(context=context, entries=entries)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" task_id = addresser.task.unique_id() task_address = addresser.task.address(task_id) parsed = addresser.parse(task_address) self.assertEqual(parsed.object_type, addresser.ObjectType.TASK) self.assertEqual(parsed.related_type, addresser.ObjectType.NONE) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.ATTRIBUTES) self.assertEqual(parsed.address_type, addresser.AddressSpace.TASKS_ATTRIBUTES) self.assertEqual(parsed.object_id, task_id) self.assertEqual(parsed.related_id, None)
def _get_store(self, object_id, related_id, outputs, output_state): """Gets the store object to store data for this message""" address = self.address(object_id=object_id, related_id=related_id) container = None if address not in outputs and address in output_state: raise ValueError("Address {} not in listed outputs".format( addresser.parse(address))) if address in output_state: container = output_state[address] # TODO: is getting the first item in the container... may not be correct! store = getattr(container, self._state_container_list_name)[0] if not container: container, store = self._get_new_state() output_state[address] = container return store
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" sysadmin_address = addresser.sysadmin.address() parsed = addresser.parse(sysadmin_address) self.assertEqual(parsed.object_type, addresser.ObjectType.SYSADMIN) self.assertEqual(parsed.related_type, addresser.ObjectType.NONE) self.assertEqual( parsed.relationship_type, addresser.RelationshipType.ATTRIBUTES ) self.assertEqual( parsed.address_type, addresser.AddressSpace.SYSADMIN_ATTRIBUTES ) self.assertEqual(parsed.object_id, "000000000000000000000000") self.assertEqual(parsed.related_id, None)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" role_id = addresser.role.unique_id() next_id = addresser.user.unique_id() rel_address = addresser.role.member.address(role_id, next_id) parsed = addresser.parse(rel_address) self.assertEqual(parsed.object_type, addresser.ObjectType.ROLE) self.assertEqual(parsed.related_type, addresser.ObjectType.USER) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.MEMBER) self.assertEqual(parsed.address_type, addresser.AddressSpace.ROLES_MEMBERS) self.assertEqual(parsed.object_id, role_id) self.assertEqual(parsed.related_id, next_id)
def test_addresser_parse(self): """Test addresser.parse returns a parsed address""" role_id = addresser.role.unique_id() task_id = addresser.task.unique_id() rel_address = addresser.role.task.address(role_id, task_id) parsed = addresser.parse(rel_address) self.assertEqual(parsed.object_type, addresser.ObjectType.ROLE) self.assertEqual(parsed.related_type, addresser.ObjectType.TASK) self.assertEqual(parsed.relationship_type, addresser.RelationshipType.MEMBER) self.assertEqual(parsed.address_type, addresser.AddressSpace.ROLES_TASKS) self.assertEqual(parsed.object_id, role_id) self.assertEqual(parsed.related_id, task_id)
def _remove_state(database, block_num, address): """ Update the state, state_history and metadata tables """ try: # update state table now = r.now() address_parts = addresser.parse(address) address_binary = bytes_from_hex(address) object_id = bytes_from_hex(address_parts.object_id) object_type = address_parts.object_type.value related_id = bytes_from_hex(address_parts.related_id) related_type = address_parts.related_type.value relationship_type = address_parts.relationship_type.value state = database.get_table("state") state_history = database.get_table("state_history") query = state.get(address_binary).delete(return_changes=True) result = database.run_query(query) if result["errors"] > 0: LOGGER.warning("error deleting from state table:\n%s\n%s", result, query) if result["deleted"] and "changes" in result and result["changes"]: query = state_history.insert(result["changes"][0]["old_val"]) result = database.run_query(query) if result["errors"] > 0: LOGGER.warning( "error inserting into state_history table:\n%s\n%s", result, query ) if not related_id: query = database.get_table("metadata").get(address_binary).delete() result = database.run_query(query) if result["errors"] > 0: LOGGER.warning("error removing metadata record:\n%s\n%s", result, query) except Exception as err: # pylint: disable=broad-except LOGGER.warning("remove_state %s error:", type(err)) LOGGER.warning(err)
def _update_state(conn, block_num, address, resource): """ Update the state, state_history and metadata tables """ try: # update state table now = r.now() address_parts = addresser.parse(address) address_binary = bytes_from_hex(address) object_id = bytes_from_hex(address_parts.object_id) object_type = address_parts.object_type.value related_id = bytes_from_hex(address_parts.related_id) related_type = address_parts.related_type.value relationship_type = address_parts.relationship_type.value data = { "address": address_binary, "object_type": object_type, "object_id": object_id, "related_type": related_type, "relationship_type": relationship_type, "related_id": related_id, "block_created": int(block_num), "block_num": int(block_num), "updated_date": now, **resource, } delta = {"block_num": int(block_num), "updated_at": now, **resource} query = ( r.table("state").get(address_binary).replace( lambda doc: r.branch( # pylint: disable=singleton-comparison (doc == None), # noqa r.expr(data), doc.merge(delta), ), return_changes=True, )) result = query.run(conn) if result["errors"] > 0: LOGGER.warning("error updating state table:\n%s\n%s", result, query) if result["replaced"] and "changes" in result and result["changes"]: query = r.table("state_history").insert( result["changes"][0]["old_val"]) result = query.run(conn) # data["address"] = [address_binary, int(block_num)] if result["errors"] > 0: LOGGER.warning("error updating state_history table:\n%s\n%s", result, query) if not related_id: data["address"] = address_binary del data["related_type"] del data["relationship_type"] del data["related_id"] query = ( r.table("metadata").get(address_binary).replace( lambda doc: r.branch( # pylint: disable=singleton-comparison (doc == None), # noqa r.expr(data), doc.merge(delta), ))) result = query.run(conn) if result["errors"] > 0: LOGGER.warning("error updating metadata record:\n%s\n%s", result, query) except Exception as err: # pylint: disable=broad-except LOGGER.warning("update_state %s error:", type(err)) LOGGER.warning(err)