async def _find_by_lookup(self, pubkey, community): identity = self._identities(community)[pubkey] lookup_tries = 0 while lookup_tries < 3: try: data = await community.bma_access.simple_request(bma.wot.Lookup, req_args={'search': pubkey}) timestamp = BlockUID.empty() for result in data['results']: if result["pubkey"] == identity.pubkey: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: identity.sigdate = BlockUID.from_str(uid_data["meta"]["timestamp"]) identity.uid = uid_data["uid"] identity.blockchain_state = BlockchainState.BUFFERED identity.local_state = LocalState.PARTIAL timestamp = identity.sigdate return identity except errors.DuniterError as e: lookup_tries += 1 except asyncio.TimeoutError: lookup_tries += 1 except ClientError: lookup_tries += 1 except NoPeerAvailable: return identity return identity
def test_add_get_multiple_node(meta_repo): nodes_repo = NodesRepo(meta_repo.conn) nodes_repo.insert(Node("testcurrency", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", """BASIC_MERKLED_API test-net.duniter.fr 13.222.11.22 9201 BASIC_MERKLED_API testnet.duniter.org 80 UNKNOWNAPI some useless information""", BlockUID.empty(), "doe", "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 12376543345, "14-AEFFCB00E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 0, "duniter", "0.30.17")) nodes_repo.insert(Node("testcurrency", "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn", "BASIC_MERKLED_API test-net.duniter.org 22.22.22.22 9201", BlockUID.empty(), "doe", "18-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 12376543345, "12-AEFFCB00E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 0, "duniter", "0.30.2a5")) nodes = nodes_repo.get_all(currency="testcurrency") assert "testcurrency" in [t.currency for t in nodes] assert "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" in [n.pubkey for n in nodes] assert "FADxcH5LmXGmGFgdixSes6nWnC4Vb4pRUBYT81zQRhjn" in [n.pubkey for n in nodes]
async def refresh_uid(self): """ Refresh the node UID """ conn_handler = self.endpoint.conn_handler() try: data = await bma.wot.Lookup(conn_handler, self.pubkey).get(self._session) self.state = Node.ONLINE timestamp = BlockUID.empty() uid = "" for result in data['results']: if result["pubkey"] == self.pubkey: uids = result['uids'] for uid in uids: if BlockUID.from_str(uid["meta"]["timestamp"]) >= timestamp: timestamp = uid["meta"]["timestamp"] uid = uid["uid"] if self._uid != uid: self._uid = uid self.identity_changed.emit() except errors.DuniterError as e: if e.ucode == errors.NO_MATCHING_IDENTITY: logging.debug("UID not found : {0}".format(self.pubkey[:5])) else: logging.debug("error in uid reply : {0}".format(self.pubkey[:5])) self.state = Node.OFFLINE self.identity_changed.emit() except (ClientError, gaierror, TimeoutError, DisconnectedError, ValueError) as e: logging.debug("{0} : {1}".format(type(e).__name__, self.pubkey[:5])) self.state = Node.OFFLINE except jsonschema.ValidationError as e: logging.debug(str(e)) logging.debug("Validation error : {0}".format(self.pubkey[:5])) self.state = Node.CORRUPTED
def test_certification_raw(self): version = 2 currency = "beta_brousouf" pubkey_from = "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV" pubkey_to = "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd" timestamp = BlockUID(36, "1076F10A7397715D2BEE82579861999EA1F274AC") signature = "SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk" selfcert = Identity( version, currency, pubkey_to, "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci" ) certification = Certification(version, currency, pubkey_from, pubkey_to, timestamp, signature) result = """Version: 2 Type: Certification Currency: beta_brousouf Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV IdtyIssuer: HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd IdtyUniqueID: lolcat IdtyTimestamp: 32-DB30D958EE5CB75186972286ED3F4686B8A1C2CD IdtySignature: J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci CertTimestamp: 36-1076F10A7397715D2BEE82579861999EA1F274AC SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneNYSMV3rk """ self.assertEqual(certification.signed_raw(selfcert), result) from_raw = Certification.from_signed_raw( certification.signed_raw(selfcert)) self.assertEqual(from_raw.signed_raw(selfcert), result)
async def _find_by_lookup(self, pubkey, community): identity = self._identities(community)[pubkey] lookup_tries = 0 while lookup_tries < 3: try: data = await community.bma_access.simple_request( bma.wot.Lookup, req_args={'search': pubkey}) timestamp = BlockUID.empty() for result in data['results']: if result["pubkey"] == identity.pubkey: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"] ["timestamp"]) >= timestamp: identity.sigdate = BlockUID.from_str( uid_data["meta"]["timestamp"]) identity.uid = uid_data["uid"] identity.blockchain_state = BlockchainState.BUFFERED identity.local_state = LocalState.PARTIAL timestamp = identity.sigdate return identity except errors.DuniterError as e: lookup_tries += 1 except asyncio.TimeoutError: lookup_tries += 1 except ClientError: lookup_tries += 1 except NoPeerAvailable: return identity return identity
class Identity: currency = attr.ib(convert=str) pubkey = attr.ib(convert=str) uid = attr.ib(convert=str, default="") blockstamp = attr.ib(convert=block_uid, default=BlockUID.empty()) signature = attr.ib(convert=str, default="", cmp=False, hash=False) # Mediantime of the block referenced by blockstamp timestamp = attr.ib(convert=int, default=0, cmp=False, hash=False) written = attr.ib(convert=bool, default=False, cmp=False, hash=False) revoked_on = attr.ib(convert=int, default=0, cmp=False, hash=False) outdistanced = attr.ib(convert=bool, default=True, cmp=False, hash=False) member = attr.ib(validator=attr.validators.instance_of(bool), default=False, cmp=False, hash=False) membership_buid = attr.ib(convert=block_uid, default=BlockUID.empty(), cmp=False, hash=False) membership_timestamp = attr.ib(convert=int, default=0, cmp=False, hash=False) membership_type = attr.ib(convert=str, default='', validator=lambda s, a, t: t in ('', 'IN', 'OUT'), cmp=False, hash=False) membership_written_on = attr.ib(convert=int, default=0, cmp=False, hash=False) sentry = attr.ib(convert=bool, default=False, cmp=False, hash=False) def document(self): """ Creates a self cert document for a given identity :param sakia.data.entities.Identity identity: :return: the document :rtype: duniterpy.documents.Identity """ return IdentityDoc(10, self.currency, self.pubkey, self.uid, self.blockstamp, self.signature) def is_obsolete(self, sig_window, current_time): expired = self.timestamp + sig_window <= current_time return not self.written and expired
async def get_identity_document(connection, current_block, pubkey): """ Get the identity document of the pubkey :param bma.api.ConnectionHandler connection: Connection handler :param dict current_block: Current block data :param str pubkey: UID/Public key :rtype: Identity """ # Here we request for the path wot/lookup/pubkey lookup_data = await bma.wot.lookup(connection, pubkey) # init vars uid = None timestamp = BlockUID.empty() signature = None # parse results for result in lookup_data['results']: if result["pubkey"] == pubkey: uids = result['uids'] for uid_data in uids: # capture data timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) uid = uid_data["uid"] signature = uid_data["self"] # return self-certification document return Identity(version=10, currency=current_block['currency'], pubkey=pubkey, uid=uid, ts=timestamp, signature=signature)
def test_add_get_drop_identity(meta_repo): identities_repo = IdentitiesRepo(meta_repo.conn) identities_repo.insert(Identity("testcurrency", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", "john", "20-7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==", 1473108382)) identity = identities_repo.get_one(currency="testcurrency", pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", uid="john", blockstamp=BlockUID(20, "7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67") ) assert identity.currency == "testcurrency" assert identity.pubkey == "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" assert identity.uid == "john" assert identity.blockstamp.number == 20 assert identity.blockstamp.sha_hash == "7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67" assert identity.timestamp == 1473108382 assert identity.signature == "H41/8OGV2W4CLKbE35kk5t1HJQsb3jEM0/QGLUf80CwJvGZf3HvVCcNtHPUFoUBKEDQO9mPK3KJkqOoxHpqHCw==" assert identity.member == False assert identity.membership_buid == BlockUID.empty() assert identity.membership_timestamp == 0 assert identity.membership_written_on == 0 identities_repo.drop(identity) identity = identities_repo.get_one(currency="testcurrency", pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", uid="john", blockstamp=BlockUID(20, "7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67") ) assert identity is None
async def get_identity_document(connection, currency, pubkey): """ Get the SelfCertification document of the pubkey :param bma.api.ConnectionHandler connection: Connection handler :param str currency: Currency name :param str pubkey: Public key :rtype: SelfCertification """ # Here we request for the path wot/lookup/pubkey lookup_data = await bma.wot.Lookup(connection, pubkey).get(AIOHTTP_SESSION) # init vars uid = None timestamp = BlockUID.empty() signature = None # parse results for result in lookup_data['results']: if result["pubkey"] == pubkey: uids = result['uids'] for uid_data in uids: # capture data timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) uid = uid_data["uid"] signature = uid_data["self"] # return self-certification document return SelfCertification(version=PROTOCOL_VERSION, currency=currency, pubkey=pubkey, uid=uid, ts=timestamp, signature=signature)
def test_send_certification(self): cert_signal_sent = False def check_certification_accepted(): nonlocal cert_signal_sent cert_signal_sent = True account = Account("test_salt", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", "test_account", [], [], [], self.identities_registry) account.certification_accepted.connect(check_certification_accepted) account_identity = MagicMock(autospec='sakia.core.registry.Identity') account_identity.selfcert = CoroutineMock(return_value=SelfCertification( 2, "meta_brouzouf", "H8uYXvyF6GWeCr8cwFJ6V5B8tNprwRdjepFNJBqivrzr", "test_account", BlockUID( 1000, "49E2A1D1131F1496FAD6EDAE794A9ADBFA8844029675E3732D3B027ABB780243" ), "82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw==" )) certified = MagicMock(autospec='sakia.core.registry.Identity') certified.uid = "john" certified.pubkey = "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" certified.sigdate = 1441130831 certified.selfcert = CoroutineMock(return_value=SelfCertification( 2, "meta_brouzouf", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", "john", BlockUID( 1200, "49E2A1D1131F1496FAD6EDAE794A9ADBFA8844029675E3732D3B027ABB780243" ), "82o1sNCh1bLpUXU6nacbK48HBcA9Eu2sPkL1/3c2GtDPxBUZd2U2sb7DxwJ54n6ce9G0Oy7nd1hCxN3fS0oADw==" )) community = MagicMock(autospec='sakia.core.Community') community.blockUID = CoroutineMock(return_value=BlockUID( 3102, "49E2A1D1131F1496FAD6EDAE794A9ADBFA8844029675E3732D3B027ABB780243") ) self.identities_registry.future_find = CoroutineMock(side_effect=lambda pubkey, community :account_identity \ if pubkey == "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" else certified) community.bma_access = MagicMock( autospec='sakia.core.net.api.bma.access.BmaAccess') response = Mock() response.json = CoroutineMock(return_value={}) response.status = 200 community.bma_access.broadcast = CoroutineMock(return_value=[response]) async def exec_test(): result = await account.certify("test_password", community, "") self.assertTrue(result) self.lp.run_until_complete(exec_test()) self.assertTrue(cert_signal_sent)
def current_blockUID(self): """ Get the latest block considered valid It is the most frequent last block of every known nodes """ blocks = [n.block for n in self.synced_nodes if n.block] if len(blocks) > 0: return BlockUID(blocks[0]['number'], blocks[0]['hash']) else: return BlockUID.empty()
async def refresh_block(self, block_data): """ Refresh the blocks of this node :param dict block_data: The block data in json format """ if not self.node.current_buid or self.node.current_buid.sha_hash != block_data[ 'hash']: for endpoint in [ e for e in self.node.endpoints if isinstance(e, BMAEndpoint) ]: conn_handler = next( endpoint.conn_handler(self.session, proxy=self._user_parameters.proxy())) self._logger.debug("Requesting {0}".format(conn_handler)) try: previous_block = await self.safe_request( endpoint, bma.blockchain.block, proxy=self._user_parameters.proxy(), req_args={'number': self.node.current_buid.number}) if not previous_block: continue self.node.previous_buid = BlockUID( previous_block['number'], previous_block['hash']) break # Do not try any more endpoint except errors.DuniterError as e: if e.ucode == errors.BLOCK_NOT_FOUND: self.node.previous_buid = BlockUID.empty() # we don't change state here break else: self.change_state_and_emit(Node.CORRUPTED) break self._logger.debug( "Error in previous block reply of {0} : {1}".format( self.node.pubkey[:5], str(e))) finally: if self.node.current_buid != BlockUID( block_data['number'], block_data['hash']): self.node.current_buid = BlockUID( block_data['number'], block_data['hash']) self.node.current_ts = block_data['medianTime'] self._logger.debug("Changed block {0} -> {1}".format( self.node.current_buid.number, block_data['number'])) self.changed.emit() else: self._logger.debug( "Could not connect to any BMA endpoint : {0}".format( self.node.pubkey[:5])) self.change_state_and_emit(Node.OFFLINE) else: self.change_state_and_emit(Node.ONLINE)
def _parse_uid_lookup(data): timestamp = BlockUID.empty() found_uid = "" for result in data['results']: if result["pubkey"] == self.pubkey: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = uid_data["meta"]["timestamp"] found_uid = uid_data["uid"] return self.name == found_uid, self.name, found_uid
def _parse_uid_lookup(data): timestamp = BlockUID.empty() found_uid = "" for result in data['results']: if result["pubkey"] == identity.pubkey: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) found_identity.blockstamp = timestamp found_uid = uid_data["uid"] found_identity.signature = uid_data["self"] return identity.uid == found_uid, identity.uid, found_uid
def _refresh_uid(self, uids): """ Refresh UID from uids list, got from a successful lookup request :param list uids: UIDs got from a lookup request """ timestamp = BlockUID.empty() if self.local_state == LocalState.NOT_FOUND: for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) identity_uid = uid_data["uid"] self.uid = identity_uid self.blockchain_state = BlockchainState.BUFFERED self.local_state = LocalState.PARTIAL
def _parse_uid_lookup(data): timestamp = BlockUID.empty() found_uid = "" for result in data['results']: if result["pubkey"] == identity.pubkey: uids = result['uids'] for uid_data in uids: if BlockUID.from_str( uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str( uid_data["meta"]["timestamp"]) found_identity.blockstamp = timestamp found_uid = uid_data["uid"] found_identity.signature = uid_data["self"] return identity.uid == found_uid, identity.uid, found_uid
def _parse_pubkey_lookup(data): timestamp = BlockUID.empty() found_uid = "" found_result = ["", ""] for result in data['results']: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = uid_data["meta"]["timestamp"] found_uid = uid_data["uid"] if found_uid == self.name: found_result = result['pubkey'], found_uid if found_result[1] == self.name: return self.pubkey == found_result[0], self.pubkey, found_result[0] else: return False, self.pubkey, None
def test_identity_membership(self): def bma_access(request, *args): if request is bma.blockchain.Membership: return nice_blockchain.bma_membership_john identity = Identity( "john", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", BlockUID( 20, "7518C700E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67" ), LocalState.COMPLETED, BlockchainState.VALIDATED) self.community.bma_access.future_request = CoroutineMock( side_effect=bma_access) async def exec_test(): ms = await identity.membership(self.community) self.assertEqual(ms["blockNumber"], 0) self.assertEqual( ms["blockHash"], "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855" ) self.assertEqual(ms["membership"], "IN") self.assertEqual(ms["currency"], "test_currency") self.assertEqual(ms["written"], 10000) self.lp.run_until_complete(exec_test())
def peer_doc(self): peer = Peer(2, self.forge.currency, self.forge.key.pubkey, BlockUID.empty(), [BMAEndpoint(None, "127.0.0.1", None, self.http.port)], None) peer.sign([self.forge.key]) return peer
def test_document_message(self): # prepare message document_message = DocumentMessage() # prepare document identity_document = Identity( 10, "beta_brousouf", "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd", "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci", ) # get json string message json_document_message = document_message.get_json( DocumentMessage.IDENTITY_TYPE_ID, identity_document.inline()) # convert to dict to verify dict_document_message = json.loads(json_document_message) # verify self.assertIn("body", dict_document_message) self.assertIn("name", dict_document_message["body"]) self.assertIn("identity", dict_document_message["body"]) self.assertEqual(4, dict_document_message["body"]["name"]) expected = """HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd\ :J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci:32\ -DB30D958EE5CB75186972286ED3F4686B8A1C2CD:lolcat""" self.assertEqual(expected, dict_document_message["body"]["identity"])
def current_buid(self, currency): c = self._conn.execute( """SELECT COUNT(`uid`) FROM `nodes` WHERE member == 1 AND currency == ? LIMIT 1;""", (currency, )) data = c.fetchone() if data and data[0] > 3: c = self._conn.execute( """SELECT `current_buid`, COUNT(`current_buid`) AS `value_occurrence` FROM `nodes` WHERE member == 1 AND currency == ? GROUP BY `current_buid` ORDER BY `value_occurrence` DESC LIMIT 1;""", (currency, )) data = c.fetchone() if data: return block_uid(data[0]) else: c = self._conn.execute( """SELECT `current_buid`, COUNT(`current_buid`) AS `value_occurrence` FROM `nodes` WHERE currency == ? GROUP BY `current_buid` ORDER BY `value_occurrence` DESC LIMIT 1;""", (currency, )) data = c.fetchone() if data: return block_uid(data[0]) return BlockUID.empty()
def test_add_get_drop_node(meta_repo): nodes_repo = NodesRepo(meta_repo.conn) inserted = Node(currency="testcurrency", pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", endpoints="""BASIC_MERKLED_API test-net.duniter.fr 13.222.11.22 9201 BASIC_MERKLED_API testnet.duniter.org 80 UNKNOWNAPI some useless information""", peer_blockstamp=BlockUID.empty(), uid="doe", current_buid="15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", current_ts=12376543345, previous_buid="14-AEFFCB00E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", state=0, software="duniter", version="0.30.17") nodes_repo.insert(inserted) node = nodes_repo.get_one(currency="testcurrency", pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ") assert node.currency == "testcurrency" assert node.pubkey == "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ" assert node.endpoints[0] == BMAEndpoint("test-net.duniter.fr", "13.222.11.22", None, 9201) assert node.endpoints[1] == BMAEndpoint("testnet.duniter.org", None, None, 80) assert node.endpoints[2] == UnknownEndpoint("UNKNOWNAPI", ["some", "useless", "information"]) assert node.previous_buid == block_uid("14-AEFFCB00E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67") assert node.current_buid == block_uid("15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67") assert node.state == 0 assert node.software == "duniter" assert node.version == "0.30.17" assert node.merkle_peers_root == Node.MERKLE_EMPTY_ROOT assert node.merkle_peers_leaves == tuple() nodes_repo.drop(node) node = nodes_repo.get_one(pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ") assert node is None
async def check_destruction(self, pubkey, block_number, unit_base): amount = self._sources_processor.amount(self.currency, pubkey) if amount < 100 * 10 ** unit_base: if self._sources_processor.available(self.currency, pubkey): self._sources_processor.drop_all_of(self.currency, pubkey) timestamp = await self._blockchain_processor.timestamp(self.currency, block_number) next_txid = self._transactions_processor.next_txid(self.currency, block_number) sha_identifier = hashlib.sha256("Destruction{0}{1}{2}".format(block_number, pubkey, amount).encode("ascii")).hexdigest().upper() destruction = Transaction(currency=self.currency, pubkey=pubkey, sha_hash=sha_identifier, written_block=block_number, blockstamp=BlockUID.empty(), timestamp=timestamp, signatures=[], issuers=[pubkey], receivers=[], amount=amount, amount_base=0, comment="Too low balance", txid=next_txid, state=Transaction.VALIDATED, local=True, raw="") self._transactions_processor.commit(destruction) return destruction
async def _async_execute_search_text(self, checked): cancel_once_task(self, self._async_search_direct_connections) self.ui.busy.show() text = self.ui.edit_textsearch.text() if len(text) < 2: return try: response = await self.community.bma_access.future_request(bma.wot.Lookup, {'search': text}) identities = [] for identity_data in response['results']: for uid_data in identity_data['uids']: identity = Identity.from_handled_data(uid_data['uid'], identity_data['pubkey'], BlockUID.from_str(uid_data['meta']['timestamp']), BlockchainState.BUFFERED) identities.append(identity) self.ui.edit_textsearch.clear() self.ui.edit_textsearch.setPlaceholderText(text) await self.refresh_identities(identities) except errors.DuniterError as e: if e.ucode == errors.BLOCK_NOT_FOUND: logging.debug(str(e)) except NoPeerAvailable as e: logging.debug(str(e)) finally: self.ui.busy.hide()
def current_buid(self, currency): c = self._conn.execute("""SELECT COUNT(`uid`) FROM `nodes` WHERE member == 1 AND currency == ? LIMIT 1;""", (currency,)) data = c.fetchone() if data and data[0] > 3: c = self._conn.execute("""SELECT `current_buid`, COUNT(`current_buid`) AS `value_occurrence` FROM `nodes` WHERE member == 1 AND currency == ? GROUP BY `current_buid` ORDER BY `value_occurrence` DESC LIMIT 1;""", (currency,)) data = c.fetchone() if data: return block_uid(data[0]) else: c = self._conn.execute("""SELECT `current_buid`, COUNT(`current_buid`) AS `value_occurrence` FROM `nodes` WHERE currency == ? GROUP BY `current_buid` ORDER BY `value_occurrence` DESC LIMIT 1;""", (currency,)) data = c.fetchone() if data: return block_uid(data[0]) return BlockUID.empty()
def get_membership_document(mtype, current_block, identity, salt, password): """ Get a Membership document :param str mtype: "IN" to ask for membership or "OUT" to cancel membership :param dict current_block: Current block data :param Identity identity: Identity document :param str salt: Passphrase of the account :param str password: Password of the account :rtype: Membership """ # get current block BlockStamp timestamp = BlockUID(current_block['number'], current_block['hash']) # create keys from credentials key = SigningKey(salt, password, ScryptParams(4096, 16, 1)) # create identity document membership = Membership(version=10, currency=current_block['currency'], issuer=key.pubkey, membership_ts=timestamp, membership_type=mtype, uid=identity.uid, identity_ts=identity.timestamp, signature=None) # sign document membership.sign([key]) return membership
def get_identity_document(current_block, uid, salt, password): """ Get an Identity document :param dict current_block: Current block data :param str uid: Unique Identifier :param str salt: Passphrase of the account :param str password: Password of the account :rtype: SelfCertification """ # get current block BlockStamp timestamp = BlockUID(current_block['number'], current_block['hash']) # create keys from credentials key = SigningKey(salt, password) # create identity document identity = SelfCertification(version=2, currency=current_block['currency'], pubkey=key.pubkey, uid=uid, ts=timestamp, signature=None) # sign document identity.sign([key]) return identity
def get_identity_document(current_block: dict, uid: str, salt: str, password: str) -> Identity: """ Get an Identity document :param current_block: Current block data :param uid: Unique IDentifier :param salt: Passphrase of the account :param password: Password of the account :rtype: Identity """ # get current block BlockStamp timestamp = BlockUID(current_block['number'], current_block['hash']) # create keys from credentials key = SigningKey.from_credentials(salt, password) # create identity document identity = Identity(version=10, currency=current_block['currency'], pubkey=key.pubkey, uid=uid, ts=timestamp, signature=None) # sign document identity.sign([key]) return identity
def _refresh_uid(self, uids): """ Refresh UID from uids list, got from a successful lookup request :param list uids: UIDs got from a lookup request """ timestamp = BlockUID.empty() if self.local_state == LocalState.NOT_FOUND: for uid_data in uids: if BlockUID.from_str( uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str( uid_data["meta"]["timestamp"]) identity_uid = uid_data["uid"] self.uid = identity_uid self.blockchain_state = BlockchainState.BUFFERED self.local_state = LocalState.PARTIAL
async def future_find(self, pubkey, community): """ :param pubkey: The pubkey we look for :param community: The community where we look for the identity :return: The identity found :rtype: sakia.core.registry.Identity """ if pubkey in self._identities(community): identity = self._identities(community)[pubkey] else: identity = Identity.empty(pubkey) self._identities(community)[pubkey] = identity tries = 0 while tries < 3 and identity.local_state == LocalState.NOT_FOUND: try: data = await community.bma_access.simple_request(bma.blockchain.Membership, req_args={'search': pubkey}) identity.uid = data['uid'] identity.sigdate = BlockUID.from_str(data['sigDate']) identity.local_state = LocalState.PARTIAL identity.blockchain_state = BlockchainState.VALIDATED except errors.DuniterError as e: if errors.NO_MEMBER_MATCHING_PUB_OR_UID: identity = await self._find_by_lookup(pubkey, community) return identity else: tries += 1 except asyncio.TimeoutError: tries += 1 except ClientError: tries += 1 except NoPeerAvailable: return identity return identity
async def request_current_block(self): """ Request a node on the HTTP GET interface If an error occurs, the node is considered offline """ for endpoint in [ e for e in self.node.endpoints if isinstance(e, BMAEndpoint) ]: try: block_data = await self.safe_request( endpoint, bma.blockchain.current, proxy=self._user_parameters.proxy()) if not block_data: continue await self.refresh_block(block_data) return # Do not try any more endpoint except errors.DuniterError as e: if e.ucode == errors.BLOCK_NOT_FOUND: self.node.previous_buid = BlockUID.empty() self.change_state_and_emit(Node.ONLINE) else: self.change_state_and_emit(Node.CORRUPTED) self._logger.debug("Error in block reply : {0}".format( str(e))) else: self._logger.debug("Could not connect to any BMA endpoint") self.change_state_and_emit(Node.OFFLINE)
def get_identity_document( current_block: dict, uid: str, key: SigningKey, ) -> Identity: """ Get an Identity document :param current_block: Current block data :param uid: Unique IDentifier :param key: cryptographic key to sign documents :rtype: Identity """ # get current block BlockStamp timestamp = BlockUID(current_block["number"], current_block["hash"]) # create identity document identity = Identity( version=10, currency=current_block["currency"], pubkey=key.pubkey, uid=uid, ts=timestamp, signature=None, ) # sign document identity.sign([key]) return identity
class Connection: """ A connection represents a connection to a currency's network It is defined by the currency name, and the key informations used to connect to it. If the user is using an identity, it is defined here too. """ currency = attr.ib(convert=str) pubkey = attr.ib(convert=str) uid = attr.ib(convert=str, default="", cmp=False, hash=False) scrypt_N = attr.ib(convert=int, default=4096, cmp=False, hash=False) scrypt_r = attr.ib(convert=int, default=16, cmp=False, hash=False) scrypt_p = attr.ib(convert=int, default=1, cmp=False, hash=False) blockstamp = attr.ib(convert=block_uid, default=BlockUID.empty(), cmp=False, hash=False) salt = attr.ib(convert=str, init=False, cmp=False, hash=False) password = attr.ib(init=False, convert=str, default="", cmp=False, hash=False) def is_identity(self): return self.uid is not "" def is_wallet(self): return self.uid is "" def title(self): return "@".join([self.uid, self.pubkey[:11]]) @property def scrypt_params(self): return ScryptParams(self.scrypt_N, self.scrypt_r, self.scrypt_p)
def get_certification_document(current_block, self_cert_document, from_pubkey, salt, password): """ Create and return a Certification document :param dict current_block: Current block data :param Identity self_cert_document: Identity document :param str from_pubkey: Pubkey of the certifier :param str salt: Secret salt (DO NOT SHOW IT ANYWHERE, IT IS SECRET !!!) :param str password: Secret password (DO NOT SHOW IT ANYWHERE, IT IS SECRET !!!) :rtype: Certification """ # construct Certification Document certification = Certification(version=10, currency=current_block['currency'], pubkey_from=from_pubkey, pubkey_to=self_cert_document.pubkey, timestamp=BlockUID(current_block['number'], current_block['hash']), signature="") # sign document key = SigningKey(salt, password, ScryptParams(4096, 16, 1)) certification.sign(self_cert_document, [key]) return certification
class Blockchain: # Parameters in block 0 parameters = attr.ib(default=BlockchainParameters(), cmp=False, hash=False) # block number and hash current_buid = attr.ib(convert=block_uid, default=BlockUID.empty()) # Number of members current_members_count = attr.ib(convert=int, default=0, cmp=False, hash=False) # Current monetary mass in units current_mass = attr.ib(convert=int, default=0, cmp=False, hash=False) # Median time in seconds median_time = attr.ib(convert=int, default=0, cmp=False, hash=False) # Last members count last_mass = attr.ib(convert=int, default=0, cmp=False, hash=False) # Last members count last_members_count = attr.ib(convert=int, default=0, cmp=False, hash=False) # Last UD amount in units (multiply by 10^base) last_ud = attr.ib(convert=int, default=1, cmp=False, hash=False) # Last UD base last_ud_base = attr.ib(convert=int, default=0, cmp=False, hash=False) # Last UD base last_ud_time = attr.ib(convert=int, default=0, cmp=False, hash=False) # Previous monetary mass in units previous_mass = attr.ib(convert=int, default=0, cmp=False, hash=False) # Previous members count previous_members_count = attr.ib(convert=int, default=0, cmp=False, hash=False) # Previous UD amount in units (multiply by 10^base) previous_ud = attr.ib(convert=int, default=0, cmp=False, hash=False) # Previous UD base previous_ud_base = attr.ib(convert=int, default=0, cmp=False, hash=False) # Previous UD base previous_ud_time = attr.ib(convert=int, default=0, cmp=False, hash=False) # Currency name currency = attr.ib(convert=str, default="", cmp=False, hash=False)
def application_with_two_connections(application_with_one_connection, big_blockchain_forge, bob, john): connection = Connection(currency="test_currency", pubkey=john.key.pubkey, uid="", scrypt_N=mirage.User.SCRYPT_PARAMS.N, scrypt_r=mirage.User.SCRYPT_PARAMS.r, scrypt_p=mirage.User.SCRYPT_PARAMS.p, blockstamp=str(BlockUID.empty())) application_with_one_connection.db.connections_repo.insert(connection) for s in big_blockchain_forge.user_identities[bob.key.pubkey].sources: try: application_with_one_connection.db.sources_repo.insert( Source(currency=big_blockchain_forge.currency, pubkey=bob.key.pubkey, identifier=s.origin_id, noffset=s.index, type=s.source, amount=s.amount, base=s.base)) except sqlite3.IntegrityError: pass return application_with_one_connection
async def test_new_block_with_idty(application_with_one_connection, john, fake_server_with_blockchain): john_identity = Identity( currency=fake_server_with_blockchain.forge.currency, pubkey=john.key.pubkey, uid=john.uid, blockstamp=john.blockstamp, signature=john.identity().signatures[0]) john_connection = Connection(currency="test_currency", pubkey=john.key.pubkey, uid=john.uid, scrypt_N=4096, scrypt_r=4, scrypt_p=2, blockstamp=john.blockstamp) application_with_one_connection.db.connections_repo.insert(john_connection) application_with_one_connection.db.identities_repo.insert(john_identity) application_with_one_connection.instanciate_services() john_found = application_with_one_connection.db.identities_repo.get_one( pubkey=john_identity.pubkey) assert john_found.written is False fake_server_with_blockchain.forge.forge_block() fake_server_with_blockchain.forge.push(john.identity()) fake_server_with_blockchain.forge.push(john.join(BlockUID.empty())) fake_server_with_blockchain.forge.forge_block() fake_server_with_blockchain.forge.forge_block() new_blocks = fake_server_with_blockchain.forge.blocks[-3:] await application_with_one_connection.identities_service.handle_new_blocks( new_blocks) john_found = application_with_one_connection.db.identities_repo.get_one( pubkey=john_identity.pubkey) assert john_found.written is True await fake_server_with_blockchain.close()
def from_json(cls, json_data, version): """ Create a person from json data :param dict json_data: The person as a dict in json format :return: A new person if pubkey wasn't known, else a new person instance. """ pubkey = json_data['pubkey'] uid = json_data['uid'] local_state = LocalState[json_data['local_state']] blockchain_state = BlockchainState[json_data['blockchain_state']] if version >= parse_version("0.20.0dev0") and json_data['sigdate']: sigdate = BlockUID.from_str(json_data['sigdate']) else: sigdate = BlockUID.empty() return cls(uid, pubkey, sigdate, local_state, blockchain_state)
async def selfcert(self, community): """ Get the identity self certification. This request is not cached in the person object. :param sakia.core.community.Community community: The community target to request the self certification :return: A SelfCertification duniterpy object :rtype: duniterpy.documents.certification.SelfCertification """ try: timestamp = BlockUID.empty() lookup_data = await community.bma_access.future_request(bma.wot.Lookup, req_args={'search': self.pubkey}) for result in lookup_data['results']: if result["pubkey"] == self.pubkey: uids = result['uids'] for uid_data in uids: # If the sigDate was written in the blockchain if self._sigdate and BlockUID.from_str(uid_data["meta"]["timestamp"]) == self._sigdate: timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) uid = uid_data["uid"] signature = uid_data["self"] # Else we choose the latest one found elif BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) uid = uid_data["uid"] signature = uid_data["self"] if not self.sigdate: self.sigdate = timestamp return SelfCertification(PROTOCOL_VERSION, community.currency, self.pubkey, uid, timestamp, signature) except errors.DuniterError as e: if e.ucode == errors.NO_MATCHING_IDENTITY: raise LookupFailureError(self.pubkey, community) except MalformedDocumentError: raise LookupFailureError(self.pubkey, community) except NoPeerAvailable: logging.debug("No peer available")
def initialize_root_nodes(self, currency): if not self.nodes(currency): for pubkey in ROOT_SERVERS[currency]["nodes"]: node = Node(currency=currency, pubkey=pubkey, endpoints=ROOT_SERVERS[currency]["nodes"][pubkey], peer_blockstamp=BlockUID.empty(), state=0) self._repo.insert(node)
def _parse_pubkey_lookup(data): timestamp = BlockUID.empty() found_uid = "" found_result = ["", ""] for result in data['results']: uids = result['uids'] for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) found_identity.blockstamp = timestamp found_uid = uid_data["uid"] found_identity.signature = uid_data["self"] if found_uid == identity.uid: found_result = result['pubkey'], found_uid if found_result[1] == identity.uid: return identity.pubkey == found_result[0], identity.pubkey, found_result[0] else: return False, identity.pubkey, None
def current_buid(self, currency): """ Get the latest block considered valid It is the most frequent last block of every known nodes """ blocks_uids = [n.current_buid for n in self.synced_nodes(currency)] if len(blocks_uids) > 0: return blocks_uids[0] else: return BlockUID.empty()
def load(cls, data): """ Create a new transfer from a dict in json format. :param dict data: The loaded data :return: A new transfer :rtype: Transfer """ return cls(data['hash'], TransferState[data['state']], BlockUID.from_str(data['blockUID']) if data['blockUID'] else None, data['metadata'], data['local'])
def simple_blockchain_forge(simple_forge, alice, bob): simple_forge.push(alice.identity()) simple_forge.push(bob.identity()) simple_forge.push(alice.join(BlockUID.empty())) simple_forge.push(bob.join(BlockUID.empty())) simple_forge.push(alice.certify(bob, BlockUID.empty())) simple_forge.push(bob.certify(alice, BlockUID.empty())) simple_forge.forge_block() simple_forge.set_member(alice.key.pubkey, True) simple_forge.set_member(bob.key.pubkey, True) for i in range(0, 10): new_user = mirage.User.create("test_currency", "user{0}".format(i), "salt{0}".format(i), "password{0}".format(i), simple_forge.blocks[-1].blockUID) simple_forge.push(new_user.identity()) simple_forge.push(new_user.join(simple_forge.blocks[-1].blockUID)) simple_forge.forge_block() simple_forge.set_member(new_user.key.pubkey, True) simple_forge.generate_dividend() simple_forge.forge_block() return simple_forge
async def published_uid(self, community): try: data = await community.bma_access.future_request(bma.wot.Lookup, req_args={'search': self.pubkey}) timestamp = BlockUID.empty() for result in data['results']: if result["pubkey"] == self.pubkey: uids = result['uids'] person_uid = "" for uid_data in uids: if BlockUID.from_str(uid_data["meta"]["timestamp"]) >= timestamp: timestamp = uid_data["meta"]["timestamp"] person_uid = uid_data["uid"] if person_uid == self.uid: return True except errors.DuniterError as e: logging.debug("Lookup error : {0}".format(str(e))) except NoPeerAvailable as e: logging.debug(str(e)) return False
async def certified_by(self, identities_registry, community): """ Get the list of persons certified by this person :param sakia.core.registry.IdentitiesRegistry identities_registry: The registry :param sakia.core.community.Community community: The community target :return: The list of the certified persons of this community in BMA json format :rtype: list """ certified_list = list() try: data = await community.bma_access.future_request(bma.wot.CertifiedBy, {'search': self.pubkey}) for certified_data in data['certifications']: certified = {} certified['identity'] = identities_registry.from_handled_data(certified_data['uid'], certified_data['pubkey'], None, BlockchainState.VALIDATED, community) certified['cert_time'] = certified_data['cert_time']['medianTime'] if certified_data['written']: certified['block_number'] = certified_data['written']['number'] else: certified['block_number'] = None certified_list.append(certified) except errors.DuniterError as e: if e.ucode in (errors.NO_MATCHING_IDENTITY, errors.NO_MEMBER_MATCHING_PUB_OR_UID): logging.debug("Certified by error : {0}".format(str(e))) except NoPeerAvailable as e: logging.debug(str(e)) try: data = await community.bma_access.future_request(bma.wot.Lookup, {'search': self.pubkey}) for result in data['results']: if result["pubkey"] == self.pubkey: self._refresh_uid(result['uids']) for certified_data in result['signed']: certified = {} certified['identity'] = identities_registry.from_handled_data(certified_data['uid'], certified_data['pubkey'], None, BlockchainState.BUFFERED, community) timestamp = BlockUID.from_str(certified_data['meta']['timestamp']) certified['cert_time'] = await community.time(timestamp.number) certified['block_number'] = None certified_list.append(certified) except errors.DuniterError as e: if e.ucode in (errors.NO_MATCHING_IDENTITY, errors.NO_MEMBER_MATCHING_PUB_OR_UID): logging.debug("Lookup error : {0}".format(str(e))) except NoPeerAvailable as e: logging.debug(str(e)) return certified_list
async def get_identity_document(client: Client, currency: str, pubkey: str) -> Identity: """ Get the Identity document of the pubkey :param client: Client to connect to the api :param currency: Currency name :param pubkey: Public key :rtype: Identity """ # Here we request for the path wot/lookup/pubkey lookup_data = await client(bma.wot.lookup, pubkey) # init vars uid = None timestamp = BlockUID.empty() signature = None # parse results for result in lookup_data['results']: if result["pubkey"] == pubkey: uids = result['uids'] for uid_data in uids: # capture data timestamp = BlockUID.from_str(uid_data["meta"]["timestamp"]) uid = uid_data["uid"] signature = uid_data["self"] # return self-certification document return Identity( version=PROTOCOL_VERSION, currency=currency, pubkey=pubkey, uid=uid, ts=timestamp, signature=signature )
def fake_server(application, event_loop): server = event_loop.run_until_complete(mirage.Node.start(None, "test_currency", "12356", "123456", event_loop)) application.db.nodes_repo.insert(Node(currency=server.forge.currency, pubkey=server.forge.key.pubkey, endpoints=server.peer_doc().endpoints, peer_blockstamp=server.peer_doc().blockUID, uid="", current_buid=BlockUID.empty(), current_ts=0, state=0, software="duniter", version="0.40.2")) application.instanciate_services() return server
async def requirements(self, community): """ Get the current requirements data. :param sakia.core.Community community: the community :return: the requirements :rtype: dict """ try: requirements = await community.bma_access.future_request(bma.wot.Requirements, {'search': self.pubkey}) for req in requirements['identities']: if req['pubkey'] == self.pubkey and req['uid'] == self.uid and \ self._sigdate and \ BlockUID.from_str(req['meta']['timestamp']) == self._sigdate: return req except errors.DuniterError as e: logging.debug(str(e)) return None
def build_stopline(currency, pubkey, block_number, mediantime): """ Used to insert a line of ignored tx in the history """ transaction = Transaction(currency=currency, pubkey=pubkey, sha_hash=STOPLINE_HASH, written_block=block_number, blockstamp=BlockUID(block_number, BlockUID.empty().sha_hash), timestamp=mediantime, signatures="", issuers="", receivers="", amount=0, amount_base=0, comment="", txid=0, state=Transaction.VALIDATED, raw="") return transaction
def test_add_update_node(meta_repo): nodes_repo = NodesRepo(meta_repo.conn) node = Node("testcurrency", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", """BASIC_MERKLED_API test-net.duniter.fr 13.222.11.22 9201 BASIC_MERKLED_API testnet.duniter.org 80 UNKNOWNAPI some useless information""", BlockUID.empty(), "doe", "15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 12376543345, "14-AEFFCB00E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67", 0, "duniter") nodes_repo.insert(node) node.previous_buid = node.current_buid node.current_buid = "16-77543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67" nodes_repo.update(node) node2 = nodes_repo.get_one(pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ") assert node2.current_buid == block_uid("16-77543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67") assert node2.previous_buid == block_uid("15-76543400E78B56CC21FB1DDC6CBAB24E0FACC9A798F5ED8736EA007F38617D67")
def application_with_two_connections(application_with_one_connection, big_blockchain_forge, bob, john): connection = Connection(currency="test_currency", pubkey=john.key.pubkey, uid="", scrypt_N=mirage.User.SCRYPT_PARAMS.N, scrypt_r=mirage.User.SCRYPT_PARAMS.r, scrypt_p=mirage.User.SCRYPT_PARAMS.p, blockstamp=str(BlockUID.empty())) application_with_one_connection.db.connections_repo.insert(connection) for s in big_blockchain_forge.user_identities[bob.key.pubkey].sources: try: application_with_one_connection.db.sources_repo.insert(Source(currency=big_blockchain_forge.currency, pubkey=bob.key.pubkey, identifier=s.origin_id, noffset=s.index, type=s.source, amount=s.amount, base=s.base)) except sqlite3.IntegrityError: pass return application_with_one_connection
async def send_selfcert(self, password, community): """ Send our self certification to a target community :param str password: The account SigningKey password :param community: The community target of the self certification """ try: block_data = await community.bma_access.simple_request(bma.blockchain.Current) signed_raw = "{0}{1}\n".format(block_data['raw'], block_data['signature']) block_uid = Block.from_signed_raw(signed_raw).blockUID except errors.DuniterError as e: if e.ucode == errors.NO_CURRENT_BLOCK: block_uid = BlockUID.empty() else: raise selfcert = SelfCertification(PROTOCOL_VERSION, community.currency, self.pubkey, self.name, block_uid, None) key = SigningKey(self.salt, password) selfcert.sign([key]) logging.debug("Key publish : {0}".format(selfcert.signed_raw())) responses = await community.bma_access.broadcast(bma.wot.Add, {}, {'identity': selfcert.signed_raw()}) result = (False, "") for r in responses: if r.status == 200: result = (True, (await r.json())) elif not result[0]: result = (False, (await r.text())) else: await r.release() if result[0]: (await self.identity(community)).sigdate = block_uid return result