public void VerifyThatColdStakeTransactionCanBeFiltered() { this.Initialize(); this.CreateMempoolManager(); this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1)); Wallet.Wallet wallet1 = this.coldStakingManager.GetWalletByName(walletName1); // This will add a normal account to our wallet. Transaction trx1 = this.AddSpendableTransactionToWallet(wallet1); // This will add a secondary account to our wallet. Transaction trx2 = this.AddSpendableColdstakingTransactionToWallet(wallet1); // THis will add a cold staking transaction to the secondary normal account address. This simulates activation of cold staking onto any normal address. Transaction trx3 = this.AddSpendableColdstakingTransactionToNormalWallet(wallet1); var accounts = wallet1.GetAccounts(Wallet.Wallet.AllAccounts).ToArray(); // We should have 2 accounts in our wallet. Assert.Equal(2, accounts.Length); // But not if we use default or specify to only return normal accounts. Assert.Single(wallet1.GetAccounts().ToArray()); // Defaults to NormalAccounts Assert.Single(wallet1.GetAccounts(Wallet.Wallet.NormalAccounts).ToArray()); // Verify that we actually have an cold staking activation UTXO in the wallet of 202 coins. // This should normally not be returned by the GetAllTransactions, and should never be included in balance calculations. Assert.True(accounts[0].ExternalAddresses.ToArray()[1].Transactions.ToArray()[0].IsColdCoinStake); Assert.Equal(new Money(202, MoneyUnit.BTC), accounts[0].ExternalAddresses.ToArray()[1].Transactions.ToArray()[0].Amount); Assert.Single(wallet1.GetAllTransactions().ToArray()); // Default to NormalAccounts, should filter out cold staking (trx3) from normal wallet. Assert.Single(wallet1.GetAllTransactions(Wallet.Wallet.NormalAccounts).ToArray()); Assert.Single(wallet1.GetAllSpendableTransactions(5, 0, Wallet.Wallet.NormalAccounts).ToArray()); // Default to NormalAccounts Assert.Equal(2, wallet1.GetAllTransactions(Wallet.Wallet.AllAccounts).ToArray().Length); Assert.Equal(2, wallet1.GetAllSpendableTransactions(5, 0, Wallet.Wallet.AllAccounts).ToArray().Length); // Specified AllAccounts, should include cold-staking transaction. // Verify balance on normal account var balance1 = accounts[0].GetBalances(true); var balance2 = accounts[0].GetBalances(false); Assert.Equal(new Money(101, MoneyUnit.BTC), balance1.ConfirmedAmount); Assert.Equal(new Money(303, MoneyUnit.BTC), balance2.ConfirmedAmount); // Verify balance on special account. // Verify balance on normal account var balance3 = accounts[1].GetBalances(true); var balance4 = accounts[1].GetBalances(false); // The only transaction that exists in the cold staking wallet, is a normal one, and should be returned for both balance queries. Assert.Equal(new Money(101, MoneyUnit.BTC), balance3.ConfirmedAmount); Assert.Equal(new Money(101, MoneyUnit.BTC), balance4.ConfirmedAmount); }
public async Task GenerateBlocksAsync_does_not_use_small_coins() { var walletSecret = new WalletSecret() { WalletName = "wallet", WalletPassword = "******" }; var wallet = new Wallet.Wallet() { Network = this.network }; var milliseconds550MinutesAgo = (uint)Math.Max(this.chain.Tip.Header.Time - TimeSpan.FromMinutes(550).Milliseconds, 0); this.AddAccountWithSpendableOutputs(wallet); var spendableTransactions = wallet.GetAllSpendableTransactions(CoinType.Stratis, this.chain.Tip.Height, 0).ToList(); this.walletManager.Setup(w => w.GetSpendableTransactionsInWallet(It.IsAny <string>(), It.IsAny <int>())) .Returns(spendableTransactions); var fetchedUtxos = spendableTransactions .Select(t => new UnspentOutputs(t.Transaction.Id, new Coins() { CoinBase = false, CoinStake = false, Height = 0, Outputs = { new TxOut(t.Transaction.Amount ?? Money.Zero, t.Address.ScriptPubKey) }, Time = milliseconds550MinutesAgo, Version = 1 })) .ToArray(); var fetchCoinsResponse = new FetchCoinsResponse(fetchedUtxos, this.chain.Tip.HashBlock); fetchCoinsResponse.UnspentOutputs .Where(u => u.Outputs.Any(o => o.Value < this.posMinting.MinimumStakingCoinValue)).Should() .NotBeEmpty("otherwise we are not sure the code actually excludes them"); fetchCoinsResponse.UnspentOutputs .Where(u => u.Outputs.Any(o => o.Value >= this.posMinting.MinimumStakingCoinValue)).Should() .NotBeEmpty("otherwise we are not sure the code actually includes them"); this.coinView.Setup(c => c.FetchCoinsAsync(It.IsAny <uint256[]>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(fetchCoinsResponse)); this.consensusManager.Setup(c => c.Tip).Returns(this.chain.Tip); this.dateTimeProvider.Setup(c => c.GetAdjustedTimeAsUnixTimestamp()) .Returns(this.chain.Tip.Header.Time + 16); var ct = CancellationToken.None; var utxoStakeDescriptions = await this.posMinting.GetUtxoStakeDescriptionsAsync(walletSecret, ct); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v < this.posMinting.MinimumStakingCoinValue) .Should().BeEmpty("small coins should not be included"); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v >= this.posMinting.MinimumStakingCoinValue) .Should().NotBeEmpty("big enough coins should be included"); var expectedAmounts = spendableTransactions.Select(s => s.Transaction.Amount) .Where(a => a >= this.posMinting.MinimumStakingCoinValue).ToArray(); utxoStakeDescriptions.Count.Should().Be(expectedAmounts.Length); utxoStakeDescriptions.Select(d => d.TxOut.Value).Should().Contain(expectedAmounts); }
public void GenerateBlocks_does_not_use_small_coins() { var walletSecret = new WalletSecret() { WalletName = "wallet", WalletPassword = "******" }; var wallet = new Wallet.Wallet(this.network); var milliseconds550MinutesAgo = (uint)Math.Max(this.chainIndexer.Tip.Header.Time - TimeSpan.FromMinutes(550).Milliseconds, 0); this.AddAccountWithSpendableOutputs(wallet); var spendableTransactions = wallet.GetAllSpendableTransactions(this.chainIndexer.Tip.Height, 0).ToList(); this.walletManager.Setup(w => w.GetSpendableTransactionsInWalletForStaking(It.IsAny <string>(), It.IsAny <int>())) .Returns(spendableTransactions); var fetchedUtxos = spendableTransactions .Select(t => new UnspentOutput( new OutPoint(t.Transaction.Id, 0), new Utilities.Coins(0, new TxOut(t.Transaction.Amount ?? Money.Zero, t.Address.ScriptPubKey), false, false))) .ToArray(); var fetchCoinsResponse = new FetchCoinsResponse(); foreach (var fetch in fetchedUtxos) { fetchCoinsResponse.UnspentOutputs.Add(fetch.OutPoint, fetch); } fetchCoinsResponse.UnspentOutputs .Where(u => u.Value.Coins.TxOut.Value < this.posMinting.MinimumStakingCoinValue).Should() .NotBeEmpty("otherwise we are not sure the code actually excludes them"); fetchCoinsResponse.UnspentOutputs .Where(u => u.Value.Coins.TxOut.Value >= this.posMinting.MinimumStakingCoinValue).Should() .NotBeEmpty("otherwise we are not sure the code actually includes them"); this.coinView.Setup(c => c.FetchCoins(It.IsAny <OutPoint[]>())) .Returns(fetchCoinsResponse); this.consensusManager.Setup(c => c.Tip).Returns(this.chainIndexer.Tip); this.dateTimeProvider.Setup(c => c.GetAdjustedTimeAsUnixTimestamp()) .Returns(this.chainIndexer.Tip.Header.Time + 16); var ct = CancellationToken.None; var utxoStakeDescriptions = this.posMinting.GetUtxoStakeDescriptions(walletSecret, ct); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v < this.posMinting.MinimumStakingCoinValue) .Should().BeEmpty("small coins should not be included"); utxoStakeDescriptions.Select(d => d.TxOut.Value).Where(v => v >= this.posMinting.MinimumStakingCoinValue) .Should().NotBeEmpty("big enough coins should be included"); var expectedAmounts = spendableTransactions.Select(s => s.Transaction.Amount) .Where(a => a >= this.posMinting.MinimumStakingCoinValue).ToArray(); utxoStakeDescriptions.Count.Should().Be(expectedAmounts.Length); utxoStakeDescriptions.Select(d => d.TxOut.Value).Should().Contain(expectedAmounts); }
/// <summary> /// Gets the spendable transactions associated with cold wallet addresses. /// </summary> /// <param name="walletName">The name of the wallet.</param> /// <param name="isColdWalletAccount">The cold staking account to get the transactions for.</param> /// <param name="confirmations">The number of confirmations.</param> /// <returns>An enumeration of <see cref="UnspentOutputReference"/> items.</returns> public IEnumerable <UnspentOutputReference> GetSpendableTransactionsInColdWallet(string walletName, bool isColdWalletAccount, int confirmations = 0) { Guard.NotEmpty(walletName, nameof(walletName)); Wallet.Wallet wallet = this.GetWalletByName(walletName); UnspentOutputReference[] res = null; lock (this.lockObject) { res = wallet.GetAllSpendableTransactions(this.ChainIndexer.Tip.Height, confirmations, a => a.Index == (isColdWalletAccount ? ColdWalletAccountIndex : HotWalletAccountIndex)).ToArray(); } this.logger.LogTrace("(-):*.Count={0}", res.Count()); return(res); }