def post_uri(guid): offer_channel = channel_to_dict( g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call()) msig_address = offer_channel['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_uri_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message) websocket_uri = body['websocketUri'] transactions = [ build_transaction( offer_msig.functions.setCommunicationUri( g.chain.w3.toHex(text=websocket_uri)), base_nonce), ] return success({'transactions': transactions})
def post_challange(guid): offer_channel = channel_to_dict( g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call()) msig_address = offer_channel['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_challange_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message) state = g.chain.w3.toBytes(hexstr=body['state']) v = body['v'] r = list(map(lambda s: g.chain.w3.toBytes(hexstr=s), body['r'])) s = list(map(lambda s: g.chain.w3.toBytes(hexstr=s), body['s'])) transactions = [ build_transaction(offer_msig.functions.challengeSettle(state, v, r, s), base_nonce), ] return success({'transactions': transactions})
def post_artifacts(): config = app.config['POLYSWARMD'] session = app.config['REQUESTS_SESSION'] try: files = [(f'{i:06d}', f) for (i, f) in enumerate(request.files.getlist(key='file')) if check_size(f, g.user.max_artifact_size)] except (AttributeError, IOError): logger.error('Error checking file size') return failure('Unable to read file sizes', 400) except ArtifactTooLargeException: return failure('Artifact too large', 413) except ArtifactEmptyException: return failure('Artifact empty', 400) if not files: return failure('No artifacts', 400) if len(files) > config.artifact.limit: return failure('Too many artifacts', 400) try: response = success(config.artifact.client.add_artifacts( files, session)) except HTTPError as e: response = failure(e.response.content, e.response.status_code) except ArtifactException as e: response = failure(e.message, 500) return response
def post_create_offer_channel(): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_create_offer_channel_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message) guid = uuid.uuid4() ambassador = g.chain.w3.toChecksumAddress(body['ambassador']) expert = g.chain.w3.toChecksumAddress(body['expert']) settlement_period_length = body['settlementPeriodLength'] transactions = [ build_transaction( g.chain.offer_registry.contract.functions.initializeOfferChannel( guid.int, ambassador, expert, settlement_period_length), base_nonce), ] return success({'transactions': transactions})
def get_bounty_parameters(): bounty_fee = g.chain.bounty_registry.contract.functions.bountyFee().call() assertion_fee = g.chain.bounty_registry.contract.functions.assertionFee( ).call() bounty_amount_minimum = g.chain.bounty_registry.contract.functions.BOUNTY_AMOUNT_MINIMUM( ).call() assertion_bid_minimum = g.chain.bounty_registry.contract.functions.ASSERTION_BID_ARTIFACT_MINIMUM( ).call() assertion_bid_maximum = g.chain.bounty_registry.contract.functions.ASSERTION_BID_ARTIFACT_MAXIMUM( ).call() arbiter_lookback_range = g.chain.bounty_registry.contract.functions.ARBITER_LOOKBACK_RANGE( ).call() max_duration = g.chain.bounty_registry.contract.functions.MAX_DURATION( ).call() assertion_reveal_window = g.chain.bounty_registry.contract.functions.assertionRevealWindow( ).call() arbiter_vote_window = g.chain.bounty_registry.contract.functions.arbiterVoteWindow( ).call() return success({ 'bounty_fee': bounty_fee, 'assertion_fee': assertion_fee, 'bounty_amount_minimum': bounty_amount_minimum, 'assertion_bid_maximum': assertion_bid_maximum, 'assertion_bid_minimum': assertion_bid_minimum, 'arbiter_lookback_range': arbiter_lookback_range, 'max_duration': max_duration, 'assertion_reveal_window': assertion_reveal_window, 'arbiter_vote_window': arbiter_vote_window })
def post_assertion_metadata(): config = app.config['POLYSWARMD'] session = app.config['REQUESTS_SESSION'] body = request.get_json() loaded_body = json.loads(body) if isinstance(body, str) else body try: if not AssertionMetadata.validate(loaded_body, silent=True) and \ not BountyMetadata.validate(loaded_body, silent=True): return failure('Invalid metadata', 400) except json.JSONDecodeError: # Expected when people provide incorrect metadata. Not stack worthy return failure('Invalid Assertion metadata', 400) try: uri = config.artifact.client.add_artifact(json.dumps(loaded_body), session, redis=config.redis.client) response = success(uri) except HTTPError as e: response = failure(e.response.content, e.response.status_code) except ArtifactException as e: response = failure(e.message, 500) except Exception: logger.exception('Received error posting to IPFS got response') response = failure('Could not add metadata to ipfs', 500) return response
def post_join(guid): offer_channel = channel_to_dict( g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call()) msig_address = offer_channel['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_join_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message) state = body['state'] v = body['v'] r = body['r'] s = body['s'] transactions = [ build_transaction( offer_msig.functions.joinAgreement(state, v, to_padded_hex(r), to_padded_hex(s)), base_nonce), ] return success({'transactions': transactions})
def post_bounties_guid_assertions(guid): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_bounties_guid_assertions_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) bid = [int(b) for b in body['bid']] mask = bool_list_to_int(body['mask']) verdict_count = len([m for m in body['mask'] if m]) commitment = body.get('commitment') verdicts = body.get('verdicts') if commitment is None and verdicts is None: return failure('Require verdicts and bid_portions or a commitment', 400) if not bid or len(bid) != verdict_count: return failure( 'bid_portions must be equal in length to the number of true mask values', 400) max_bid = eth.assertion_bid_max(g.chain.bounty_registry.contract) min_bid = eth.assertion_bid_min(g.chain.bounty_registry.contract) if any((b for b in bid if max_bid < b < min_bid)): return failure('Invalid assertion bid', 400) approve_amount = sum(bid) + eth.assertion_fee( g.chain.bounty_registry.contract) nonce = None if commitment is None: nonce, commitment = calculate_commitment(account, bool_list_to_int(verdicts)) else: commitment = int(commitment) ret = { 'transactions': [ build_transaction( g.chain.nectar_token.contract.functions.approve( g.chain.bounty_registry.contract.address, approve_amount), base_nonce), build_transaction( g.chain.bounty_registry.contract.functions.postAssertion( guid.int, bid, mask, commitment), base_nonce + 1), ] } if nonce is not None: # Pass generated nonce onto user in response, used for reveal ret['nonce'] = nonce return success(ret)
def post_arbiter_staking_deposit(): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_arbiter_staking_deposit_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) amount = int(body['amount']) total = g.chain.arbiter_staking.contract.functions.balanceOf( account).call() if amount + total >= eth.staking_total_max( g.chain.arbiter_staking.contract): return failure('Total stake above allowable maximum.', 400) transactions = [ build_transaction( g.chain.nectar_token.contract.functions.approve( g.chain.arbiter_staking.contract.address, amount), base_nonce), build_transaction( g.chain.arbiter_staking.contract.functions.deposit(amount), base_nonce + 1), ] return success({'transactions': transactions})
def post_arbiter_staking_withdrawal(): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_arbiter_staking_withdrawal_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) amount = int(body['amount']) available = g.chain.arbiter_staking.contract.functions.withdrawableBalanceOf( account).call() if amount > available: return failure('Exceeds withdrawal eligible %s' % available, 400) transactions = [ build_transaction( g.chain.arbiter_staking.contract.functions.withdraw(amount), base_nonce), ] return success({'transactions': transactions})
def get_settlement_period(guid): offer_channel = g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call() channel_data = channel_to_dict(offer_channel) msig_address = channel_data['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) settlement_period_end = offer_msig.functions.settlementPeriodEnd().call() return success({'settlementPeriodEnd': settlement_period_end})
def post_bounties(): config = app.config['POLYSWARMD'] session = app.config['REQUESTS_SESSION'] account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_bounties_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) guid = uuid.uuid4() artifact_type = ArtifactType.from_string(body['artifact_type']) amount = int(body['amount']) artifact_uri = body['uri'] duration_blocks = body['duration'] metadata = body.get('metadata', '') try: arts = config.artifact.client.ls(artifact_uri, session) except HTTPError as e: return failure(e.response.content, e.response.status_code) except ArtifactException: logger.exception('Failed to ls given artifact uri') return failure(f'Failed to check artifact uri', 500) if amount < eth.bounty_amount_min( g.chain.bounty_registry.contract) * len(arts): return failure('Invalid bounty amount', 400) if metadata and not config.artifact.client.check_uri(metadata): return failure('Invalid bounty metadata URI (should be IPFS hash)', 400) num_artifacts = len(arts) bloom = calculate_bloom(arts) approve_amount = amount + eth.bounty_fee(g.chain.bounty_registry.contract) transactions = [ build_transaction( g.chain.nectar_token.contract.functions.approve( g.chain.bounty_registry.contract.address, approve_amount), base_nonce), build_transaction( g.chain.bounty_registry.contract.functions.postBounty( guid.int, artifact_type.value, amount, artifact_uri, num_artifacts, duration_blocks, bloom, metadata), base_nonce + 1), ] return success({'transactions': transactions})
def get_artifacts_status(): config = app.config['POLYSWARMD'] session = app.config['REQUESTS_SESSION'] try: return success(config.artifact.client.status(session)) except HTTPError as e: return failure(e.response.content, e.response.status_code) except ArtifactException as e: return failure(e.message, 500)
def get_balance_address_eth(address): if not g.chain.w3.isAddress(address): return failure('Invalid address', 400) address = g.chain.w3.toChecksumAddress(address) try: balance = g.chain.w3.eth.getBalance(address) return success(str(balance)) except Exception: logger.exception('Unexpected exception retrieving ETH balance') return failure("Could not retrieve balance")
def get_pending_nonces(): tx_pool = get_txpool() logger.debug('Got txpool response from Ethereum node: %s', tx_pool) transactions = dict() for key in tx_pool.keys(): tx_pool_category_nonces = tx_pool[key].get(g.eth_address, {}) transactions.update(dict(tx_pool_category_nonces)) nonces = [str(nonce) for nonce in transactions.keys()] logger.debug('Pending txpool for %s: %s', g.eth_address, nonces) return success(nonces)
def get_balance_address_nct(address): if not g.chain.w3.isAddress(address): return failure('Invalid address', 400) address = g.chain.w3.toChecksumAddress(address) try: balance = g.chain.nectar_token.contract.functions.balanceOf( address).call() return success(str(balance)) except Exception: logger.exception('Unexpected exception retrieving NCT balance') return failure("Could not retrieve balance")
def get_balance_total_stake(address): if not g.chain.w3.isAddress(address): return failure('Invalid address', 400) address = g.chain.w3.toChecksumAddress(address) try: balance = g.chain.arbiter_staking.contract.functions.balanceOf( address).call() return success(str(balance)) except Exception: logger.exception( 'Unexpected exception retrieving total staking balance') return failure("Could not retrieve balance")
def get_bounties_guid_assertions_id(guid, id_): bounty = bounty_to_dict( g.chain.bounty_registry.contract.functions.bountiesByGuid( guid.int).call()) if bounty['author'] == ZERO_ADDRESS: return failure('Bounty not found', 404) try: assertion = get_assertion(guid, id_, bounty['num_artifacts']) return success(assertion) except: # noqa: E772 return failure('Assertion not found', 404)
def post_bounties_guid_settle(guid): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) transactions = [ build_transaction( g.chain.bounty_registry.contract.functions.settleBounty(guid.int), base_nonce) ] return success({'transactions': transactions})
def get_bounties_guid_votes_id(guid, id_): bounty = bounty_to_dict( g.chain.bounty_registry.contract.functions.bountiesByGuid( guid.int).call()) if bounty['author'] == ZERO_ADDRESS: return failure('Bounty not found', 404) try: vote = vote_to_dict( g.chain.bounty_registry.contract.functions.votesByGuid( guid.int, id_).call(), bounty['num_artifacts']) return success(vote) except: # noqa: E772 return failure('Vote not found', 404)
def create_state(): body = request.get_json() try: _create_state_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message) body['token_address'] = str(g.chain.nectar_token.address) if 'verdicts' in body and 'mask' in body: body['verdicts'] = bool_list_to_int(body['verdicts']) body['mask'] = bool_list_to_int(body['mask']) return success({'state': dict_to_state(body)})
def get_websocket(guid): offer_channel = g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call() channel_data = channel_to_dict(offer_channel) msig_address = channel_data['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) socket_uri = offer_msig.functions.websocketUri().call() # TODO find a better way than replace socket_uri = g.chain.w3.toText(socket_uri).replace('\u0000', '') if not validate_ws_url(socket_uri): return failure('Contract does not have a valid WebSocket uri', 400) return success({'websocket': socket_uri})
def post_cancel(guid): offer_channel = channel_to_dict( g.chain.offer_registry.contract.functions.guidToChannel( guid.int).call()) msig_address = offer_channel['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) transactions = [ build_transaction(offer_msig.functions.cancel(), base_nonce), ] return success({'transactions': transactions})
def get_staking_parameters(): minimum_stake = g.chain.arbiter_staking.contract.functions.MINIMUM_STAKE( ).call() maximum_stake = g.chain.arbiter_staking.contract.functions.MAXIMUM_STAKE( ).call() vote_ratio_numerator = g.chain.arbiter_staking.contract.functions.VOTE_RATIO_NUMERATOR( ).call() vote_ratio_denominator = g.chain.arbiter_staking.contract.functions.VOTE_RATIO_DENOMINATOR( ).call() return success({ 'minimum_stake': minimum_stake, 'maximum_stake': maximum_stake, 'vote_ratio_numerator': vote_ratio_numerator, 'vote_ratio_denominator': vote_ratio_denominator })
def get_artifacts_identifier_id_stat(identifier, id_): config = app.config['POLYSWARMD'] session = app.config['REQUESTS_SESSION'] try: response = success( config.artifact.client.details(identifier, id_, session)) except HTTPError as e: response = failure(e.response.content, e.response.status_code) except InvalidUriException: response = failure('Invalid artifact URI', 400) except ArtifactNotFoundException: response = failure(f'Artifact with URI {identifier} not found', 404) except ArtifactException as e: response = failure(e.message, 500) return response
def get_transactions(): body = request.get_json() try: _get_transactions_schema_validator(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) ret: Dict[str, List[Any]] = defaultdict(list) for transaction in body['transactions']: event = events_from_transaction(HexBytes(transaction), g.chain.name) for k, v in event.items(): ret[k].extend(v) if ret['errors']: logging.error('Got transaction errors: %s', ret['errors']) return failure(ret, 400) return success(ret)
def get_bounties_guid_bloom(guid): bounty = bounty_to_dict( g.chain.bounty_registry.contract.functions.bountiesByGuid( guid.int).call()) if bounty['author'] == ZERO_ADDRESS: return failure('Bounty not found', 404) try: bloom_parts = [] for i in range(0, 8): bloom_parts.append( g.chain.bounty_registry.contract.functions.bloomByGuid( guid.int, i).call()) bloom = bloom_to_dict(bloom_parts) return success(bloom) except: # noqa: E772 logger.exception('Bloom not found') return failure('Bloom not found', 404)
def get_closed(): offers_closed = [] num_of_offers = g.chain.offer_registry.contract.functions.getNumberOfOffers( ).call() for i in range(0, num_of_offers): guid = g.chain.offer_registry.contract.functions.channelsGuids( i).call() offer_channel = g.chain.offer_registry.contract.functions.guidToChannel( guid).call() channel_data = channel_to_dict(offer_channel) msig_address = channel_data['msig_address'] offer_msig = g.chain.offer_multi_sig.bind(msig_address) closed_channel = offer_msig.functions.isClosed().call() if closed_channel: offers_closed.append({'guid': guid, 'address': msig_address}) return success(offers_closed)
def post_bounties_guid_vote(guid): account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int( request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) body = request.get_json() try: _post_bounties_guid_vote_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) votes = bool_list_to_int(body['votes']) valid_bloom = bool(body['valid_bloom']) transactions = [ build_transaction( g.chain.bounty_registry.contract.functions.voteOnBounty( guid.int, votes, valid_bloom), base_nonce), ] return success({'transactions': transactions})
def send_funds_from(): # Grab correct versions by chain type account = g.chain.w3.toChecksumAddress(g.eth_address) base_nonce = int(request.args.get('base_nonce', g.chain.w3.eth.getTransactionCount(account))) erc20_relay_address = g.chain.w3.toChecksumAddress(g.chain.erc20_relay.address) body = request.get_json() try: _send_funds_from_schema(body) except fastjsonschema.JsonSchemaException as e: return failure('Invalid JSON: ' + e.message, 400) amount = int(body['amount']) transactions = [ build_transaction( g.chain.nectar_token.contract.functions.transfer(erc20_relay_address, amount), base_nonce ), ] return success({'transactions': transactions})