def ec_recover(message, signed_message): w3 = Web3Provider.get_web3() v, r, s = split_signature(w3, w3.toBytes(hexstr=signed_message)) signature_object = SignatureFix(vrs=(v, big_endian_to_int(r), big_endian_to_int(s))) return Web3Provider.get_web3().personal.ecRecover( message, signature_object.to_hex_v_hacked())
def create_agreement(did, service_definition_id, agreement_id, consumer_address, ocean=None): assert consumer_address and Web3Provider.get_web3().isChecksumAddress( consumer_address), f'Invalid consumer address {consumer_address}' asset = ocean.assets.resolve(did) asset_id = asset.asset_id service_agreement = ServiceAgreement.from_ddo(service_definition_id, asset) agreement_template = ocean.keeper.escrow_access_secretstore_template.get_instance( ) publisher_address = Web3Provider.get_web3().toChecksumAddress( asset.publisher) condition_ids = service_agreement\ .generate_agreement_condition_ids( agreement_id, asset_id, consumer_address, publisher_address, ocean.keeper ) time_locks = service_agreement.conditions_timelocks time_outs = service_agreement.conditions_timeouts return agreement_template.create_agreement(agreement_id, asset_id, condition_ids, time_locks, time_outs, consumer_address, ocean.account)
def test_create_data_asset(publisher_ocean_instance, consumer_ocean_instance): """ Setup accounts and asset, register this asset on Aquarius (MetaData store) """ pub_ocn = publisher_ocean_instance cons_ocn = consumer_ocean_instance logging.debug("".format()) sample_ddo_path = get_resource_path('ddo', 'ddo_sa_sample.json') assert sample_ddo_path.exists(), "{} does not exist!".format( sample_ddo_path) ########################################################## # Setup 2 accounts ########################################################## aquarius_acct = pub_ocn.main_account consumer_acct = cons_ocn.main_account # ensure Ocean token balance if pub_ocn.accounts.balance(aquarius_acct).ocn == 0: rcpt = pub_ocn.accounts.request_tokens(aquarius_acct, 200) Web3Provider.get_web3().eth.waitForTransactionReceipt(rcpt) if cons_ocn.accounts.balance(consumer_acct).ocn == 0: rcpt = cons_ocn.accounts.request_tokens(consumer_acct, 200) Web3Provider.get_web3().eth.waitForTransactionReceipt(rcpt) # You will need some token to make this transfer! assert pub_ocn.accounts.balance(aquarius_acct).ocn > 0 assert cons_ocn.accounts.balance(consumer_acct).ocn > 0 ########################################################## # Create an Asset with valid metadata ########################################################## asset = DDO(json_filename=sample_ddo_path) ########################################################## # List currently published assets ########################################################## meta_data_assets = pub_ocn.assets.search('') if meta_data_assets: print("Currently registered assets:") print(meta_data_assets) if asset.did in meta_data_assets: pub_ocn.assets.resolve(asset.did) pub_ocn.assets.retire(asset.did) # Publish the metadata new_asset = pub_ocn.assets.create(asset.metadata, aquarius_acct) # TODO: Ensure returned metadata equals sent! # get_asset_metadata only returns 'base' key, is this correct? published_metadata = cons_ocn.assets.resolve(new_asset.did) assert published_metadata # only compare top level keys assert sorted(list( asset.metadata['base'].keys())).remove('files') == sorted( list(published_metadata.metadata['base'].keys())).remove( 'encryptedFiles')
def get_registered_attribute(self, did_bytes): """ Example of event logs from event_filter.get_all_entries(): [AttributeDict( {'args': AttributeDict( {'did': b'\x02n\xfc\xfb\xfdNM\xe9\xb8\xe0\xba\xc2\xb2\xc7\xbeg\xc9/\x95\xc3\x16\ x98G^\xb9\xe1\xf0T\xce\x83\xcf\xab', 'owner': '0xAd12CFbff2Cb3E558303334e7e6f0d25D5791fc2', 'value': 'http://localhost:5000', 'checksum': '0x...', 'updatedAt': 1947}), 'event': 'DIDAttributeRegistered', 'logIndex': 0, 'transactionIndex': 1, 'transactionHash': HexBytes( '0xea9ca5748d54766fb43fe9660dd04b2e3bb29a0fbe18414457cca3dd488d359d'), 'address': '0x86DF95937ec3761588e6DEbAB6E3508e271cC4dc', 'blockHash': HexBytes( '0xbbbe1046b737f33b2076cb0bb5ba85a840c836cf1ffe88891afd71193d677ba2'), 'blockNumber': 1947})] """ result = None did = Web3Provider.get_web3().toHex(did_bytes) block_number = self.get_block_number_updated(did_bytes) logger.debug(f'got blockNumber {block_number} for did {did}') if block_number == 0: raise OceanDIDNotFound( f'DID "{did}" is not found on-chain in the current did registry. ' f'Please ensure assets are registered in the correct keeper contracts. ' f'The keeper-contracts DIDRegistry address is {self.address}') block_filter = self._get_event_filter(did=did, from_block=block_number, to_block=block_number) log_items = block_filter.get_all_entries(max_tries=5) if log_items: log_item = log_items[-1].args value = log_item['_value'] block_number = log_item['_blockNumberUpdated'] result = { 'checksum': log_item['_checksum'], 'value': value, 'block_number': block_number, 'did_bytes': log_item['_did'], 'owner': Web3Provider.get_web3().toChecksumAddress(log_item['_owner']), } else: logger.warning(f'Could not find {DIDRegistry.DID_REGISTRY_EVENT_NAME} event logs for ' f'did {did} at blockNumber {block_number}') return result
def get_tx_receipt(tx_hash): """ Get the receipt of a tx. :param tx_hash: hash of the transaction :return: Tx receipt """ try: Web3Provider.get_web3().eth.waitForTransactionReceipt(tx_hash, timeout=20) except Timeout: logger.info('Waiting for transaction receipt timed out.') return return Web3Provider.get_web3().eth.getTransactionReceipt(tx_hash)
def test_agreement(): template_id = Web3Provider.get_web3().toChecksumAddress('0x' + ('f' * 40)) agreement_id = '0x' + ('e' * 64) access_id = '0x' + ('a' * 64) lock_id = '0x' + ('b' * 64) escrow_id = '0x' + ('c' * 64) signature = ServiceAgreement.generate_service_agreement_hash( template_id, [access_id, lock_id, escrow_id], [0, 0, 0], [0, 0, 0], agreement_id) print({signature}) assert signature == Web3Provider.get_web3().toBytes( hexstr="0x67901517c18a3d23e05806fff7f04235cc8ae3b1f82345b8bfb3e4b02b5800c7"), \ "The signatuere is not correct."
def _get_event_filter(self, did=None, owner=None, from_block=0, to_block='latest'): _filters = {} if did is not None: _filters['_did'] = Web3Provider.get_web3().toBytes(hexstr=did) if owner is not None: _filters['_owner'] = Web3Provider.get_web3().toBytes(hexstr=owner) block_filter = EventFilter( DIDRegistry.DID_REGISTRY_EVENT_NAME, getattr(self.events, DIDRegistry.DID_REGISTRY_EVENT_NAME), from_block=from_block, to_block=to_block, argument_filters=_filters ) return block_filter
def register(self, did, checksum, url, account, providers=None): """ Register or update a DID on the block chain using the DIDRegistry smart contract. :param did: DID to register/update, can be a 32 byte or hexstring :param checksum: hex str hash of TODO :param url: URL of the resolved DID :param account: instance of Account to use to register/update the DID :param providers: list of addresses of providers to be allowed to serve the asset and play a part in creating and fulfilling service agreements :return: Receipt """ did_source_id = did_to_id_bytes(did) if not did_source_id: raise ValueError(f'{did} must be a valid DID to register') if not urlparse(url): raise ValueError(f'Invalid URL {url} to register for DID {did}') if checksum is None: checksum = Web3Provider.get_web3().toBytes(0) if not isinstance(checksum, bytes): raise ValueError(f'Invalid checksum value {checksum}, must be bytes or string') if account is None: raise ValueError('You must provide an account to use to register a DID') transaction = self._register_attribute( did_source_id, checksum, url, account, providers or [] ) receipt = self.get_tx_receipt(transaction) return receipt
def subscribe_condition_fulfilled(self, agreement_id, timeout, callback, args, timeout_callback=None, wait=False): """ Subscribe to the condition fullfilled event. :param agreement_id: id of the agreement, hex str :param timeout: :param callback: :param args: :param timeout_callback: :param wait: if true block the listener until get the event, bool :return: """ logger.info( f'Subscribing {self.FULFILLED_EVENT} event with agreement id {agreement_id}.' ) return self.subscribe_to_event( self.FULFILLED_EVENT, timeout, { '_agreementId': Web3Provider.get_web3().toBytes(hexstr=agreement_id) }, callback=callback, timeout_callback=timeout_callback, args=args, wait=wait)
def subscribe_agreement_created(self, agreement_id, timeout, callback, args, wait=False): """ Subscribe to an agreement created. :param agreement_id: id of the agreement, hex str :param timeout: :param callback: :param args: :param wait: if true block the listener until get the event, bool :return: """ logger.info( f'Subscribing {self.AGREEMENT_CREATED_EVENT} event with agreement id {agreement_id}.' ) return self.subscribe_to_event( self.AGREEMENT_CREATED_EVENT, timeout, { '_agreementId': Web3Provider.get_web3().toBytes(hexstr=agreement_id) }, callback=callback, args=args, wait=wait)
def get_default_account(config): account_address = config.get('keeper-contracts', 'account.address') account_password = config.get('keeper-contracts', 'account.password') account = Account( Web3Provider.get_web3().toChecksumAddress(account_address), account_password) return account
def test_agreement_hash(publisher_ocean_instance): """ This test verifies generating agreement hash using fixed inputs and ddo example. This will make it easier to compare the hash generated from different languages. """ w3 = Web3Provider.get_web3() did = "did:op:cb36cf78d87f4ce4a784f17c2a4a694f19f3fbf05b814ac6b0b7197163888865" template_id = w3.toChecksumAddress( "0x00bd138abd70e2f00903268f3db08f2d25677c9e") agreement_id = '0xf136d6fadecb48fdb2fc1fb420f5a5d1c32d22d9424e47ab9461556e058fefaa' ddo = get_ddo_sample() sa = ServiceAgreement.from_service_dict( ddo.get_service(service_type='Access').as_dictionary()) sa.service_agreement_template.set_template_id(template_id) assert template_id == sa.template_id, '' assert did == ddo.did # Don't generate condition ids, use fixed ids so we get consistent hash # (access_id, lock_id, escrow_id) = sa.generate_agreement_condition_ids( # agreement_id, ddo.asset_id, consumer, publisher, keeper) access_id = '0x2d7c1d60dc0c3f52aa9bd71ffdbe434a0e58435571e64c893bc9646fea7f6ec1' lock_id = '0x1e265c434c14e668695dda1555088f0ea4356f596bdecb8058812e7dcba9ee73' escrow_id = '0xe487fa6d435c2f09ef14b65b34521302f1532ac82ba8f6c86116acd8566e2da3' print(f'condition ids: \n' f'{access_id} \n' f'{lock_id} \n' f'{escrow_id}') agreement_hash = ServiceAgreement.generate_service_agreement_hash( sa.template_id, (access_id, lock_id, escrow_id), sa.conditions_timelocks, sa.conditions_timeouts, agreement_id) print('agreement hash: ', agreement_hash.hex()) expected = '0x96732b390dacec0f19ad304ac176b3407968a0184d01b3262687fd23a3f0995e' print('expected hash: ', expected) assert agreement_hash.hex() == expected, 'hash does not match.'
def get_network_id(): """ Return the ethereum network id calling the `web3.version.network` method. :return: Network id, int """ return int(Web3Provider.get_web3().version.network)
def unlock_account(account): """ Unlock the account. :param account: Account :return: """ return Web3Provider.get_web3().personal.unlockAccount(account.address, account.password)
def to_checksum_address(address): """ Validate the address provided. :param address: Address, hex str :return: address, hex str """ return Web3Provider.get_web3().toChecksumAddress(address)
def _load(contract_name): """Retrieve the contract instance for `contract_name` that represent the smart contract in the keeper network. :param contract_name: str name of the solidity keeper contract without the network name. :return: web3.eth.Contract instance """ contract_definition = ContractHandler.get_contract_dict_by_name( contract_name) address = Web3Provider.get_web3().toChecksumAddress( contract_definition['address']) abi = contract_definition['abi'] contract = Web3Provider.get_web3().eth.contract(address=address, abi=abi) ContractHandler._contracts[contract_name] = (contract, ConciseContract(contract)) return ContractHandler._contracts[contract_name]
def get_ether_balance(address): """ Get balance of an ethereum address. :param address: address, bytes32 :return: balance, int """ return Web3Provider.get_web3().eth.getBalance(address, block_identifier='latest')
def get(did): register_values = Keeper.get_instance().did_registry.contract_concise\ .getDIDRegister(did_to_id(did)) response = [] if register_values and len(register_values) == 5: response = DIDRegisterValues(*register_values)._asdict() response['last_checksum'] = Web3Provider.get_web3()\ .toHex(response['last_checksum']) return response
def token_approve(self, spender_address, price, from_account): """ Approve the passed address to spend the specified amount of tokens. :param spender_address: Account address, str :param price: Asset price, int :param from_account: Account address, str :return: bool """ if not Web3Provider.get_web3().isChecksumAddress(spender_address): spender_address = Web3Provider.get_web3().toChecksumAddress( spender_address) tx_hash = self.send_transaction('approve', (spender_address, price), transact={ 'from': from_account.address, 'passphrase': from_account.password }) return self.get_tx_receipt(tx_hash).status == 1
def sign_hash(msg_hash, account): """ :param msg_hash: :param account: Account :return: """ return Web3Provider.get_web3().personal.sign( msg_hash, account.address, account.password )
def test_get_publickey_from_address(publisher_ocean_instance): from eth_keys.exceptions import BadSignature for account in publisher_ocean_instance.accounts.list(): try: pub_key = utilities.get_public_key_from_address(Web3Provider.get_web3(), account) assert pub_key.to_checksum_address() == account.address, \ 'recovered public key address does not match original address.' except BadSignature: pytest.fail("BadSignature") except ValueError: pass
def generate_multi_value_hash(types, values): """ Return the hash of the given list of values. This is equivalent to packing and hashing values in a solidity smart contract hence the use of `soliditySha3`. :param types: list of solidity types expressed as strings :param values: list of values matching the `types` list :return: bytes """ assert len(types) == len(values) return Web3Provider.get_web3().soliditySha3(types, values)
def access(ctx): ocean, account = ctx.obj['ocean'], ctx.obj['account'] template = ocean.keeper.escrow_access_secretstore_template.get_instance() filter = template.events.AgreementCreated.createFilter(fromBlock='latest') while True: for event in filter.get_new_entries(): access_provider = event['args']['_accessProvider'] if access_provider == account.address: agreement_id = Web3Provider.get_web3().toHex( event['args']['_agreementId']) access_consumer = event['args']['_accessConsumer'] from .api.conditions import access_release access_release(ocean, account, agreement_id, access_consumer) time.sleep(0.5)
def ocean_agreements(): keeper = Keeper.get_instance() w3 = Web3Provider.get_web3() did_resolver = Mock() ddo = get_ddo_sample() service = ddo.get_service(ServiceTypes.ASSET_ACCESS) service.update_value( ServiceAgreementTemplate.TEMPLATE_ID_KEY, w3.toChecksumAddress("0x00bd138abd70e2f00903268f3db08f2d25677c9e")) did_resolver.resolve = MagicMock(return_value=ddo) consumer_class = Mock consumer_class.download = MagicMock(return_value='') return OceanAgreements(keeper, did_resolver, AssetConsumer, ConfigProvider.get_config())
def listen_lock_reward(callback_agreement_created=handle_agreement_created, callback_lock_reward=handle_lock_reward, ocean=None): template = ocean.keeper.escrow_access_secretstore_template.get_instance() lock_reward = ocean.keeper.lock_reward_condition.get_instance() filters = [ template.events.AgreementCreated.createFilter(fromBlock='latest'), lock_reward.events.Fulfilled.createFilter(fromBlock='latest'), ] while True: for _filter in filters: try: for event in _filter.get_new_entries(): print( f"\n\n{'*'*30}\nEVENT: {event['event']}\n{'*'*30}\n\n", event) agreement_id = Web3Provider.get_web3().toHex( event['args'].get('_agreementId', None)) print(ocean.agreements.status(agreement_id)) if event['event'] == 'AgreementCreated': agreements[agreement_id] = \ callback_agreement_created(event=event, agreement_id=agreement_id, ocean=ocean) elif event['event'] == 'Fulfilled': if agreement_id in agreements: agreement = agreements[agreement_id] callback_lock_reward(event=event, agreement_id=agreement_id, agreement=agreement, ocean=ocean) del agreements[agreement_id] else: # todo clean error handling print(f'error: agreement {agreement_id} ' f'not in {agreements}') print(ocean.agreements.status(agreement_id)) except ValueError as e: print('error', e) # avoid hangup, refresh filters filters = [ template.events.AgreementCreated.createFilter( fromBlock='latest'), lock_reward.events.Fulfilled.createFilter( fromBlock='latest'), ] time.sleep(0.1)
def verify_signature(_address, _agreement_hash, _signature, expected_match): w3 = Web3Provider.get_web3() prefixed_hash = prepare_prefixed_hash(_agreement_hash) recovered_address0 = w3.eth.account.recoverHash(prefixed_hash, signature=_signature) recovered_address1 = w3.eth.account.recoverHash(_agreement_hash, signature=_signature) print('original address: ', _address) print( 'w3.eth.account.recoverHash(prefixed_hash, signature=signature) => ', recovered_address0) print( 'w3.eth.account.recoverHash(agreement_hash, signature=signature) => ', recovered_address1) assert _address == (recovered_address0, recovered_address1)[expected_match], \ 'Could not verify signature using address {}'.format(_address)
def get_account_from_config(config, config_account_key, config_account_password_key): address = None if config.has_option('keeper-contracts', config_account_key): address = config.get('keeper-contracts', config_account_key) if not address: return None password = None address = Web3Provider.get_web3().toChecksumAddress(address) if address else None if (address and address in Keeper.get_instance().accounts and config.has_option('keeper-contracts', config_account_password_key)): password = config.get('keeper-contracts', config_account_password_key) return Account(address, password)
def __init__(self): self.network_name = Keeper.get_network_name(Keeper.get_network_id()) self.artifacts_path = ConfigProvider.get_config().keeper_path self.accounts = Web3Provider.get_web3().eth.accounts self.dispenser = Dispenser.get_instance() self.token = Token.get_instance() self.did_registry = DIDRegistry.get_instance() self.template_manager = TemplateStoreManager.get_instance() self.escrow_access_secretstore_template = EscrowAccessSecretStoreTemplate.get_instance() self.agreement_manager = AgreementStoreManager.get_instance() self.condition_manager = ConditionStoreManager.get_instance() self.sign_condition = SignCondition.get_instance() self.lock_reward_condition = LockRewardCondition.get_instance() self.escrow_reward_condition = EscrowRewardCondition.get_instance() self.access_secret_store_condition = AccessSecretStoreCondition.get_instance() self.hash_lock_condition = HashLockCondition.get_instance()
def list_agreements(did_or_address, ocean=None): try: assert (is_did_valid(did_or_address), True) agreement_store = AgreementStoreManager.get_instance() agreement_ids = [ Web3Provider.get_web3().toHex(_id) for _id in agreement_store.contract_concise \ .getAgreementIdsForDID(did_to_id_bytes(did_or_address)) ] except Exception as e: if did_or_address == 'me': did_or_address = ocean.account.address agreement_ids = [] for did in ocean.assets.list(did_or_address): try: agreement_ids += list_agreements(did, ocean) except ValueError as e: pass return agreement_ids
def list_agreements(ocn, account, did_or_address): try: assert (is_did_valid(did_or_address), True) agreement_store = AgreementStoreManager.get_instance() agreement_ids = [ Web3Provider.get_web3().toHex(_id) for _id in agreement_store.contract_concise \ .getAgreementIdsForDID(did_to_id_bytes(did_or_address)) ] except Exception as e: if did_or_address == 'me': did_or_address = account.address agreement_ids = [] from ocean_cli.api.assets import list_assets for did in list_assets(ocn, account, did_or_address): try: agreement_ids += list_agreements(ocn, account, did) except ValueError as e: pass return agreement_ids