Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move pending and completed withdrawal stats to CCTS #360

Merged
merged 3 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public FederationWalletControllerTests()
this.withdrawalHistoryProvider = Substitute.For<IWithdrawalHistoryProvider>();

this.controller = new FederationWalletController(this.loggerFactory, this.walletManager, this.walletSyncManager,
this.connectionManager, this.network, this.chainIndexer, this.dateTimeProvider, this.withdrawalHistoryProvider);
this.connectionManager, this.network, this.chainIndexer, Substitute.For<ICrossChainTransferStore>());

this.fedWallet = new FederationWallet
{
Expand Down Expand Up @@ -106,7 +106,7 @@ public void GetHistory()
{
var withdrawals = new List<WithdrawalModel>() { new WithdrawalModel(), new WithdrawalModel() };

this.withdrawalHistoryProvider.GetHistory(0).ReturnsForAnyArgs(withdrawals);
this.withdrawalHistoryProvider.GetHistory(new[] { new CrossChainTransfer() }, 0).ReturnsForAnyArgs(withdrawals);

IActionResult result = this.controller.GetHistory(5);
List<WithdrawalModel> model = this.ActionResultToModel<List<WithdrawalModel>>(result);
Expand Down Expand Up @@ -141,8 +141,10 @@ public void EnableFederation()
[Fact]
public void RemoveTransactions()
{
var hashSet = new HashSet<(uint256, DateTimeOffset)>();
hashSet.Add((uint256.One, DateTimeOffset.MinValue));
var hashSet = new HashSet<(uint256, DateTimeOffset)>
{
(uint256.One, DateTimeOffset.MinValue)
};

this.walletManager.RemoveAllTransactions().Returns(info => hashSet);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ protected void Init(DataFolder dataFolder)
protected ICrossChainTransferStore CreateStore()
{
return new CrossChainTransferStore(this.network, Substitute.For<INodeStats>(), this.dataFolder, this.ChainIndexer, this.federatedPegSettings, this.dateTimeProvider,
this.loggerFactory, this.withdrawalExtractor, this.blockRepository, this.federationWalletManager, this.withdrawalTransactionBuilder, this.dBreezeSerializer, this.signals, this.stateRepositoryRoot);
this.loggerFactory, this.withdrawalExtractor, Substitute.For<IWithdrawalHistoryProvider>(), this.blockRepository, this.federationWalletManager, this.withdrawalTransactionBuilder, this.dBreezeSerializer, this.signals, this.stateRepositoryRoot);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using Stratis.Bitcoin.Utilities.ModelStateErrors;
using Stratis.Features.FederatedPeg.Interfaces;
using Stratis.Features.FederatedPeg.Models;
using Stratis.Features.FederatedPeg.TargetChain;
using Stratis.Features.FederatedPeg.Wallet;

namespace Stratis.Features.FederatedPeg.Controllers
Expand All @@ -37,18 +36,13 @@ public static class FederationWalletRouteEndPoint
[Route("api/[controller]")]
public class FederationWalletController : Controller
{
private readonly ICrossChainTransferStore crossChainTransferStore;
private readonly IFederationWalletManager federationWalletManager;

private readonly Network network;
private readonly IFederationWalletSyncManager walletSyncManager;

private readonly CoinType coinType;

private readonly IConnectionManager connectionManager;

private readonly ChainIndexer chainIndexer;

private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider;

/// <summary>Instance logger.</summary>
private readonly ILogger logger;

Expand All @@ -59,16 +53,15 @@ public class FederationWalletController : Controller
IConnectionManager connectionManager,
Network network,
ChainIndexer chainIndexer,
IDateTimeProvider dateTimeProvider,
IWithdrawalHistoryProvider withdrawalHistoryProvider)
ICrossChainTransferStore crossChainTransferStore)
{
this.federationWalletManager = walletManager;
this.walletSyncManager = walletSyncManager;
this.connectionManager = connectionManager;
this.withdrawalHistoryProvider = withdrawalHistoryProvider;
this.coinType = (CoinType)network.Consensus.CoinType;
this.crossChainTransferStore = crossChainTransferStore;
this.chainIndexer = chainIndexer;
this.federationWalletManager = walletManager;
this.network = network;
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
this.walletSyncManager = walletSyncManager;
}

/// <summary>
Expand Down Expand Up @@ -136,13 +129,13 @@ public IActionResult GetBalance()
return this.NotFound("No federation wallet found.");
}

(Money ConfirmedAmount, Money UnConfirmedAmount) result = this.federationWalletManager.GetSpendableAmount();
(Money ConfirmedAmount, Money UnConfirmedAmount) = this.federationWalletManager.GetSpendableAmount();

var balance = new AccountBalanceModel
{
CoinType = this.coinType,
AmountConfirmed = result.ConfirmedAmount,
AmountUnconfirmed = result.UnConfirmedAmount,
CoinType = (CoinType)this.network.Consensus.CoinType,
AmountConfirmed = ConfirmedAmount,
AmountUnconfirmed = UnConfirmedAmount,
};

var model = new WalletBalanceModel();
Expand Down Expand Up @@ -175,11 +168,9 @@ public IActionResult GetHistory([FromQuery] int maxEntriesToReturn)
{
FederationWallet wallet = this.federationWalletManager.GetWallet();
if (wallet == null)
{
return this.NotFound("No federation wallet found.");
}

List<WithdrawalModel> result = this.withdrawalHistoryProvider.GetHistory(maxEntriesToReturn);
List<WithdrawalModel> result = this.crossChainTransferStore.GetCompletedWithdrawals(maxEntriesToReturn);

return this.Json(result);
}
Expand Down Expand Up @@ -235,7 +226,7 @@ public IActionResult Sync([FromBody] HashModel model)
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
public IActionResult EnableFederation([FromBody]EnableFederationRequest request)
public IActionResult EnableFederation([FromBody] EnableFederationRequest request)
{
Guard.NotNull(request, nameof(request));

Expand Down Expand Up @@ -282,7 +273,7 @@ public IActionResult EnableFederation([FromBody]EnableFederationRequest request)
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
public IActionResult RemoveTransactions([FromQuery]RemoveFederationTransactionsModel request)
public IActionResult RemoveTransactions([FromQuery] RemoveFederationTransactionsModel request)
{
Guard.NotNull(request, nameof(request));

Expand Down
52 changes: 0 additions & 52 deletions src/Stratis.Features.FederatedPeg/FederatedPegFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
using Stratis.Features.FederatedPeg.Distribution;
using Stratis.Features.FederatedPeg.InputConsolidation;
using Stratis.Features.FederatedPeg.Interfaces;
using Stratis.Features.FederatedPeg.Models;
using Stratis.Features.FederatedPeg.Notifications;
using Stratis.Features.FederatedPeg.Payloads;
using Stratis.Features.FederatedPeg.SourceChain;
Expand All @@ -40,16 +39,6 @@ namespace Stratis.Features.FederatedPeg
{
internal class FederatedPegFeature : FullNodeFeature
{
/// <summary>
/// Given that we can have up to 10 UTXOs going at once.
/// </summary>
private const int TransfersToDisplay = 10;

/// <summary>
/// The maximum number of pending transactions to display in the console logging.
/// </summary>
private const int PendingToDisplay = 25;

public const string FederationGatewayFeatureNamespace = "federationgateway";

private readonly IConnectionManager connectionManager;
Expand All @@ -64,8 +53,6 @@ internal class FederatedPegFeature : FullNodeFeature

private readonly IFederationWalletSyncManager walletSyncManager;

private readonly ChainIndexer chainIndexer;

private readonly Network network;

private readonly ICrossChainTransferStore crossChainTransferStore;
Expand All @@ -78,8 +65,6 @@ internal class FederatedPegFeature : FullNodeFeature

private readonly IMaturedBlocksSyncManager maturedBlocksSyncManager;

private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider;

private readonly IInputConsolidator inputConsolidator;

private readonly ILogger logger;
Expand All @@ -92,30 +77,26 @@ internal class FederatedPegFeature : FullNodeFeature
IFederationWalletManager federationWalletManager,
IFederationWalletSyncManager walletSyncManager,
Network network,
ChainIndexer chainIndexer,
INodeStats nodeStats,
ICrossChainTransferStore crossChainTransferStore,
IPartialTransactionRequester partialTransactionRequester,
MempoolCleaner mempoolCleaner,
ISignedMultisigTransactionBroadcaster signedBroadcaster,
IMaturedBlocksSyncManager maturedBlocksSyncManager,
IWithdrawalHistoryProvider withdrawalHistoryProvider,
IInputConsolidator inputConsolidator,
ICollateralChecker collateralChecker = null)
{
this.loggerFactory = loggerFactory;
this.connectionManager = connectionManager;
this.federatedPegSettings = federatedPegSettings;
this.fullNode = fullNode;
this.chainIndexer = chainIndexer;
this.federationWalletManager = federationWalletManager;
this.walletSyncManager = walletSyncManager;
this.network = network;
this.crossChainTransferStore = crossChainTransferStore;
this.partialTransactionRequester = partialTransactionRequester;
this.mempoolCleaner = mempoolCleaner;
this.maturedBlocksSyncManager = maturedBlocksSyncManager;
this.withdrawalHistoryProvider = withdrawalHistoryProvider;
this.signedBroadcaster = signedBroadcaster;
this.inputConsolidator = inputConsolidator;

Expand Down Expand Up @@ -258,39 +239,6 @@ private string CollectStats()
benchLog.AppendLine();
}

try
{
List<WithdrawalModel> pendingWithdrawals = this.withdrawalHistoryProvider.GetPending();

if (pendingWithdrawals.Count > 0)
{
benchLog.AppendLine("--- Pending Withdrawals ---");
foreach (WithdrawalModel withdrawal in pendingWithdrawals.Take(PendingToDisplay))
benchLog.AppendLine(withdrawal.ToString());

if (pendingWithdrawals.Count > PendingToDisplay)
benchLog.AppendLine($"And {pendingWithdrawals.Count - PendingToDisplay} more...");

benchLog.AppendLine();
}
}
catch (Exception exception)
{
benchLog.AppendLine("--- Pending Withdrawals ---");
benchLog.AppendLine("Failed to retrieve data");
this.logger.LogError("Exception occurred while getting pending withdrawals: '{0}'.", exception.ToString());
}

List<WithdrawalModel> completedWithdrawals = this.withdrawalHistoryProvider.GetHistory(TransfersToDisplay);

if (completedWithdrawals.Count > 0)
{
benchLog.AppendLine("--- Recently Completed Withdrawals ---");
foreach (WithdrawalModel withdrawal in completedWithdrawals)
benchLog.AppendLine(withdrawal.ToString());
benchLog.AppendLine();
}

return benchLog.ToString();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ public interface ICrossChainTransferStore : IDisposable
/// </summary>
/// <param name="transactionsToCheck">The list of input transactions.</param>
/// <returns>The list of transactions that are completed (or unknown) wihdrawals.</returns>
List<Transaction> CompletedWithdrawals(IEnumerable<Transaction> transactionsToCheck);
List<Transaction> GetCompletedWithdrawalsForTransactions(IEnumerable<Transaction> transactionsToCheck);

/// <summary>
/// Returns a list of completed withdrawals (those that are seen-in-block).
/// </summary>
/// <param name="transfersToDisplay">The max items to display.</param>
/// <returns>The completed withdrawals.</returns>
List<WithdrawalModel> GetCompletedWithdrawals(int transfersToDisplay);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public override string ToString()
{
var stringBuilder = new StringBuilder();

stringBuilder.Append(string.Format("Block Height={0,8} Paying={1} Amount={2,12} Status={3}",
stringBuilder.Append(string.Format("Block Height={0,8} Paying={1} Amount={2,14} Status={3}",
this.BlockHeight == 0 ? "Unconfirmed" : this.BlockHeight.ToString(),
this.PayingTo,
this.Amount.ToString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ namespace Stratis.Features.FederatedPeg.TargetChain
{
public class CrossChainTransferStore : ICrossChainTransferStore
{
/// <summary>
/// Given that we can have up to 10 UTXOs going at once.
/// </summary>
private const int TransfersToDisplay = 10;

/// <summary>
/// Maximum number of partial transactions.
/// </summary>
Expand Down Expand Up @@ -78,13 +83,14 @@ public class CrossChainTransferStore : ICrossChainTransferStore
private readonly ISignals signals;
private readonly IStateRepositoryRoot stateRepositoryRoot;
private readonly IWithdrawalExtractor withdrawalExtractor;
private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider;
private readonly IWithdrawalTransactionBuilder withdrawalTransactionBuilder;

/// <summary>Provider of time functions.</summary>
private readonly object lockObj;

public CrossChainTransferStore(Network network, INodeStats nodeStats, DataFolder dataFolder, ChainIndexer chainIndexer, IFederatedPegSettings settings, IDateTimeProvider dateTimeProvider,
ILoggerFactory loggerFactory, IWithdrawalExtractor withdrawalExtractor, IBlockRepository blockRepository, IFederationWalletManager federationWalletManager,
ILoggerFactory loggerFactory, IWithdrawalExtractor withdrawalExtractor, IWithdrawalHistoryProvider withdrawalHistoryProvider, IBlockRepository blockRepository, IFederationWalletManager federationWalletManager,
IWithdrawalTransactionBuilder withdrawalTransactionBuilder, DBreezeSerializer dBreezeSerializer, ISignals signals, IStateRepositoryRoot stateRepositoryRoot = null)
{
if (!settings.IsMainChain)
Expand All @@ -108,8 +114,6 @@ public class CrossChainTransferStore : ICrossChainTransferStore
this.chainIndexer = chainIndexer;
this.blockRepository = blockRepository;
this.federationWalletManager = federationWalletManager;
this.withdrawalTransactionBuilder = withdrawalTransactionBuilder;
this.withdrawalExtractor = withdrawalExtractor;
this.dBreezeSerializer = dBreezeSerializer;
this.lockObj = new object();
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
Expand All @@ -119,6 +123,9 @@ public class CrossChainTransferStore : ICrossChainTransferStore
this.settings = settings;
this.signals = signals;
this.stateRepositoryRoot = stateRepositoryRoot;
this.withdrawalExtractor = withdrawalExtractor;
this.withdrawalHistoryProvider = withdrawalHistoryProvider;
this.withdrawalTransactionBuilder = withdrawalTransactionBuilder;

// Future-proof store name.
string depositStoreName = "federatedTransfers" + settings.MultiSigAddress.ToString();
Expand Down Expand Up @@ -1385,7 +1392,7 @@ public bool ValidateTransaction(Transaction transaction, bool checkSignature = f
}

/// <inheritdoc />
public List<Transaction> CompletedWithdrawals(IEnumerable<Transaction> transactionsToCheck)
public List<Transaction> GetCompletedWithdrawalsForTransactions(IEnumerable<Transaction> transactionsToCheck)
{
var res = new List<Transaction>();

Expand Down Expand Up @@ -1440,6 +1447,64 @@ private void AddComponentStats(StringBuilder benchLog)
benchLog.AppendLine("Partial Txs:".PadRight(20) + GetTransfersByStatusCount(CrossChainTransferStatus.Partial));
benchLog.AppendLine("Suspended Txs:".PadRight(20) + GetTransfersByStatusCount(CrossChainTransferStatus.Suspended));
benchLog.AppendLine();

var depositIds = new HashSet<uint256>();
ICrossChainTransfer[] transfers;

try
{
foreach (CrossChainTransferStatus status in new[] { CrossChainTransferStatus.FullySigned, CrossChainTransferStatus.Partial })
depositIds.UnionWith(this.depositsIdsByStatus[status]);

transfers = this.Get(depositIds.ToArray()).Where(t => t != null).ToArray();

// When sorting, Suspended transactions will have null PartialTransactions. Always put them last in the order they're in.
IEnumerable<ICrossChainTransfer> inprogress = transfers.Where(x => x.Status != CrossChainTransferStatus.Suspended && x.Status != CrossChainTransferStatus.Rejected);
IEnumerable<ICrossChainTransfer> suspended = transfers.Where(x => x.Status == CrossChainTransferStatus.Suspended || x.Status == CrossChainTransferStatus.Rejected);

List<WithdrawalModel> pendingWithdrawals = this.withdrawalHistoryProvider.GetPendingWithdrawals(inprogress.Concat(suspended));

if (pendingWithdrawals.Count > 0)
{
benchLog.AppendLine("--- Pending Withdrawals ---");
foreach (WithdrawalModel withdrawal in pendingWithdrawals.Take(TransfersToDisplay))
benchLog.AppendLine(withdrawal.ToString());

if (pendingWithdrawals.Count > TransfersToDisplay)
benchLog.AppendLine($"And {pendingWithdrawals.Count - TransfersToDisplay} more...");

benchLog.AppendLine();
}
}
catch (Exception exception)
{
benchLog.AppendLine("--- Pending Withdrawals ---");
benchLog.AppendLine("Failed to retrieve data");
this.logger.LogError("Exception occurred while getting pending withdrawals: '{0}'.", exception.ToString());
}

List<WithdrawalModel> completedWithdrawals = GetCompletedWithdrawals(TransfersToDisplay);
if (completedWithdrawals.Count > 0)
{
benchLog.AppendLine("--- Recently Completed Withdrawals ---");

foreach (WithdrawalModel withdrawal in completedWithdrawals)
benchLog.AppendLine(withdrawal.ToString());

benchLog.AppendLine();
}
}

/// <inheritdoc />
public List<WithdrawalModel> GetCompletedWithdrawals(int transfersToDisplay)
{
var depositIds = new HashSet<uint256>();
foreach (CrossChainTransferStatus status in new[] { CrossChainTransferStatus.SeenInBlock })
depositIds.UnionWith(this.depositsIdsByStatus[status]);

ICrossChainTransfer[] transfers = this.Get(depositIds.ToArray()).Where(t => t != null).ToArray();

return this.withdrawalHistoryProvider.GetHistory(transfers, transfersToDisplay);
}

/// <inheritdoc />
Expand Down
Loading