public async Task FinishSessionsAsync(INdmProviderPeer peer, bool removePeer = true) { if (!Nodes.TryGetValue(peer.NodeId, out var node)) { if (_logger.IsInfo) { _logger.Info($"No sessions to be finished found for node: '{peer.NodeId}'."); } return; } if (_logger.IsInfo) { _logger.Info($"Finishing session(s) for node: '{peer.NodeId}'."); } var timestamp = _timestamper.UnixTime.Seconds; foreach (var session in node.Sessions) { if (_logger.IsInfo) { _logger.Info($"Finishing a session: '{session.Id}' for deposit: '{session.DepositId}', node: '{peer.NodeId}'."); } session.Finish(SessionState.ConsumerDisconnected, timestamp); await _sessionRepository.UpdateAsync(session); node.RemoveSession(session.DepositId); if (removePeer) { TryRemoveDepositNode(session.DepositId, peer); } if (_logger.IsInfo) { _logger.Info($"Finished a session: '{session.Id}' for deposit: '{session.DepositId}', node: '{peer.NodeId}', timestamp: {timestamp}."); } } if (!removePeer) { return; } TryRemovePeer(node, peer); }
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); }
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); } }