Beispiel #1
0
        public async Task should_return_0_consumed_units_for_confirmed_deposit_without_any_sessions_and_unit_unit_type()
        {
            var deposit = GetDepositDetails();

            _sessionRepository.BrowseAsync(Arg.Any <GetConsumerSessions>()).Returns(PagedResult <ConsumerSession> .Empty);

            var consumedUnits = await _calculator.GetConsumedAsync(deposit);

            consumedUnits.Should().Be(0);
            await _sessionRepository.Received(1).BrowseAsync(Arg.Any <GetConsumerSessions>());
        }
        public async Task send_data_request_should_succeed_for_valid_deposit()
        {
            var depositId = Keccak.Zero;
            var deposit   = GetDepositDetails(DepositConfirmationTimestamp, DepositExpiryTime);

            _depositProvider.GetAsync(depositId).Returns(deposit);
            _wallet.IsUnlocked(deposit.Consumer).Returns(true);
            var provider = Substitute.For <INdmPeer>();

            _providerService.GetPeer(deposit.DataAsset.Provider.Address).Returns(provider);
            var sessions = new List <ConsumerSession>
            {
                GetConsumerSession()
            };
            var dataRequest = new DataRequest(Keccak.OfAnEmptyString, 1, 1, 1, Array.Empty <byte>(), Address.Zero,
                                              Address.Zero, null);
            var sessionsPagedResult = PagedResult <ConsumerSession> .Create(sessions, 1, 1, 1, 1);

            _sessionRepository.BrowseAsync(Arg.Any <GetConsumerSessions>()).Returns(sessionsPagedResult);
            _dataRequestFactory.Create(deposit.Deposit, deposit.DataAsset.Id, deposit.DataAsset.Provider.Address,
                                       deposit.Consumer, deposit.Pepper).Returns(dataRequest);
            var consumedUnits = (uint)sessions.Sum(s => s.ConsumedUnits);

            provider.SendDataRequestAsync(dataRequest, consumedUnits).Returns(DataRequestResult.DepositVerified);

            var result = await _dataRequestService.SendAsync(depositId);

            result.Should().Be(DataRequestResult.DepositVerified);
            await _depositProvider.Received(1).GetAsync(depositId);

            _wallet.Received(1).IsUnlocked(deposit.Consumer);
            await _kycVerifier.DidNotReceive().IsVerifiedAsync(deposit.DataAsset.Id, deposit.Consumer);

            _providerService.Received(1).GetPeer(deposit.DataAsset.Provider.Address);
            await _sessionRepository.Received(1).BrowseAsync(Arg.Any <GetConsumerSessions>());

            _dataRequestFactory.Received(1).Create(deposit.Deposit, deposit.DataAsset.Id,
                                                   deposit.DataAsset.Provider.Address, deposit.Consumer, deposit.Pepper);
            await provider.Received(1).SendDataRequestAsync(dataRequest, consumedUnits);

            await _consumerNotifier.Received(1).SendDataRequestResultAsync(depositId, result);
        }
Beispiel #3
0
        public async Task <uint> GetConsumedAsync(DepositDetails deposit)
        {
            if (!deposit.Confirmed)
            {
                return(0);
            }

            if (deposit.DataAsset.UnitType == DataAssetUnitType.Time)
            {
                return((uint)_timestamper.EpochSeconds - deposit.ConfirmationTimestamp);
            }

            var sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
            {
                DepositId = deposit.Id,
                Results   = int.MaxValue
            });

            return(sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0);
        }
