def decode_ipfs_hash(hex_hash): """ Decode a Base58 IPFS hash from a 32 byte hex string """ if hex_hash.startswith('0x'): hex_hash = remove_0x_prefix(hex_hash) if not hex_hash.startswith('1220'): hex_hash = '1220' + hex_hash return multihash.to_b58_string(multihash.from_hex_string(hex_hash))
async def _do_join_market(self, member_oid, market_oid, actor_type): assert actor_type in [ActorType.CONSUMER, ActorType.PROVIDER, ActorType.PROVIDER_CONSUMER] member_data = await self.call('network.xbr.console.get_member', member_oid.bytes) member_adr = member_data['address'] config = await self.call('network.xbr.console.get_config') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex(config['verifying_contract_adr'][2:]) status = await self.call('network.xbr.console.get_status') block_number = status['block']['number'] meta_obj = { } meta_data = cbor2.dumps(meta_obj) h = hashlib.sha256() h.update(meta_data) meta_hash = multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256')) signature = sign_eip712_market_join(self._ethkey_raw, verifyingChain, verifyingContract, member_adr, block_number, market_oid.bytes, actor_type, meta_hash) request_submitted = await self.call('network.xbr.console.join_market', member_oid.bytes, market_oid.bytes, verifyingChain, block_number, verifyingContract, actor_type, meta_hash, meta_data, signature) vaction_oid = uuid.UUID(bytes=request_submitted['vaction_oid']) self.log.info('SUCCESS! XBR market join request submitted: vaction_oid={vaction_oid}', vaction_oid=vaction_oid)
def test_valid_to_b58_string(self, valid): for case in valid: code = case['encoding']['code'] buf = multihash.encode(bytes.fromhex(case['hex']), code) # Currently a lame test, but good for regression testing if we change our underlying base58 lib assert multihash.to_b58_string(buf) == base58.b58encode( buf).decode()
def decode(value): """ Decode B58 multi hash. :param bytes value: an encoded content :return: the decoded content :rtype: str """ cid = make_cid(value) return multihash.to_b58_string(cid.multihash)
def _get_file_multihash(self, fobj): fobj.seek(0) BLOCK_SIZE = 2**20 hash_function = hashlib.sha256() while True: data = fobj.read(BLOCK_SIZE) if not data: break hash_function.update(data) fobj.seek(0) return multihash.to_b58_string( multihash.encode(hash_function.digest(), 'sha2-256'))
def get_resolver_data(query, net='ropsten'): registry = web3_data['ENSRegistry']['contract'][net] resol = registry.functions.resolver(ENS.namehash(query)).call() owner = registry.functions.owner(ENS.namehash(query)).call() resolver = w3[net].eth.contract(resol, abi=web3_data['PublicResolver']['abi']) if resolver.functions.supportsInterface( '0x3b3b57de').call(): #addr interface address = resolver.functions.addr(ENS.namehash(query)).call() else: address = '' contenthash = '' onion = '' ipfs = '' swarm = '' if resolver.functions.supportsInterface( '0xbc1c58d1').call(): #contentHash interface contenthashbytes = resolver.functions.contenthash( ENS.namehash(query)).call() print(is_empty_hex(contenthashbytes), 'contenthash') if not is_empty_hex(contenthashbytes): #check codec of multihash mh = multihash.decode(contenthashbytes) print(mh) contenthash = mh.digest.decode('utf-8') if mh.name == 'ipfs-ns': ipfs = contenthash elif mh.name == 'swarm-ns': swarm = contenthash elif (mh.name == 'onion' or mh.name == 'onion3'): onion = contenthash content = '' if resolver.functions.supportsInterface( '0xd8389dc5').call(): #content interface contentbytes = resolver.functions.content(ENS.namehash(query)).call() print(is_empty_hex(contentbytes), 'content') if not is_empty_hex(contentbytes): buffer = multihash.encode(contentbytes, 'sha2-256') content = multihash.to_b58_string(buffer) return { 'owner': owner, 'resolver': resol, 'address': address, 'content': content, 'contenthash': contenthash, 'onion': onion, 'ipfs': ipfs, 'swarm': swarm }
def ipfs_get_json(ipfs_conn: ipfsapi.client.Client, file_hash: str, tmpdir: Optional[PS] = None) -> Dict[str, Any]: """ Perform an ipfs.get and return the json object as a Python dict """ if isinstance(file_hash, bytes): file_hash = to_b58_string( from_hex_string('1220' + remove_0x_prefix(file_hash.hex()))) elif is_0x_prefixed(file_hash): file_hash = to_b58_string( from_hex_string('1220' + remove_0x_prefix(file_hash))) elif is_hex(file_hash): file_hash = to_b58_string(from_hex_string('1220' + file_hash)) elif file_hash.startswith('Qm'): pass else: raise ValueError("Invalid file_hash") with tempfile.TemporaryDirectory(dir=tmpdir) as _workdir: workdir = Path(_workdir) orig_dir = Path.cwd() assert orig_dir is not None os.chdir(workdir) ipfs_conn.get(file_hash) downloaded: Path = workdir.joinpath(file_hash) if not downloaded.exists() or not downloaded.is_file(): raise ScatterError("Download filed. File not found.") contents = '' with downloaded.open() as _userfile: userfile_text = _userfile.read() print("Downloaded... {}".format(userfile_text)) contents = json.loads(userfile_text) os.chdir(orig_dir) downloaded.unlink() return contents
async def onJoin(self, details): self.log.info('{klass}.onJoin(details={details})', klass=self.__class__.__name__, details=details) try: member_username = self.config.extra['username'] member_email = self.config.extra['email'] client_pubkey = binascii.a2b_hex(self._key.public_key()) # fake wallet type "metamask" wallet_type = 'metamask' # delegate ethereum private key object wallet_key = self._ethkey wallet_raw = self._ethkey_raw # delegate ethereum account canonical address wallet_adr = wallet_key.public_key.to_canonical_address() config = await self.call('xbr.network.get_config') status = await self.call('xbr.network.get_status') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex( config['verifying_contract_adr'][2:]) registered = status['block']['number'] eula = config['eula']['hash'] # create an aux-data object with info only stored off-chain (in our xbrbackend DB) .. profile_obj = { 'member_username': member_username, 'member_email': member_email, 'client_pubkey': client_pubkey, 'wallet_type': wallet_type, } # .. hash the serialized aux-data object .. profile_data = cbor2.dumps(profile_obj) h = hashlib.sha256() h.update(profile_data) # .. compute the sha256 multihash b58-encoded string from that .. profile = multihash.to_b58_string( multihash.encode(h.digest(), 'sha2-256')) signature = sign_eip712_member_register(wallet_raw, verifyingChain, verifyingContract, wallet_adr, registered, eula, profile) # https://xbr.network/docs/network/api.html#xbrnetwork.XbrNetworkApi.onboard_member try: result = await self.call('xbr.network.onboard_member', member_username, member_email, client_pubkey, wallet_type, wallet_adr, verifyingChain, registered, verifyingContract, eula, profile, profile_data, signature) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) self.leave('wamp.error', str(e)) return except Exception as e: raise e assert type(result) == dict assert 'timestamp' in result and type( result['timestamp']) == int and result['timestamp'] > 0 assert 'action' in result and result['action'] == 'onboard_member' assert 'vaction_oid' in result and type( result['vaction_oid']) == bytes and len( result['vaction_oid']) == 16 vaction_oid = uuid.UUID(bytes=result['vaction_oid']) self.log.info( 'On-boarding member - verification "{vaction_oid}" created', vaction_oid=vaction_oid) # fd = 'cloud/planet_xbr_crossbar/.crossbar/.verifications' fd = self._verifications if not os.path.isdir(fd): os.mkdir(fd) fn = 'onboard-member-email-verification.{}'.format(vaction_oid) verification_file = os.path.abspath(os.path.join(fd, fn)) with open(verification_file, 'rb') as f: data = f.read() verified_data = cbor2.loads(data) self.log.info('Verified data:\n{verified_data}', verified_data=verified_data) vaction_code = verified_data['onboard_vcode'] self.log.info( 'Verifying member using vaction_oid={vaction_oid}, vaction_code={vaction_code} ..', vaction_oid=vaction_oid, vaction_code=vaction_code) try: result = await self.call('xbr.network.verify_onboard_member', vaction_oid.bytes, vaction_code) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) raise e assert type(result) == dict assert 'member_oid' in result and type( result['member_oid']) == bytes and len( result['member_oid']) == 16 assert 'created' in result and type( result['created']) == int and result['created'] > 0 member_oid = result['member_oid'] self.log.info( 'SUCCESS! New XBR Member onboarded: member_oid={member_oid}, result=\n{result}', member_oid=uuid.UUID(bytes=member_oid), result=pformat(result)) except Exception as e: self.log.failure() self.config.extra['error'] = e finally: self.leave()
async def _do_onboard_member(self, member_username, member_email): client_pubkey = binascii.a2b_hex(self._key.public_key()) # fake wallet type "metamask" wallet_type = 'metamask' # delegate ethereum private key object wallet_key = self._ethkey wallet_raw = self._ethkey_raw # delegate ethereum account canonical address wallet_adr = wallet_key.public_key.to_canonical_address() config = await self.call('network.xbr.console.get_config') status = await self.call('network.xbr.console.get_status') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex(config['verifying_contract_adr'][2:]) registered = status['block']['number'] eula = config['eula']['hash'] # create an aux-data object with info only stored off-chain (in our xbrbackend DB) .. profile_obj = { 'member_username': member_username, 'member_email': member_email, 'client_pubkey': client_pubkey, 'wallet_type': wallet_type, } # .. hash the serialized aux-data object .. profile_data = cbor2.dumps(profile_obj) h = hashlib.sha256() h.update(profile_data) # .. compute the sha256 multihash b58-encoded string from that .. profile = multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256')) signature = sign_eip712_member_register(wallet_raw, verifyingChain, verifyingContract, wallet_adr, registered, eula, profile) # https://xbr.network/docs/network/api.html#xbrnetwork.XbrNetworkApi.onboard_member try: result = await self.call('network.xbr.console.onboard_member', member_username, member_email, client_pubkey, wallet_type, wallet_adr, verifyingChain, registered, verifyingContract, eula, profile, profile_data, signature) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) self.leave('wamp.error', str(e)) return except Exception as e: raise e assert type(result) == dict assert 'timestamp' in result and type(result['timestamp']) == int and result['timestamp'] > 0 assert 'action' in result and result['action'] == 'onboard_member' assert 'vaction_oid' in result and type(result['vaction_oid']) == bytes and len(result['vaction_oid']) == 16 vaction_oid = uuid.UUID(bytes=result['vaction_oid']) self.log.info('On-boarding member - verification "{vaction_oid}" created', vaction_oid=vaction_oid)
async def onJoin(self, details): self.log.info('{klass}.onJoin(details={details})', klass=self.__class__.__name__, details=details) try: assert details.authrole == 'member' # WAMP authid on xbrnetwork follows this format: "member-" member_id = details.authid[7:] member_id = UUID(member_id) # member_data = await self.call('xbr.network.get_member', member_id.bytes) # member_adr = member_data['address'] # delegate ethereum private key object wallet_key = self._ethkey wallet_raw = self._ethkey_raw # delegate ethereum account canonical address wallet_adr = wallet_key.public_key.to_canonical_address() config = await self.call('xbr.network.get_config') status = await self.call('xbr.network.get_status') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex( config['verifying_contract_adr'][2:]) created = status['block']['number'] # FIXME: Where to get ? api_id = uuid.uuid4().bytes # Get catalogs of the current user try: catalogs_oids = await self.call( 'xbr.network.get_catalogs_by_owner', member_id.bytes) self.log.info( f"get_catalogs_by_owner results=\n\n{pformat(catalogs_oids)}\n" ) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) raise e assert len( catalogs_oids) > 0, "Not catalogs found for the current user" catalog_id = catalogs_oids[0] # create an aux-data object with info only stored off-chain (in our xbrbackend DB) .. data_obj = {} # .. hash the serialized aux-data object .. meta_data = cbor2.dumps(data_obj) h = hashlib.sha256() h.update(meta_data) # .. compute the sha256 multihash b58-encoded string from that .. meta_hash = multihash.to_b58_string( multihash.encode(h.digest(), 'sha2-256')) schema_obj = {} schema_data = cbor2.dumps(schema_obj) h = hashlib.sha256() h.update(schema_data) # .. compute the sha256 multihash b58-encoded string from that .. schema_hash = multihash.to_b58_string( multihash.encode(h.digest(), 'sha2-256')) signature = sign_eip712_api_publish(wallet_raw, verifyingChain, verifyingContract, wallet_adr, created, catalog_id, api_id, schema_hash, meta_hash) # https://xbr.network/docs/network/api.html#xbrnetwork.XbrNetworkApi.onboard_member try: result = await self.call('xbr.network.publish_api', member_id.bytes, catalog_id, api_id, verifyingChain, created, verifyingContract, schema_hash, schema_data, meta_hash, meta_data, signature, {}) self.log.info("create_catalog results:\n\n{result}\n", result=pformat(result)) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) self.leave('wamp.error', str(e)) return except Exception as e: raise e assert type(result) == dict assert 'created' in result and type( result['created']) == int and result['created'] > 0 assert 'action' in result and result['action'] == 'publish_api' assert 'vaction_oid' in result and type( result['vaction_oid']) == bytes and len( result['vaction_oid']) == 16 vaction_oid = uuid.UUID(bytes=result['vaction_oid']) self.log.info('Publish API - verification "{vaction_oid}" created', vaction_oid=vaction_oid) # fd = 'cloud/planet_xbr_crossbar/.crossbar/.verifications' fd = self._verifications if not os.path.isdir(fd): os.mkdir(fd) fn = 'publish-api-email-verification.{}'.format(vaction_oid) verification_file = os.path.abspath(os.path.join(fd, fn)) with open(verification_file, 'rb') as f: data = f.read() verified_data = cbor2.loads(data) self.log.info('Verified data:\n{verified_data}\n', verified_data=pformat(verified_data)) vaction_code = verified_data['vcode'] self.log.info( 'Publishing Api using vaction_oid={vaction_oid}, vaction_code={vaction_code} ..', vaction_oid=vaction_oid, vaction_code=vaction_code) try: result = await self.call('xbr.network.verify_publish_api', vaction_oid.bytes, vaction_code) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) raise e assert type(result) == dict assert 'member_oid' in result and type( result['member_oid']) == bytes and len( result['member_oid']) == 16 assert 'catalog_oid' in result and type(result['catalog_oid']) == bytes and \ len(result['catalog_oid']) == 16 and result['catalog_oid'] == catalog_id assert 'api_oid' in result and type( result['api_oid']) == bytes and len(result['api_oid']) == 16 catalog_oid = result['catalog_oid'] api_id = result['api_oid'] self.log.info( 'SUCCESS! New XBR Api published: api_oid={api_oid}, catalog_oid={catalog_id}, ' 'result: {result}\n', api_oid=uuid.UUID(bytes=api_id).__str__(), catalog_id=uuid.UUID(bytes=catalog_oid).__str__(), result=pformat(result)) # Lets see if we can now fetch the newly created catalog try: result = await self.call('xbr.network.get_api', api_id) except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) raise e assert type(result) == dict assert 'oid' in result and type( result['oid']) == bytes and result['oid'] == api_id assert 'catalog_oid' in result and type( result['catalog_oid']) == bytes # Lets get *all* APIs try: apis = await self.call('xbr.network.find_apis') except ApplicationError as e: self.log.error('ApplicationError: {error}', error=e) raise e assert type(apis) == list for api in apis: assert type(api) == bytes and len(api) == 16 except Exception as e: self.log.failure() self.config.extra['error'] = e finally: self.leave()
def test_to_b58_string_valid(self, value): """ to_b58_string: test if it passes for all valid cases """ code = value['encoding']['code'] buffer = encode(bytes.fromhex(value['hex']), code) assert to_b58_string(buffer) == base58.b58encode(buffer).decode()
def test_to_b58_string_invalid(self, value): """ to_b58_string: raises TypeError for invalid types """ with pytest.raises(TypeError) as excinfo: to_b58_string(value) assert 'multihash should be bytes' in str(excinfo.value)
async def _do_create_market(self, member_oid, market_oid, marketmaker, title=None, label=None, homepage=None, provider_security=0, consumer_security=0, market_fee=0): member_data = await self.call('network.xbr.console.get_member', member_oid.bytes) member_adr = member_data['address'] config = await self.call('network.xbr.console.get_config') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex(config['verifying_contract_adr'][2:]) coin_adr = binascii.a2b_hex(config['contracts']['xbrtoken'][2:]) status = await self.call('network.xbr.console.get_status') block_number = status['block']['number'] # count all markets before we create a new one: res = await self.call('network.xbr.console.find_markets') cnt_market_before = len(res) self.log.info('Total markets before: {cnt_market_before}', cnt_market_before=cnt_market_before) res = await self.call('network.xbr.console.get_markets_by_owner', member_oid.bytes) cnt_market_by_owner_before = len(res) self.log.info('Market for owner: {cnt_market_by_owner_before}', cnt_market_by_owner_before=cnt_market_by_owner_before) # collect information for market creation that is stored on-chain # terms text: encode in utf8 and compute BIP58 multihash string terms_data = 'these are my market terms (randint={})'.format(random.randint(0, 1000)).encode('utf8') h = hashlib.sha256() h.update(terms_data) terms_hash = str(multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256'))) # market meta data that doesn't change. the hash of this is part of the data that is signed and also # stored on-chain (only the hash, not the meta data!) meta_obj = { 'chain_id': verifyingChain, 'block_number': block_number, 'contract_adr': verifyingContract, 'member_adr': member_adr, 'member_oid': member_oid.bytes, 'market_oid': market_oid.bytes, } meta_data = cbor2.dumps(meta_obj) h = hashlib.sha256() h.update(meta_data) meta_hash = multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256')) # create signature for pre-signed transaction signature = sign_eip712_market_create(self._ethkey_raw, verifyingChain, verifyingContract, member_adr, block_number, market_oid.bytes, coin_adr, terms_hash, meta_hash, marketmaker, provider_security, consumer_security, market_fee) # for wire transfer, convert to bytes provider_security = pack_uint256(provider_security) consumer_security = pack_uint256(consumer_security) market_fee = pack_uint256(market_fee) # market settings that can change. even though changing might require signing, neither the data nor # and signatures are stored on-chain. however, even when only signed off-chain, this establishes # a chain of signature anchored in the on-chain record for this market! attributes = { 'title': title, 'label': label, 'homepage': homepage, } # now provide everything of above: # - market operator (owning member) and market oid # - signed market data and signature # - settings createmarket_request_submitted = await self.call('network.xbr.console.create_market', member_oid.bytes, market_oid.bytes, verifyingChain, block_number, verifyingContract, coin_adr, terms_hash, meta_hash, meta_data, marketmaker, provider_security, consumer_security, market_fee, signature, attributes) self.log.info('SUCCESS: Create market request submitted: \n{createmarket_request_submitted}\n', createmarket_request_submitted=pformat(createmarket_request_submitted)) assert type(createmarket_request_submitted) == dict assert 'timestamp' in createmarket_request_submitted and type( createmarket_request_submitted['timestamp']) == int and createmarket_request_submitted['timestamp'] > 0 assert 'action' in createmarket_request_submitted and createmarket_request_submitted[ 'action'] == 'create_market' assert 'vaction_oid' in createmarket_request_submitted and type( createmarket_request_submitted['vaction_oid']) == bytes and len( createmarket_request_submitted['vaction_oid']) == 16 vaction_oid = uuid.UUID(bytes=createmarket_request_submitted['vaction_oid']) self.log.info('SUCCESS: New Market verification "{vaction_oid}" created', vaction_oid=vaction_oid)
async def onJoin(self, details): self.log.info('{klass}.onJoin(details={details})', klass=self.__class__.__name__, details=details) try: assert details.authrole == 'member' # WAMP authid on xbrnetwork follows this format: "member-" member_id = details.authid[7:] member_id = UUID(member_id) member_data = await self.call('xbr.network.get_member', member_id.bytes) member_adr = member_data['address'] config = await self.call('xbr.network.get_config') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex( config['verifying_contract_adr'][2:]) # remember the number of markets we joined before markets_by_actor_before = await self.call( 'xbr.network.get_markets_by_actor', member_id.bytes) cnt_markets_by_actor_before = len(markets_by_actor_before) # join the first market we find market_oids = await self.call('xbr.network.find_markets') assert len(market_oids ) > 0, 'fatal: no markets defined that we could join' marketId = market_oids[0] for actorType in [ActorType.PROVIDER, ActorType.CONSUMER]: status = await self.call('xbr.network.get_status') block_number = status['block']['number'] meta_obj = {} meta_data = cbor2.dumps(meta_obj) h = hashlib.sha256() h.update(meta_data) meta_hash = multihash.to_b58_string( multihash.encode(h.digest(), 'sha2-256')) signature = sign_eip712_market_join( self._ethkey_raw, verifyingChain, verifyingContract, member_adr, block_number, marketId, actorType, meta_hash) request_submitted = await self.call( 'xbr.network.join_market', member_id.bytes, marketId, verifyingChain, block_number, verifyingContract, actorType, meta_hash, meta_data, signature) self.log.info( 'Join market request submitted (actorType={actorType}, member_id={member_id}, member_adr=0x{member_adr}): \n{request_submitted}\n', member_id=member_id, actorType=actorType, member_adr=binascii.b2a_hex(member_adr).decode(), request_submitted=pformat(request_submitted)) assert type(request_submitted) == dict assert 'created' in request_submitted and type( request_submitted['created'] ) == int and request_submitted['created'] > 0 assert 'action' in request_submitted and request_submitted[ 'action'] == 'join_market' assert 'vaction_oid' in request_submitted and type( request_submitted['vaction_oid']) == bytes and len( request_submitted['vaction_oid']) == 16 vaction_oid = UUID(bytes=request_submitted['vaction_oid']) self.log.info( 'Join market verification "{vaction_oid}" created', vaction_oid=vaction_oid) # fd = 'cloud/planet_xbr_crossbar/.crossbar/.verifications' fd = self._verifications if not os.path.isdir(fd): os.mkdir(fd) fn = 'join-market-email-verification.{}'.format(vaction_oid) verification_file = os.path.abspath(os.path.join(fd, fn)) with open(verification_file, 'rb') as f: data = f.read() verified_data = cbor2.loads(data) self.log.info('Verified data:\n{verified_data}', verified_data=verified_data) vaction_code = verified_data['vcode'] self.log.info( 'Verifying join market using vaction_oid={vaction_oid}, vaction_code={vaction_code} ..', vaction_oid=vaction_oid, vaction_code=vaction_code) request_verified = await self.call( 'xbr.network.verify_join_market', vaction_oid.bytes, vaction_code) self.log.info( 'Join market request verified: \n{request_verified}\n', request_verified=pformat(request_verified)) assert type(request_verified) == dict assert 'market_oid' in request_verified and type( request_verified['market_oid']) == bytes and len( request_verified['market_oid']) == 16 assert 'created' in request_verified and type( request_verified['created'] ) == int and request_verified['created'] > 0 market_oid = request_verified['market_oid'] self.log.info( 'SUCCESS! XBR market joined: market_oid={market_oid}, actor_type={actor_type}, result=\n{result}', market_oid=UUID(bytes=market_oid), actor_type=actorType, result=pformat(request_verified)) markets_by_actor_after = await self.call( 'xbr.network.get_markets_by_actor', member_id.bytes) cnt_markets_by_actor_after = len(markets_by_actor_after) cnt_new_joins = cnt_markets_by_actor_after - cnt_markets_by_actor_before print('markets_by_actor_before: ', markets_by_actor_before) print('markets_by_actor_after: ', markets_by_actor_after) print('cnt_markets_by_actor_before: ', cnt_markets_by_actor_before) print('cnt_markets_by_actor_after: ', cnt_markets_by_actor_after) print('cnt_new_joins: ', cnt_new_joins) # assert cnt_new_joins == 1, 'expected 1 market, but found {} new ones!'.format(cnt_new_joins) # assert market_oid in market_oids, 'expected to find market ID {}, but not found in {} returned market IDs'.format(UUID(bytes=market_oid), len(market_oids)) except Exception as e: self.log.failure() self.config.extra['error'] = e finally: self.leave()
def test_invalid_to_b58_string(self): # In actual fact, type checking should catch this for us with pytest.raises(TypeError): multihash.to_b58_string('hello world')
def _gen_ipfs_hash(): # IPFS uses sha2-256 and B58 string encoding, eg "QmevbQAb6L7MsZUxqsspYREqMhMqaaV6arvF4UytgdsSfX" data = os.urandom(100) digest = hashlib.sha256(data).digest() hash = multihash.encode(digest, 'sha2-256') return multihash.to_b58_string(hash)
def _get_multihash(self, data: bytes) -> CID: hasher = sha256() hasher.update(data) h = hasher.digest() return to_b58_string(mh_encode(h, 'sha2-256'))
async def onJoin(self, details): self.log.info('{klass}.onJoin(details={details})', klass=self.__class__.__name__, details=details) try: assert details.authrole == 'member' # WAMP authid on xbrnetwork follows this format: "member-" member_id = details.authid[7:] member_id = UUID(member_id) member_data = await self.call('xbr.network.get_member', member_id.bytes) member_adr = member_data['address'] config = await self.call('xbr.network.get_config') verifyingChain = config['verifying_chain_id'] verifyingContract = binascii.a2b_hex(config['verifying_contract_adr'][2:]) coin_adr = binascii.a2b_hex(config['contracts']['xbrtoken'][2:]) status = await self.call('xbr.network.get_status') block_number = status['block']['number'] # count all markets before we create a new one: res = await self.call('xbr.network.find_markets') cnt_market_before = len(res) res = await self.call('xbr.network.get_markets_by_owner', member_id.bytes) cnt_market_by_owner_before = len(res) # create a new market .. market_oid = uuid.uuid4() # collect information for market creation that is stored on-chain # terms text: encode in utf8 and compute BIP58 multihash string terms_data = 'these are my market terms (randint={})'.format(random.randint(0, 1000)).encode('utf8') h = hashlib.sha256() h.update(terms_data) terms_hash = str(multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256'))) # market maker address maker = os.urandom(20) # provider and consumer security provider_security = 0 * 10**18 consumer_security = 0 * 10**18 # market operator fee market_fee = 0 * 10**18 # market meta data that doesn't change. the hash of this is part of the data that is signed and also # stored on-chain (only the hash, not the meta data!) meta_obj = { 'chain_id': verifyingChain, 'block_number': block_number, 'contract_adr': verifyingContract, 'member_adr': member_adr, 'member_oid': member_id.bytes, 'market_oid': market_oid.bytes, } meta_data = cbor2.dumps(meta_obj) h = hashlib.sha256() h.update(meta_data) meta_hash = multihash.to_b58_string(multihash.encode(h.digest(), 'sha2-256')) # create signature for pre-signed transaction signature = sign_eip712_market_create(self._ethkey_raw, verifyingChain, verifyingContract, member_adr, block_number, market_oid.bytes, coin_adr, terms_hash, meta_hash, maker, provider_security, consumer_security, market_fee) # for wire transfer, convert to bytes provider_security = pack_uint256(provider_security) consumer_security = pack_uint256(consumer_security) market_fee = pack_uint256(market_fee) # market settings that can change. even though changing might require signing, neither the data nor # and signatures are stored on-chain. however, even when only signed off-chain, this establishes # a chain of signature anchored in the on-chain record for this market! attributes = { 'title': 'International Data Monetization Award', 'label': 'IDMA', 'homepage': 'https://markets.international-data-monetization-award.com/', } # now provide everything of above: # - market operator (owning member) and market oid # - signed market data and signature # - settings createmarket_request_submitted = await self.call('xbr.network.create_market', member_id.bytes, market_oid.bytes, verifyingChain, block_number, verifyingContract, coin_adr, terms_hash, meta_hash, meta_data, maker, provider_security, consumer_security, market_fee, signature, attributes) self.log.info('Create market request submitted: \n{createmarket_request_submitted}\n', createmarket_request_submitted=pformat(createmarket_request_submitted)) assert type(createmarket_request_submitted) == dict assert 'timestamp' in createmarket_request_submitted and type( createmarket_request_submitted['timestamp']) == int and createmarket_request_submitted['timestamp'] > 0 assert 'action' in createmarket_request_submitted and createmarket_request_submitted[ 'action'] == 'create_market' assert 'vaction_oid' in createmarket_request_submitted and type( createmarket_request_submitted['vaction_oid']) == bytes and len( createmarket_request_submitted['vaction_oid']) == 16 vaction_oid = UUID(bytes=createmarket_request_submitted['vaction_oid']) self.log.info('Create market verification "{vaction_oid}" created', vaction_oid=vaction_oid) # fd = 'cloud/planet_xbr_crossbar/.crossbar/.verifications' fd = self._verifications if not os.path.isdir(fd): os.mkdir(fd) fn = 'create-market-email-verification.{}'.format(vaction_oid) verification_file = os.path.abspath(os.path.join(fd, fn)) with open(verification_file, 'rb') as f: data = f.read() verified_data = cbor2.loads(data) self.log.info('Verified data:\n{verified_data}', verified_data=verified_data) vaction_code = verified_data['vcode'] self.log.info('Verifying create market using vaction_oid={vaction_oid}, vaction_code={vaction_code} ..', vaction_oid=vaction_oid, vaction_code=vaction_code) create_market_request_verified = await self.call('xbr.network.verify_create_market', vaction_oid.bytes, vaction_code) self.log.info('Create market request verified: \n{create_market_request_verified}\n', create_market_request_verified=pformat(create_market_request_verified)) assert type(create_market_request_verified) == dict assert 'market_oid' in create_market_request_verified and type( create_market_request_verified['market_oid']) == bytes and len( create_market_request_verified['market_oid']) == 16 assert 'created' in create_market_request_verified and type( create_market_request_verified['created']) == int and create_market_request_verified['created'] > 0 market_oid = create_market_request_verified['market_oid'] self.log.info('SUCCESS! New XBR market created: market_oid={market_oid}, result=\n{result}', market_oid=UUID(bytes=market_oid), result=pformat(create_market_request_verified)) market_oids = await self.call('xbr.network.find_markets') self.log.info('SUCCESS - find_markets: found {cnt_markets} markets', cnt_markets=len(market_oids)) # count all markets after we created a new market: cnt_market_after = len(market_oids) cnt_new_markets = cnt_market_after - cnt_market_before assert cnt_new_markets == 1, 'expected 1 market, but found {} new ones!'.format(cnt_new_markets) assert market_oid in market_oids, 'expected to find market ID {}, but not found in {} returned market IDs'.format( UUID(bytes=market_oid), len(market_oids)) market_oids = await self.call('xbr.network.get_markets_by_owner', member_id.bytes) self.log.info('SUCCESS - get_markets_by_owner: found {cnt_markets} markets', cnt_markets=len(market_oids)) # count all markets after we created a new market: cnt_market_by_owner_after = len(market_oids) cnt_new_markets_by_owner = cnt_market_by_owner_after - cnt_market_by_owner_before assert cnt_new_markets_by_owner == 1, 'expected 1 market, but found {} new ones!'.format( cnt_new_markets_by_owner) assert market_oid in market_oids, 'expected to find market ID {}, but not found in {} returned market IDs'.format( UUID(bytes=market_oid), len(market_oids)) for market_oid in market_oids: self.log.info('xbr.network.get_market(market_oid={market_oid}) ..', market_oid=market_oid) market = await self.call('xbr.network.get_market', market_oid, include_attributes=True) self.log.info('SUCCESS: got market information\n\n{market}\n', market=pformat(market)) except Exception as e: self.log.failure() self.config.extra['error'] = e finally: self.leave()
def _random_multihash(): digest = str(uuid.uuid4()).encode() return multihash.to_b58_string(multihash.encode(digest, 'sha2-256'))