public async Task <bool> TryProcessAsync(ProviderSession session, Address consumer, INdmProviderPeer peer,
                                                 DataDeliveryReceiptRequest receiptRequest, DataDeliveryReceipt deliveryReceipt)
        {
            var depositId  = session.DepositId;
            var unitsRange = receiptRequest.UnitsRange;
            var abiHash    = _abiEncoder.Encode(AbiEncodingStyle.Packed, _dataDeliveryReceiptAbiSig,
                                                receiptRequest.DepositId.Bytes, new[] { unitsRange.From, unitsRange.To });
            var address = _ecdsa.RecoverPublicKey(deliveryReceipt.Signature, Keccak.Compute(abiHash)).Address;

            if (!consumer.Equals(address))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Recovered an invalid address: '{address}' (should be: '{consumer}') for delivery receipt for deposit: '{depositId}', consumer: '{session.ConsumerAddress}', session: '{session.Id}'.");
                }
                session.SetDataAvailability(DataAvailability.DataDeliveryReceiptInvalid);
                await _sessionRepository.UpdateAsync(session);

                peer.SendDataAvailability(depositId, DataAvailability.DataDeliveryReceiptInvalid);

                return(false);
            }

            var paidUnits = unitsRange.To - unitsRange.From + 1;

            if (_logger.IsInfo)
            {
                _logger.Info($"Consumer: '{consumer}' has provided a valid receipt for deposit: '{receiptRequest.DepositId}', range: [{unitsRange.From}, {unitsRange.To}], paid units: {paidUnits}");
            }
            if (receiptRequest.ReceiptsToMerge.Any())
            {
                if (_logger.IsInfo)
                {
                    _logger.Info($"Processing a merged receipt request for consumer: {session.ConsumerAddress}, session: '{session.Id} - units will not be updated.");
                }
            }
            else
            {
                if (_logger.IsInfo)
                {
                    _logger.Info($"Processing a receipt request for deposit: '{receiptRequest.DepositId}', consumer: {session.ConsumerAddress}, session: '{session.Id} - units will be updated.");
                }
                var unpaidUnits = session.UnpaidUnits > paidUnits ? session.UnpaidUnits - paidUnits : 0;
                session.SetUnpaidUnits(unpaidUnits);
                session.AddPaidUnits(paidUnits);
                if (receiptRequest.IsSettlement)
                {
                    session.SetPaidUnits(paidUnits);
                    session.SettleUnits(paidUnits);
                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Settled {paidUnits} units for deposit: '{receiptRequest.DepositId}', consumer: {session.ConsumerAddress}, session: '{session.Id}'.");
                    }
                }

                await _sessionRepository.UpdateAsync(session);
            }

            var dataAvailability = session.DataAvailability;

            if (dataAvailability == DataAvailability.DataDeliveryReceiptInvalid ||
                dataAvailability == DataAvailability.DataDeliveryReceiptNotProvided)
            {
                session.SetDataAvailability(DataAvailability.Available);
                await _sessionRepository.UpdateAsync(session);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Updated previously set data availability: '{dataAvailability}' -> '{DataAvailability.Available}', consumer: {session.ConsumerAddress}, session: '{session.Id}'.");
                }
            }

            return(true);
        }
Exemple #2
0
        private async Task <DataDeliveryReceiptDetails?> TryHandleReceiptAsync(ProviderSession session, Address consumer,
                                                                               INdmProviderPeer peer, DataDeliveryReceiptRequest request)
        {
            Keccak depositId             = session.DepositId;
            IDepositNodesHandler?deposit = GetDepositNodesHandler(depositId);

            if (deposit == null)
            {
                throw new InvalidDataException($"Cannot resolve deposit handle for deposit ID: {depositId}");
            }

            try
            {
                UnitsRange unitsRange = request.UnitsRange;
                if (_logger.IsInfo)
                {
                    _logger.Info($"Sending data delivery receipt request ({request.Number}), deposit: '{depositId}', session: '{session.Id}', range: [{unitsRange.From}, {unitsRange.To}].");
                }
                if (request.ReceiptsToMerge.Any())
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Receipts to merge for deposit: '{depositId}': {string.Join(", ", request.ReceiptsToMerge.Select(r => $"[{r.UnitsRange.From}, {r.UnitsRange.To}]"))}");
                    }
                }

                (DataDeliveryReceipt receipt, RequestReceiptStatus status) = await TryHandleDeliveryReceipt(deposit, consumer, session, request, peer);

                Keccak id = Keccak.Compute(Rlp.Encode(Rlp.Encode(depositId), Rlp.Encode(request.Number)).Bytes);
                DataDeliveryReceiptDetails receiptDetails = new DataDeliveryReceiptDetails(id, session.Id, session.DataAssetId, peer.NodeId,
                                                                                           request, receipt, _timestamper.UnixTime.Seconds, false);
                await _receiptRepository.AddAsync(receiptDetails);

                if (status != RequestReceiptStatus.Ok)
                {
                    return(null);
                }

                UnitsRange range        = request.UnitsRange;
                uint       claimedUnits = range.To - range.From + 1;
                deposit.AddReceipt(receiptDetails);
                if (!request.ReceiptsToMerge.Any())
                {
                    deposit.SubtractUnpaidUnits(claimedUnits);
                }

                if (_logger.IsInfo)
                {
                    _logger.Info($"Successfully processed receipt ({claimedUnits} units) for deposit: '{depositId}' with node: '{peer.NodeId}'.");
                }

                return(receiptDetails);
            }
            catch (Exception ex)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"There was an error when processing a receipt for deposit: '{depositId}'. {ex}");
                }
                session.SetDataAvailability(DataAvailability.DataDeliveryReceiptNotProvided);
                await _sessionRepository.UpdateAsync(session);

                peer.SendDataAvailability(depositId, DataAvailability.DataDeliveryReceiptInvalid);

                return(null);
            }
        }