Beispiel #4
0
        public async Task <DepositsReport> GetAsync(GetDepositsReport query)
        {
            var deposits = query.DepositId is null
                ? await _depositRepository.BrowseAsync(new GetDeposits
            {
                Results = int.MaxValue
            })
                : PagedResult <DepositDetails> .Create(new[] { await _depositRepository.GetAsync(query.DepositId) },
                                                       1, 1, 1, 1);

            if (!deposits.Items.Any() || deposits.Items.Any(d => d is null))
            {
                return(DepositsReport.Empty);
            }

            var foundDeposits = deposits.Items
                                .Where(d => (query.Provider is null || d.DataAsset.Provider.Address == query.Provider) &&
                                       (query.AssetId is null || d.DataAsset.Id == query.AssetId))
                                .ToDictionary(d => d.Id, d => d);

            if (!foundDeposits.Any())
            {
                return(DepositsReport.Empty);
            }

            var assetIds = foundDeposits.Select(d => d.Value.DataAsset.Id);
            var receipts = await _receiptRepository.BrowseAsync(query.DepositId, query.AssetId);

            var depositsReceipts = receipts.Where(r => assetIds.Contains(r.DataAssetId))
                                   .GroupBy(r => r.DepositId).ToDictionary(r => r.Key, r => r.AsEnumerable());

            var page = query.Page;

            if (page <= 0)
            {
                page = 1;
            }

            var results = query.Results;

            if (results <= 0)
            {
                results = 10;
            }

            var timestamp = (uint)_timestamper.EpochSeconds;
            var skip      = (page - 1) * results;
            var items     = new List <DepositReportItem>();

            foreach (var(_, deposit) in foundDeposits.OrderByDescending(d => d.Value.Timestamp).Skip(skip)
                     .Take(results))
            {
                depositsReceipts.TryGetValue(deposit.Id, out var depositReceipts);
                var expired      = deposit.IsExpired(timestamp);
                var receiptItems = depositReceipts?.Select(r => new DataDeliveryReceiptReportItem(r.Id, r.Number,
                                                                                                  r.SessionId, r.ConsumerNodeId, r.Request, r.Receipt, r.Timestamp, r.IsMerged, r.IsClaimed));
                var sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
                {
                    DepositId = deposit.Id,
                    Results   = int.MaxValue
                });

                var consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;
                items.Add(new DepositReportItem(deposit.Id, deposit.DataAsset.Id, deposit.DataAsset.Name,
                                                deposit.DataAsset.Provider.Address, deposit.DataAsset.Provider.Name, deposit.Deposit.Value,
                                                deposit.Deposit.Units, deposit.Consumer, deposit.Timestamp, deposit.Deposit.ExpiryTime, expired,
                                                deposit.Transaction?.Hash, deposit.ConfirmationTimestamp, deposit.Confirmations,
                                                deposit.RequiredConfirmations, deposit.Confirmed, deposit.Rejected,
                                                deposit.ClaimedRefundTransaction?.Hash, deposit.RefundClaimed, consumedUnits, receiptItems));
            }

            var(total, claimed, refunded) = CalculateValues(foundDeposits, depositsReceipts);
            var totalResults = foundDeposits.Count;
            var totalPages   = (int)Math.Ceiling((double)totalResults / query.Results);

            return(new DepositsReport(total, claimed, refunded,
                                      PagedResult <DepositReportItem> .Create(items.OrderByDescending(i => i.Timestamp).ToList(),
                                                                              query.Page, query.Results, totalPages, totalResults)));
        }
Beispiel #5
0
        public async Task <DataRequestResult> SendAsync(Keccak depositId)
        {
            var deposit = await _depositProvider.GetAsync(depositId);

            if (deposit is null)
            {
                return(DataRequestResult.DepositNotFound);
            }

            if (!_wallet.IsUnlocked(deposit.Consumer))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Account: '{deposit.Consumer}' is locked, can't send a data request.");
                }

                return(DataRequestResult.ConsumerAccountLocked);
            }

            if (deposit.DataAsset.KycRequired &&
                !(await _kycVerifier.IsVerifiedAsync(deposit.DataAsset.Id, deposit.Consumer)))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' has unconfirmed KYC.'");
                }

                return(DataRequestResult.KycUnconfirmed);
            }

            if (!deposit.Confirmed)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' is unconfirmed.'");
                }

                return(DataRequestResult.DepositUnconfirmed);
            }

            if (deposit.IsExpired((uint)_timestamper.EpochSeconds))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Deposit with id: '{depositId}' is expired.'");
                }

                return(DataRequestResult.DepositExpired);
            }

            var providerPeer = _providerService.GetPeer(deposit.DataAsset.Provider.Address);

            if (providerPeer is null)
            {
                return(DataRequestResult.ProviderNotFound);
            }

            var sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
            {
                DepositId = depositId,
                Results   = int.MaxValue
            });

            var consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;
            var dataRequest   = CreateDataRequest(deposit);

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending data request for deposit with id: '{depositId}', consumed units: {consumedUnits}, address: '{dataRequest.Consumer}'.");
            }
            var result = await providerPeer.SendDataRequestAsync(dataRequest, consumedUnits);

            if (_logger.IsInfo)
            {
                _logger.Info($"Received data request result: '{result}' for data asset: '{dataRequest.DataAssetId}', deposit: '{depositId}', consumed units: {consumedUnits}, address: '{dataRequest.Consumer}'.");
            }
            await _consumerNotifier.SendDataRequestResultAsync(depositId, result);

            return(result);
        }
