Пример #1
0
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))
Пример #2
0
    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)
Пример #3
0
 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()
Пример #4
0
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)
Пример #5
0
 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'))
Пример #6
0
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
    }
Пример #7
0
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
Пример #8
0
    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()
Пример #9
0
    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)
Пример #10
0
    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()
Пример #11
0
 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()
Пример #12
0
 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)
Пример #13
0
    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)
Пример #14
0
    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()
Пример #15
0
 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')
Пример #16
0
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)
Пример #17
0
 def _get_multihash(self, data: bytes) -> CID:
     hasher = sha256()
     hasher.update(data)
     h = hasher.digest()
     return to_b58_string(mh_encode(h, 'sha2-256'))
Пример #18
0
    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()
Пример #19
0
def _random_multihash():
    digest = str(uuid.uuid4()).encode()
    return multihash.to_b58_string(multihash.encode(digest, 'sha2-256'))