public async Task SetUnitsAsync(Keccak depositId, uint consumedUnitsFromProvider) { var(session, deposit) = await TryGetSessionAndDepositAsync(depositId); if (session is null || deposit is null) { return; } session.SetConsumedUnitsFromProvider(consumedUnitsFromProvider); switch (deposit.DataAsset.UnitType) { case DataAssetUnitType.Time: var now = (uint)_timestamper.EpochSeconds; var currentlyConsumedUnits = now - deposit.ConfirmationTimestamp; var currentlyUnpaidUnits = currentlyConsumedUnits > session.PaidUnits ? currentlyConsumedUnits - session.PaidUnits : 0; session.SetConsumedUnits((uint)(now - session.StartTimestamp)); session.SetUnpaidUnits(currentlyUnpaidUnits); break; case DataAssetUnitType.Unit: session.IncrementConsumedUnits(); session.IncrementUnpaidUnits(); Metrics.ConsumedUnits++; break; } var consumedUnits = session.ConsumedUnits; var unpaidUnits = session.UnpaidUnits; if (_logger.IsTrace) { _logger.Trace($"Setting units, consumed: [provider: {consumedUnitsFromProvider}, consumer: {consumedUnits}], unpaid: {unpaidUnits}, paid: {session.PaidUnits}, for deposit: '{depositId}', session: '{session.Id}'."); } if (consumedUnitsFromProvider > consumedUnits) { var unitsDifference = consumedUnitsFromProvider - consumedUnits; if (_logger.IsTrace) { _logger.Trace($"Provider has counted more consumed units ({unitsDifference}) for deposit: '{depositId}', session: '{session.Id}'"); } } else if (consumedUnitsFromProvider < consumedUnits) { var unitsDifference = consumedUnits - consumedUnitsFromProvider; if (_logger.IsTrace) { _logger.Trace($"Provider has counted less consumed units ({unitsDifference}) for deposit: '{depositId}', session: '{session.Id}'."); } //Adjust units? // session.SubtractUnpaidUnits(unpaidUnits); // session.SubtractUnpaidUnits(unitsDifference); } await _sessionRepository.UpdateAsync(session); }
public async Task SetEnabledDataStreamAsync(Keccak depositId, string client, string[] args) { ConsumerSession?session = _sessionService.GetActive(depositId); if (session is null) { return; } session.EnableStream(client, args); await _sessionRepository.UpdateAsync(session); await _consumerNotifier.SendDataStreamEnabledAsync(depositId, session.Id); if (_logger.IsInfo) { _logger.Info($"Enabled data stream for deposit: '{depositId}', client: '{client}', session: '{session.Id}'.'"); } }
public async Task FinishSessionAsync(Session session, INdmPeer provider, bool removePeer = true) { if (removePeer) { _providerService.Remove(provider.NodeId); } if (provider.ProviderAddress is null) { if (_logger.IsWarn) { _logger.Warn($"Provider node: '{provider.NodeId}' has no address assigned."); } return; } var depositId = session.DepositId; var consumerSession = GetActive(depositId); if (consumerSession is null) { return; } _sessions.TryRemove(session.DepositId, out _); var timestamp = session.FinishTimestamp; consumerSession.Finish(session.State, timestamp); await _sessionRepository.UpdateAsync(consumerSession); await _consumerNotifier.SendSessionFinishedAsync(session.DepositId, session.Id); if (_logger.IsInfo) { _logger.Info($"Finished a session: '{session.Id}' for deposit: '{depositId}', provider: '{provider.ProviderAddress}', state: '{session.State}', timestamp: {timestamp}."); } }
public async Task SendAsync(DataDeliveryReceiptRequest request, int fetchSessionRetries = 3, int fetchSessionRetryDelayMilliseconds = 3000) { var depositId = request.DepositId; var(deposit, session) = await TryGetDepositAndSessionAsync(depositId, fetchSessionRetries, fetchSessionRetryDelayMilliseconds); if (deposit is null || session is null) { return; } var providerAddress = deposit.DataAsset.Provider.Address; var providerPeer = _providerService.GetPeer(providerAddress); if (providerPeer is null) { if (_logger.IsWarn) { _logger.Warn($"Provider: '{providerAddress}' was not found."); } return; } var receiptId = Keccak.Compute(Rlp.Encode(Rlp.Encode(depositId), Rlp.Encode(request.Number), Rlp.Encode(_timestamper.EpochSeconds))); if (!_receiptRequestValidator.IsValid(request, session.UnpaidUnits, session.ConsumedUnits, deposit.Deposit.Units)) { if (_logger.IsWarn) { _logger.Warn($"Provider: '{providerPeer.NodeId}' sent an invalid data delivery receipt request."); } var receipt = new DataDeliveryReceipt(StatusCodes.InvalidReceiptRequestRange, session.ConsumedUnits, session.UnpaidUnits, new Signature(1, 1, 27)); await _receiptRepository.AddAsync(new DataDeliveryReceiptDetails(receiptId, session.Id, session.DataAssetId, _nodePublicKey, request, receipt, _timestamper.EpochSeconds, false)); await _sessionRepository.UpdateAsync(session); providerPeer.SendDataDeliveryReceipt(depositId, receipt); return; } var abiHash = _abiEncoder.Encode(AbiEncodingStyle.Packed, _dataDeliveryReceiptAbiSig, depositId.Bytes, new[] { request.UnitsRange.From, request.UnitsRange.To }); var receiptHash = Keccak.Compute(abiHash); var signature = _wallet.Sign(receiptHash, deposit.Consumer); var recoveredAddress = _ecdsa.RecoverPublicKey(signature, receiptHash)?.Address; if (deposit.Consumer != recoveredAddress) { if (_logger.IsError) { _logger.Error($"Signature failure when signing the receipt from provider: '{providerPeer.NodeId}', invalid recovered address."); } var receipt = new DataDeliveryReceipt(StatusCodes.InvalidReceiptAddress, session.ConsumedUnits, session.UnpaidUnits, new Signature(1, 1, 27)); await _receiptRepository.AddAsync(new DataDeliveryReceiptDetails(receiptId, session.Id, session.DataAssetId, _nodePublicKey, request, receipt, _timestamper.EpochSeconds, false)); await _sessionRepository.UpdateAsync(session); providerPeer.SendDataDeliveryReceipt(depositId, receipt); return; } if (_logger.IsInfo) { _logger.Info($"Provider: '{providerPeer.NodeId}' sent a valid data delivery receipt request."); } if (request.ReceiptsToMerge.Any()) { if (_logger.IsInfo) { _logger.Info($"Processing a merged receipt request for deposit: {session.DepositId}, session: '{session.Id} - units will not be updated."); } } else { var paidUnits = request.UnitsRange.To - request.UnitsRange.From + 1; var unpaidUnits = session.UnpaidUnits > paidUnits ? session.UnpaidUnits - paidUnits : 0; session.SetUnpaidUnits(unpaidUnits); session.AddPaidUnits(paidUnits); if (request.IsSettlement) { session.SetPaidUnits(paidUnits); session.SettleUnits(paidUnits); if (_logger.IsInfo) { _logger.Info($"Settled {paidUnits} units for deposit: '{session.DepositId}', session: '{session.Id}'."); } } await _sessionRepository.UpdateAsync(session); } if (_logger.IsInfo) { _logger.Info($"Sending data delivery receipt for deposit: '{depositId}', range: [{request.UnitsRange.From}, {request.UnitsRange.To}]."); } var deliveryReceipt = new DataDeliveryReceipt(StatusCodes.Ok, session.ConsumedUnits, session.UnpaidUnits, signature); await _receiptRepository.AddAsync(new DataDeliveryReceiptDetails(receiptId, session.Id, session.DataAssetId, _nodePublicKey, request, deliveryReceipt, _timestamper.EpochSeconds, false)); providerPeer.SendDataDeliveryReceipt(depositId, deliveryReceipt); if (_logger.IsInfo) { _logger.Info($"Sent data delivery receipt for deposit: '{depositId}', range: [{request.UnitsRange.From}, {request.UnitsRange.To}]."); } }