Beispiel #6
0
        public async Task StartSessionAsync(Session session, INdmPeer provider)
        {
//            var providerPeer = _providerService.GetPeer(provider.ProviderAddress);
//            if (!_providers.TryGetValue(provider.NodeId, out var providerPeer))
//            {
//                if (_logger.IsWarn) _logger.Warn($"Cannot start the session: '{session.Id}', provider: '{provider.NodeId}' was not found.");
//
//                return;
//            }

            var deposit = await _depositProvider.GetAsync(session.DepositId);

            if (deposit is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Cannot start the session: '{session.Id}', deposit: '{session.DepositId}' was not found.");
                }

                return;
            }

            var dataAssetId = deposit.DataAsset.Id;
            var dataAsset   = _dataAssetService.GetDiscovered(dataAssetId);

            if (dataAsset is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Available data asset: '{dataAssetId}' was not found.");
                }

                return;
            }

            if (!_dataAssetService.IsAvailable(dataAsset))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Data asset: '{dataAssetId}' is unavailable, state: {dataAsset.State}.");
                }

                return;
            }

            if (!provider.ProviderAddress.Equals(deposit.DataAsset.Provider.Address))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Cannot start the session: '{session.Id}' for deposit: '{session.DepositId}', provider address (peer): '{provider.ProviderAddress}' doesn't equal the address from data asset: '{deposit.DataAsset.Provider.Address}'.");
                }

                return;
            }

            var sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
            {
                DepositId = session.DepositId,
                Results   = int.MaxValue
            });

            var consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;

            if (_logger.IsInfo)
            {
                _logger.Info($"Starting the session: '{session.Id}' for deposit: '{session.DepositId}'. Settings consumed units - provider: {session.StartUnitsFromProvider}, consumer: {consumedUnits}.");
            }
            var consumerSession = ConsumerSession.From(session);

            consumerSession.Start(session.StartTimestamp);
            var previousSession = await _sessionRepository.GetPreviousAsync(consumerSession);

            var upfrontUnits = (uint)(deposit.DataAsset.Rules.UpfrontPayment?.Value ?? 0);

            if (upfrontUnits > 0 && previousSession is null)
            {
                consumerSession.AddUnpaidUnits(upfrontUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: {upfrontUnits} for session: '{session.Id}' based on upfront payment.");
                }
            }

            var unpaidUnits = previousSession?.UnpaidUnits ?? 0;

            if (unpaidUnits > 0 && !(previousSession is null))
            {
                consumerSession.AddUnpaidUnits(unpaidUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: {unpaidUnits} for session: '{session.Id}' from previous session: '{previousSession.Id}'.");
                }
            }

            if (deposit.DataAsset.UnitType == DataAssetUnitType.Time)
            {
                var unpaidTimeUnits = (uint)consumerSession.StartTimestamp - deposit.ConfirmationTimestamp;
                consumerSession.AddUnpaidUnits(unpaidTimeUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: '{unpaidTimeUnits}' for deposit: '{session.DepositId}' based on time.");
                }
            }

            SetActiveSession(consumerSession);
            await _sessionRepository.AddAsync(consumerSession);

            await _consumerNotifier.SendSessionStartedAsync(session.DepositId, session.Id);

            if (_logger.IsInfo)
            {
                _logger.Info($"Started a session with id: '{session.Id}' for deposit: '{session.DepositId}', address: '{deposit.Consumer}'.");
            }
        }
