async def _do_open_channel(self, market_oid, channel_oid, channel_type, delegate, amount): member_key = self._ethkey_raw member_adr = self._ethkey.public_key.to_canonical_address() config = await self.call('xbr.marketmaker.get_config') marketmaker = config['marketmaker'] recipient = config['owner'] verifying_chain_id = config['verifying_chain_id'] verifying_contract_adr = binascii.a2b_hex( config['verifying_contract_adr'][2:]) status = await self.call('xbr.marketmaker.get_status') current_block_number = status['block']['number'] if amount > 0: if channel_type == ChannelType.PAYMENT: allowance1 = xbr.xbrtoken.functions.allowance( member_adr, xbr.xbrchannel.address).call() xbr.xbrtoken.functions.approve(xbr.xbrchannel.address, amount).transact({ 'from': member_adr, 'gas': self._default_gas }) allowance2 = xbr.xbrtoken.functions.allowance( member_adr, xbr.xbrchannel.address).call() assert allowance2 - allowance1 == amount elif channel_type == ChannelType.PAYING: allowance1 = xbr.xbrtoken.functions.allowance( marketmaker, xbr.xbrchannel.address).call() xbr.xbrtoken.functions.approve(xbr.xbrchannel.address, amount).transact({ 'from': marketmaker, 'gas': self._default_gas }) allowance2 = xbr.xbrtoken.functions.allowance( marketmaker, xbr.xbrchannel.address).call() assert allowance2 - allowance1 == amount else: assert False, 'should not arrive here' # compute EIP712 signature, and sign using member private key signature = sign_eip712_channel_open( member_key, verifying_chain_id, verifying_contract_adr, channel_type, current_block_number, market_oid.bytes, channel_oid.bytes, member_adr, delegate, marketmaker, recipient, amount) attributes = None channel_request = await self.call( 'xbr.marketmaker.open_channel', member_adr, market_oid.bytes, channel_oid.bytes, verifying_chain_id, current_block_number, verifying_contract_adr, channel_type, delegate, marketmaker, recipient, pack_uint256(amount), signature, attributes) self.log.info('Channel open request submitted:\n\n{channel_request}\n', channel_request=pformat(channel_request))
def _process_block(self, w3, block_number, Events): """ :param w3: :param block_number: :param Events: :return: """ cnt = 0 # filter by block, and XBR contract addresses # FIXME: potentially add filters for global data or market specific data for the markets started in this worker filter_params = { 'address': [ xbr.xbrtoken.address, xbr.xbrnetwork.address, xbr.xbrcatalog.address, xbr.xbrmarket.address, xbr.xbrchannel.address ], 'fromBlock': block_number, 'toBlock': block_number, } result = w3.eth.getLogs(filter_params) if result: for evt in result: receipt = w3.eth.getTransactionReceipt(evt['transactionHash']) for Event, handler in Events: # FIXME: MismatchedABI pops up .. we silence this with errors=web3.logs.DISCARD if hasattr(web3, 'logs') and web3.logs: all_res = Event().processReceipt(receipt, errors=web3.logs.DISCARD) else: all_res = Event().processReceipt(receipt) for res in all_res: self.log.info('{handler} processing block {block_number} / txn {txn} with args {args}', handler=hl(handler.__name__), block_number=hlid(block_number), txn=hlid('0x' + binascii.b2a_hex(evt['transactionHash']).decode()), args=hlval(res.args)) handler(res.transactionHash, res.blockHash, res.args) cnt += 1 with self._db.begin(write=True) as txn: block = cfxdb.xbr.block.Block() block.timestamp = np.datetime64(time_ns(), 'ns') block.block_number = block_number # FIXME # block.block_hash = bytes() block.cnt_events = cnt self._xbr.blocks[txn, pack_uint256(block_number)] = block if cnt: self.log.info('Processed blockchain block {block_number}: processed {cnt} XBR events.', block_number=hlid(block_number), cnt=hlid(cnt)) else: self.log.info('Processed blockchain block {block_number}: no XBR events found!', block_number=hlid(block_number)) return cnt
async def _do_open_channel(self, market_oid, channel_oid, channel_type, delegate, amount): member_key = self._ethkey_raw member_adr = self._ethkey.public_key.to_canonical_address() config = await self.call('xbr.marketmaker.get_config') marketmaker = binascii.a2b_hex(config['marketmaker'][2:]) recipient = binascii.a2b_hex(config['owner'][2:]) verifying_chain_id = config['verifying_chain_id'] verifying_contract_adr = binascii.a2b_hex(config['verifying_contract_adr'][2:]) status = await self.call('xbr.marketmaker.get_status') current_block_number = status['block']['number'] if amount > 0: if channel_type == ChannelType.PAYMENT: from_adr = member_adr to_adr = xbr.xbrchannel.address elif channel_type == ChannelType.PAYING: from_adr = marketmaker to_adr = xbr.xbrchannel.address else: assert False, 'should not arrive here' # allowance1 = xbr.xbrtoken.functions.allowance(transact_from, xbr.xbrchannel.address).call() # xbr.xbrtoken.functions.approve(to_adr, amount).transact( # {'from': transact_from, 'gas': transact_gas}) # allowance2 = xbr.xbrtoken.functions.allowance(transact_from, xbr.xbrchannel.address).call() # assert allowance2 - allowance1 == amount try: txn_hash = await deferToThread(self._send_Allowance, from_adr, to_adr, amount) self.log.info('transaction submitted, txn_hash={txn_hash}', txn_hash=txn_hash) except Exception as e: self.log.failure() raise e # compute EIP712 signature, and sign using member private key signature = sign_eip712_channel_open(member_key, verifying_chain_id, verifying_contract_adr, channel_type, current_block_number, market_oid.bytes, channel_oid.bytes, member_adr, delegate, marketmaker, recipient, amount) attributes = None channel_request = await self.call('xbr.marketmaker.open_channel', member_adr, market_oid.bytes, channel_oid.bytes, verifying_chain_id, current_block_number, verifying_contract_adr, channel_type, delegate, marketmaker, recipient, pack_uint256(amount), signature, attributes) self.log.info('Channel open request submitted:\n\n{channel_request}\n', channel_request=pformat(channel_request))
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 build(self, builder): oid = self.oid.bytes if self.oid else None if oid: oid = builder.CreateString(oid) username = self.username if username: username = builder.CreateString(username) email = self.email if email: email = builder.CreateString(email) wallet_address = self.wallet_address if wallet_address: wallet_address = builder.CreateString(wallet_address) registered = self.registered if registered: registered = builder.CreateString(pack_uint256(registered)) eula = self.eula if eula: eula = builder.CreateString(eula) profile = self.profile if profile: profile = builder.CreateString(profile) AccountGen.AccountStart(builder) if oid: AccountGen.AccountAddOid(builder, oid) if self.created: AccountGen.AccountAddCreated(builder, int(self.created)) if username: AccountGen.AccountAddUsername(builder, username) if email: AccountGen.AccountAddEmail(builder, email) if self.email_verified: AccountGen.AccountAddEmailVerified(builder, int(self.email_verified)) if self.wallet_type: AccountGen.AccountAddWalletType(builder, self.wallet_type) if wallet_address: AccountGen.AccountAddWalletAddress(builder, wallet_address) if registered: AccountGen.AccountAddRegistered(builder, registered) if eula: AccountGen.AccountAddEula(builder, eula) if profile: AccountGen.AccountAddProfile(builder, profile) if self.level: AccountGen.AccountAddLevel(builder, self.level) final = AccountGen.AccountEnd(builder) return final
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)