Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)