Beispiel #7
0
        public async Task StartSessionAsync(Session session, INdmPeer provider)
        {
            DepositDetails?deposit = await _depositProvider.GetAsync(session.DepositId);

            if (deposit is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Cannot start the session: '{session.Id}', deposit: '{session.DepositId}' was not found.");
                }
                return;
            }

            if (session.StartTimestamp < deposit.ConfirmationTimestamp)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Cannot start the session: '{session.Id}', session timestamp {session.StartTimestamp} is before deposit confirmation timestamp {deposit.ConfirmationTimestamp}.");
                }
                return;
            }

            Keccak dataAssetId = deposit.DataAsset.Id;

            if (dataAssetId != session.DataAssetId)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Inconsistent data - data asset ID on deposit is '{dataAssetId}' while on session is '{session.DataAssetId}'.");
                }
                return;
            }

            DataAsset?dataAsset = _dataAssetService.GetDiscovered(dataAssetId);

            if (dataAsset is null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Available data asset: '{dataAssetId}' was not found.");
                }
                return;
            }

            if (!_dataAssetService.IsAvailable(dataAsset))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Data asset: '{dataAssetId}' is unavailable, state: {dataAsset.State}.");
                }
                return;
            }

            if (session.ProviderAddress == null)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Session: '{session.Id}' for '{session.DepositId}' cannot be started because of the unknown provider address.");
                }
                return;
            }

            if (!provider.ProviderAddress !.Equals(deposit.DataAsset.Provider.Address))
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn($"Cannot start the session: '{session.Id}' for deposit: '{session.DepositId}', provider address (peer): '{provider.ProviderAddress}' doesn't equal the address from data asset: '{deposit.DataAsset.Provider.Address}'.");
                }
                return;
            }

            PagedResult <ConsumerSession> sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
            {
                DepositId = session.DepositId,
                Results   = int.MaxValue
            });

            uint consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;

            if (_logger.IsInfo)
            {
                _logger.Info($"Starting the session: '{session.Id}' for deposit: '{session.DepositId}'. Settings consumed units - provider: {session.StartUnitsFromProvider}, consumer: {consumedUnits}.");
            }
            ConsumerSession consumerSession = ConsumerSession.From(session);

            consumerSession.Start(session.StartTimestamp);
            ConsumerSession?previousSession = await _sessionRepository.GetPreviousAsync(consumerSession);

            uint upfrontUnits = (uint)(deposit.DataAsset.Rules.UpfrontPayment?.Value ?? 0);

            if (upfrontUnits > 0 && previousSession is null)
            {
                consumerSession.AddUnpaidUnits(upfrontUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: {upfrontUnits} for session: '{session.Id}' based on upfront payment.");
                }
            }

            uint unpaidUnits = previousSession?.UnpaidUnits ?? 0;

            if (unpaidUnits > 0 && !(previousSession is null))
            {
                consumerSession.AddUnpaidUnits(unpaidUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: {unpaidUnits} for session: '{session.Id}' from previous session: '{previousSession.Id}'.");
                }
            }

            if (deposit.DataAsset.UnitType == DataAssetUnitType.Time)
            {
                uint unpaidTimeUnits = (uint)consumerSession.StartTimestamp - deposit.ConfirmationTimestamp;
                consumerSession.AddUnpaidUnits(unpaidTimeUnits);
                if (_logger.IsInfo)
                {
                    _logger.Info($"Unpaid units: '{unpaidTimeUnits}' for deposit: '{session.DepositId}' based on time.");
                }
            }

            SetActiveSession(consumerSession);
            await _sessionRepository.AddAsync(consumerSession);

            await _consumerNotifier.SendSessionStartedAsync(session.DepositId, session.Id);

            if (_logger.IsInfo)
            {
                _logger.Info($"Started a session with id: '{session.Id}' for deposit: '{session.DepositId}', address: '{deposit.Consumer}'.");
            }
        }
