def process_payment(iou: Optional[IOU], pathfinding_service: PathfindingService, service_fee: TokenAmount) -> None: if service_fee == 0: return if iou is None: raise exceptions.MissingIOU # Basic IOU validity checks if not is_same_address(iou.receiver, pathfinding_service.address): raise exceptions.WrongIOURecipient( expected=pathfinding_service.address) if not iou.is_signature_valid(): raise exceptions.InvalidSignature # Compare with known IOU active_iou = pathfinding_service.database.get_iou(sender=iou.sender, claimed=False) if active_iou: if active_iou.expiration_block != iou.expiration_block: raise exceptions.UseThisIOU(iou=active_iou) expected_amount = active_iou.amount + service_fee else: claimed_iou = pathfinding_service.database.get_iou( sender=iou.sender, expiration_block=iou.expiration_block, claimed=True) if claimed_iou: raise exceptions.IOUAlreadyClaimed min_expiry = pathfinding_service.web3.eth.blockNumber + MIN_IOU_EXPIRY if iou.expiration_block < min_expiry: raise exceptions.IOUExpiredTooEarly(min_expiry=min_expiry) expected_amount = service_fee if iou.amount < expected_amount: raise exceptions.InsufficientServicePayment( expected_amount=expected_amount) # Check client's deposit in UserDeposit contract udc = pathfinding_service.user_deposit_contract udc_balance = udc.functions.effectiveBalance(iou.sender).call() required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR) if udc_balance < required_deposit: raise exceptions.DepositTooLow(required_deposit=required_deposit) log.info( "Received service fee", sender=iou.sender, expected_amount=expected_amount, total_amount=iou.amount, added_amount=expected_amount - service_fee, ) # Save latest IOU iou.claimed = False pathfinding_service.database.upsert_iou(iou)
def process_payment(iou_dict: dict, pathfinding_service: PathfindingService): if pathfinding_service.service_fee == 0: return if iou_dict is None: raise exceptions.MissingIOU # Basic IOU validity checks iou, errors = IOU.Schema().load(iou_dict) if errors: raise exceptions.InvalidRequest(**errors) if iou.receiver != pathfinding_service.address: raise exceptions.WrongIOURecipient( expected=pathfinding_service.address) if not iou.is_signature_valid(): raise exceptions.InvalidSignature # Compare with known IOU active_iou = pathfinding_service.database.get_iou( sender=iou.sender, claimed=False, ) if active_iou: if active_iou.expiration_block != iou.expiration_block: raise exceptions.UseThisIOU(iou=active_iou) expected_amount = active_iou.amount + pathfinding_service.service_fee else: claimed_iou = pathfinding_service.database.get_iou( sender=iou.sender, expiration_block=iou.expiration_block, claimed=True, ) if claimed_iou: raise exceptions.IOUAlreadyClaimed min_expiry = pathfinding_service.web3.eth.blockNumber + MIN_IOU_EXPIRY if iou.expiration_block < min_expiry: raise exceptions.IOUExpiredTooEarly(min_expiry=min_expiry) expected_amount = pathfinding_service.service_fee if iou.amount < expected_amount: raise exceptions.InsufficientServicePayment( expected_amount=expected_amount) # Check client's deposit in UserDeposit contract udc = pathfinding_service.user_deposit_contract udc_balance = udc.functions.effectiveBalance(iou.sender).call() required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR) if udc_balance < required_deposit: raise exceptions.DepositTooLow(required_deposit=required_deposit) # Save latest IOU iou.claimed = False pathfinding_service.database.upsert_iou(iou)
def process_payment( # pylint: disable=too-many-branches iou: Optional[IOU], pathfinding_service: PathfindingService, service_fee: TokenAmount, one_to_n_address: Address, ) -> None: if service_fee == 0: return if iou is None: raise exceptions.MissingIOU # Basic IOU validity checks if not is_same_address(iou.receiver, pathfinding_service.address): raise exceptions.WrongIOURecipient( expected=pathfinding_service.address) if iou.chain_id != pathfinding_service.chain_id: raise exceptions.UnsupportedChainID( expected=pathfinding_service.chain_id) if iou.one_to_n_address != one_to_n_address: raise exceptions.WrongOneToNAddress(expected=one_to_n_address, got=iou.one_to_n_address) if not iou.is_signature_valid(): raise exceptions.InvalidSignature # Compare with known IOU active_iou = pathfinding_service.database.get_iou(sender=iou.sender, claimed=False) if active_iou: if active_iou.expiration_block != iou.expiration_block: raise exceptions.UseThisIOU(iou=active_iou) expected_amount = active_iou.amount + service_fee else: claimed_iou = pathfinding_service.database.get_iou( sender=iou.sender, expiration_block=iou.expiration_block, claimed=True) if claimed_iou: raise exceptions.IOUAlreadyClaimed min_expiry = pathfinding_service.web3.eth.blockNumber + MIN_IOU_EXPIRY if iou.expiration_block < min_expiry: raise exceptions.IOUExpiredTooEarly(min_expiry=min_expiry) expected_amount = service_fee if iou.amount < expected_amount: raise exceptions.InsufficientServicePayment( expected_amount=expected_amount) # Check client's deposit in UserDeposit contract udc = pathfinding_service.user_deposit_contract latest_block = pathfinding_service.web3.eth.blockNumber udc_balance = get_pessimistic_udc_balance( udc=udc, address=iou.sender, from_block=latest_block - pathfinding_service.required_confirmations, to_block=latest_block, ) required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR_PFS) if udc_balance < required_deposit: raise exceptions.DepositTooLow(required_deposit=required_deposit) log.info( "Received service fee", sender=iou.sender, expected_amount=expected_amount, total_amount=iou.amount, added_amount=expected_amount - service_fee, ) # Save latest IOU iou.claimed = False pathfinding_service.database.upsert_iou(iou)
def process_payment( # pylint: disable=too-many-branches iou: Optional[IOU], pathfinding_service: PathfindingService, service_fee: TokenAmount, one_to_n_address: Address, ) -> None: if service_fee == 0: if iou is not None: log.debug( "Discarding IOU, service fee is 0", sender=to_checksum_address(iou.sender), total_amount=iou.amount, claimable_until=iou.claimable_until, ) else: log.debug("No IOU and service fee is 0") return if iou is None: raise exceptions.MissingIOU log.debug( "Checking IOU", sender=to_checksum_address(iou.sender), total_amount=iou.amount, claimable_until=iou.claimable_until, ) # Basic IOU validity checks if not is_same_address(iou.receiver, pathfinding_service.address): raise exceptions.WrongIOURecipient(expected=pathfinding_service.address) if iou.chain_id != pathfinding_service.chain_id: raise exceptions.UnsupportedChainID(expected=pathfinding_service.chain_id) if iou.one_to_n_address != one_to_n_address: raise exceptions.WrongOneToNAddress(expected=one_to_n_address, got=iou.one_to_n_address) if not iou.is_signature_valid(): raise exceptions.InvalidSignature # Compare with known IOU latest_block = pathfinding_service.blockchain_state.latest_committed_block active_iou = pathfinding_service.database.get_iou(sender=iou.sender, claimed=False) if active_iou: if active_iou.claimable_until != iou.claimable_until: raise exceptions.UseThisIOU(iou=active_iou.Schema().dump(active_iou)) expected_amount = active_iou.amount + service_fee else: claimed_iou = pathfinding_service.database.get_iou( sender=iou.sender, claimable_until=iou.claimable_until, claimed=True ) if claimed_iou: raise exceptions.IOUAlreadyClaimed min_expiry = get_posix_utc_time_now() + MIN_IOU_EXPIRY if iou.claimable_until < min_expiry: raise exceptions.IOUExpiredTooEarly( min_expiry=min_expiry, claimable_until_received=iou.claimable_until ) expected_amount = service_fee if iou.amount < expected_amount: raise exceptions.InsufficientServicePayment( expected_amount=expected_amount, actual_amount=iou.amount ) # Check client's deposit in UserDeposit contract udc = pathfinding_service.user_deposit_contract udc_balance = get_pessimistic_udc_balance( udc=udc, address=iou.sender, from_block=BlockNumber(latest_block - pathfinding_service.required_confirmations), to_block=latest_block, ) required_deposit = round(expected_amount * UDC_SECURITY_MARGIN_FACTOR_PFS) if udc_balance < required_deposit: raise exceptions.DepositTooLow( required_deposit=required_deposit, seen_deposit=udc_balance, block_number=latest_block ) log.info( "Received service fee", sender=iou.sender, expected_amount=expected_amount, total_amount=iou.amount, added_amount=expected_amount - service_fee, ) # Save latest IOU iou.claimed = False pathfinding_service.database.upsert_iou(iou)