Beispiel #8
0
        public async Task <DepositsReport> GetAsync(GetDepositsReport query)
        {
            PagedResult <DepositDetails> deposits;

            if (query.DepositId == null)
            {
                deposits =
                    await _depositRepository.BrowseAsync(new GetDeposits
                {
                    Results = int.MaxValue
                });
            }
            else
            {
                DepositDetails?detailsOfOne = await _depositRepository.GetAsync(query.DepositId);

                if (detailsOfOne is null)
                {
                    return(DepositsReport.Empty);
                }

                deposits = PagedResult <DepositDetails> .Create(new[] { detailsOfOne },
                                                                1, 1, 1, 1);
            }

            if (deposits.Items.Count == 0)
            {
                return(DepositsReport.Empty);
            }

            if (!deposits.Items.Any() || deposits.Items.Any(d => d is null))
            {
                return(DepositsReport.Empty);
            }

            Dictionary <Keccak, DepositDetails> foundDeposits = deposits.Items
                                                                .Where(d => (query.Provider is null || d.DataAsset.Provider.Address == query.Provider) &&
                                                                       (query.AssetId is null || d.DataAsset.Id == query.AssetId))
                                                                .ToDictionary(d => d.Id, d => d);

            if (!foundDeposits.Any())
            {
                return(DepositsReport.Empty);
            }

            IEnumerable <Keccak> assetIds = foundDeposits.Select(d => d.Value.DataAsset.Id);
            IReadOnlyList <DataDeliveryReceiptDetails> receipts = await _receiptRepository.BrowseAsync(query.DepositId, query.AssetId);

            Dictionary <Keccak, IEnumerable <DataDeliveryReceiptDetails> > depositsReceipts = receipts.Where(r => assetIds.Contains(r.DataAssetId))
                                                                                              .GroupBy(r => r.DepositId).ToDictionary(r => r.Key, r => r.AsEnumerable());

            int page = query.Page;

            if (page <= 0)
            {
                page = 1;
            }

            int results = query.Results;

            if (results <= 0)
            {
                results = 10;
            }

            uint timestamp = (uint)_timestamper.EpochSeconds;
            int  skip      = (page - 1) * results;
            List <DepositReportItem> items = new List <DepositReportItem>();

            foreach ((Keccak _, DepositDetails deposit) in foundDeposits.OrderByDescending(d => d.Value.Timestamp).Skip(skip)
                     .Take(results))
            {
                depositsReceipts.TryGetValue(deposit.Id, out IEnumerable <DataDeliveryReceiptDetails>?depositReceipts);
                bool expired = deposit.IsExpired(timestamp);
                IEnumerable <DataDeliveryReceiptReportItem>?receiptItems = depositReceipts?.Select(r => new DataDeliveryReceiptReportItem(r.Id, r.Number,
                                                                                                                                          r.SessionId, r.ConsumerNodeId, r.Request, r.Receipt, r.Timestamp, r.IsMerged, r.IsClaimed));
                PagedResult <ConsumerSession> sessions = await _sessionRepository.BrowseAsync(new GetConsumerSessions
                {
                    DepositId = deposit.Id,
                    Results   = int.MaxValue
                });

                uint consumedUnits = sessions.Items.Any() ? (uint)sessions.Items.Sum(s => s.ConsumedUnits) : 0;
                items.Add(ToReportItem(deposit, expired, consumedUnits, receiptItems ?? Enumerable.Empty <DataDeliveryReceiptReportItem>()));
            }

            (UInt256 total, UInt256 claimed, UInt256 refunded) = CalculateValues(foundDeposits, depositsReceipts);
            int totalResults = foundDeposits.Count;
            int totalPages   = (int)Math.Ceiling((double)totalResults / query.Results);

            return(new DepositsReport(total, claimed, refunded,
                                      PagedResult <DepositReportItem> .Create(items.OrderByDescending(i => i.Timestamp).ToList(),
                                                                              query.Page, query.Results, totalPages, totalResults)));
        }