コード例 #1
0
        /// <summary>
        /// Adds a spendable cold staking transaction to a wallet.
        /// </summary>
        /// <param name="wallet">Wallet to add the transaction to.</param>
        /// <returns>The spendable transaction that was added to the wallet.</returns>
        private Transaction AddSpendableColdstakingTransactionToWallet(Wallet.Wallet wallet)
        {
            // Get first unused cold staking address.
            this.coldStakingManager.GetOrCreateColdStakingAccount(wallet.Name, true, walletPassword);
            HdAddress address = this.coldStakingManager.GetFirstUnusedColdStakingAddress(wallet.Name, true);

            TxDestination hotPubKey  = BitcoinAddress.Create(hotWalletAddress1, wallet.Network).ScriptPubKey.GetDestination(wallet.Network);
            TxDestination coldPubKey = BitcoinAddress.Create(coldWalletAddress2, wallet.Network).ScriptPubKey.GetDestination(wallet.Network);

            var scriptPubKey = new Script(OpcodeType.OP_DUP, OpcodeType.OP_HASH160, OpcodeType.OP_ROT, OpcodeType.OP_IF,
                                          OpcodeType.OP_CHECKCOLDSTAKEVERIFY, Op.GetPushOp(hotPubKey.ToBytes()), OpcodeType.OP_ELSE, Op.GetPushOp(coldPubKey.ToBytes()),
                                          OpcodeType.OP_ENDIF, OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG);

            var transaction = this.Network.CreateTransaction();

            transaction.Outputs.Add(new TxOut(Money.Coins(101), scriptPubKey));

            address.Transactions.Add(new TransactionData()
            {
                Hex          = transaction.ToHex(this.Network),
                Amount       = transaction.Outputs[0].Value,
                Id           = transaction.GetHash(),
                BlockHeight  = 0,
                Index        = 0,
                IsCoinBase   = false,
                IsCoinStake  = false,
                IsPropagated = true,
                BlockHash    = this.Network.GenesisHash,
                ScriptPubKey = scriptPubKey
            });

            return(transaction);
        }
コード例 #2
0
        public void StartStaking_InvalidTimeSyncState_ReturnsBadRequest()
        {
            Wallet.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet", "password1");
            this.walletManager.Setup(w => w.GetWallet("myWallet"))
            .Returns(wallet);

            this.fullNode.Setup(f => f.NodeService <IWalletManager>(false))
            .Returns(this.walletManager.Object);

            this.timeSyncBehaviorState.Setup(ts => ts.IsSystemTimeOutOfSync).Returns(true);

            this.fullNode.Setup(f => f.NodeFeature <MiningFeature>(true))
            .Returns(new MiningFeature(KnownNetworks.Main, new MinerSettings(Configuration.NodeSettings.Default()), Configuration.NodeSettings.Default(), this.LoggerFactory.Object, this.timeSyncBehaviorState.Object, null, this.posMinting.Object));

            IActionResult result = this.controller.StartStaking(new StartStakingRequest()
            {
                Name = "myWallet", Password = "******"
            });

            var errorResult   = Assert.IsType <ErrorResult>(result);
            var errorResponse = Assert.IsType <ErrorResponse>(errorResult.Value);

            Assert.Single(errorResponse.Errors);

            ErrorModel error = errorResponse.Errors[0];

            Assert.Equal(400, error.Status);
            Assert.Contains("Staking cannot start", error.Message);

            this.posMinting.Verify(pm => pm.Stake(It.IsAny <WalletSecret>()), Times.Never);
        }
コード例 #3
0
        public void VerifyThatColdStakeTransactionCanBeFiltered()
        {
            this.Initialize();
            this.CreateMempoolManager();

            this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1));

            Wallet.Wallet wallet1 = this.coldStakingManager.GetWalletByName(walletName1);

            Transaction prevTran = this.AddSpendableTransactionToWallet(wallet1);

            IActionResult result = this.coldStakingController.SetupColdStaking(new SetupColdStakingRequest
            {
                HotWalletAddress  = hotWalletAddress1,
                ColdWalletAddress = coldWalletAddress2,
                WalletName        = walletName1,
                WalletAccount     = walletAccount,
                WalletPassword    = walletPassword,
                Amount            = "100",
                Fees = "0.01"
            });

            var jsonResult  = Assert.IsType <JsonResult>(result);
            var response    = Assert.IsType <SetupColdStakingResponse>(jsonResult.Value);
            var transaction = Assert.IsType <PosTransaction>(this.Network.CreateTransaction(response.TransactionHex));

            Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 90c582cb91d6b6d777c31c891d4943fed4edac3a OP_ELSE 92dfb829d31cefe6a0731f3432dea41596a278d9 OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString());

            // Get the ColdStaking script template if available.
            Dictionary <string, ScriptTemplate> templates = this.coldStakingManager.GetValidStakingTemplates();
            ScriptTemplate coldStakingTemplate            = templates["ColdStaking"];

            Assert.True(coldStakingTemplate.CheckScriptPubKey(transaction.Outputs[1].ScriptPubKey));
        }
コード例 #4
0
        /// <summary>
        /// Gets the first unused cold staking address. Creates a new address if required.
        /// </summary>
        /// <param name="walletName">The name of the wallet providing the cold staking address.</param>
        /// <param name="isColdWalletAddress">Indicates whether we need the cold wallet address (versus the hot wallet address).</param>
        /// <returns>The cold staking address or <c>null</c> if the required account does not exist.</returns>
        internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isColdWalletAddress)
        {
            Guard.NotNull(walletName, nameof(walletName));

            Wallet.Wallet wallet  = this.GetWalletByName(walletName);
            HdAccount     account = this.GetColdStakingAccount(wallet, isColdWalletAddress);

            if (account == null)
            {
                this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null");
                return(null);
            }

            HdAddress address = account.GetFirstUnusedReceivingAddress();

            if (address == null)
            {
                this.logger.LogDebug("No unused address exists on account '{0}'. Adding new address.", account.Name);
                IEnumerable <HdAddress> newAddresses = account.CreateAddresses(wallet.Network, 1);
                this.UpdateKeysLookupLocked(newAddresses);
                address = newAddresses.First();
            }

            this.logger.LogTrace("(-):'{0}'", address.Address);
            return(address);
        }
コード例 #5
0
        /// <summary>
        /// Gets the first unused cold staking address. Creates a new address if required.
        /// </summary>
        /// <param name="walletName">The name of the wallet providing the cold staking address.</param>
        /// <param name="isColdWalletAddress">Indicates whether we need the cold wallet address (versus the hot wallet address).</param>
        /// <returns>The cold staking address or <c>null</c> if the required account does not exist.</returns>
        internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isColdWalletAddress)
        {
            Guard.NotNull(walletName, nameof(walletName));

            this.logger.LogTrace("({0}:'{1}',{2}:{3})", nameof(walletName), walletName, nameof(isColdWalletAddress), isColdWalletAddress);

            Wallet.Wallet wallet  = this.GetWalletByName(walletName);
            HdAccount     account = this.GetColdStakingAccount(wallet, isColdWalletAddress);

            if (account == null)
            {
                this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null");
                return(null);
            }

            HdAddress address = account.GetFirstUnusedReceivingAddress();

            if (address == null)
            {
                this.logger.LogTrace("No unused address exists on account '{0}'. Adding new address.", account.Name);
                address = account.CreateAddresses(wallet.Network, 1).First();
            }

            this.logger.LogTrace("(-):'{0}'", address.Address);
            return(address);
        }
コード例 #6
0
ファイル: PosMintingTest.cs プロジェクト: emilm/city-chain
        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);
        }
コード例 #7
0
        public void StopStaking_Returns_Ok()
        {
            {
                Wallet.Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet", "password1");
                this.walletManager.Setup(w => w.GetWallet("myWallet"))
                .Returns(wallet);

                this.fullNode.Setup(f => f.NodeService <IWalletManager>(false))
                .Returns(this.walletManager.Object);

                this.fullNode.Setup(f => f.NodeFeature <MiningFeature>(true))
                .Returns(new MiningFeature(new ConnectionManagerSettings(NodeSettings.Default(this.Network)), KnownNetworks.Main, new MinerSettings(NodeSettings.Default(this.Network)), NodeSettings.Default(this.Network), this.LoggerFactory.Object, this.timeSyncBehaviorState.Object, null, this.posMinting.Object));

                IActionResult startStakingResult = this.controller.StartStaking(new StartStakingRequest()
                {
                    Name = "myWallet", Password = "******"
                });

                Assert.IsType <OkResult>(startStakingResult);

                IActionResult stopStakingResult = this.controller.StopStaking();

                Assert.IsType <OkResult>(stopStakingResult);
            }
        }
コード例 #8
0
        public IActionResult StakingExpiry([FromBody] StakingExpiryRequest request)
        {
            try
            {
                if (!this.fullNode.Network.Consensus.IsProofOfStake)
                {
                    return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.MethodNotAllowed, "Method not allowed", "Method not available for Proof of Stake"));
                }

                if (!this.minerSettings.EnforceStakingFlag)
                {
                    return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Operation not allowed", "This operation is only allowed if EnforceStakingFlag is true"));
                }

                Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);

                foreach (Wallet.HdAccount account in wallet.GetAccounts(account => true))
                {
                    foreach (Wallet.HdAddress address in account.GetCombinedAddresses())
                    {
                        if ((address.Address == request.Address) || address.Bech32Address == request.Address)
                        {
                            address.StakingExpiry = request.StakingExpiry;
                        }
                    }
                }

                return(this.Ok());
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #9
0
        public void RecoverWalletSuccessfullyReturnsWalletModel()
        {
            Wallet.Wallet wallet = new Wallet.Wallet
            {
                Name    = "myWallet",
                Network = WalletHelpers.GetNetwork("mainnet")
            };
            var mockWalletWrapper = new Mock <IWalletManager>();

            mockWalletWrapper.Setup(w => w.LoadWallet(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())).Returns(wallet);

            var controller = new WalletController(mockWalletWrapper.Object, new Mock <ITracker>().Object);

            // Act
            var result = controller.Load(new WalletLoadRequest
            {
                Name       = "myWallet",
                FolderPath = "",
                Password   = ""
            });

            // Assert
            mockWalletWrapper.VerifyAll();
            var viewResult = Assert.IsType <JsonResult>(result);

            Assert.NotNull(viewResult.Value);
            Assert.IsType <WalletModel>(viewResult.Value);

            var model = viewResult.Value as WalletModel;

            Assert.Equal("Main", model.Network);
        }
コード例 #10
0
        /// <summary>
        /// change categories accessibility for wallet.
        /// </summary>
        /// <param name="wallet"></param>
        /// <param name="category">category to change</param>
        public void SwitchCategoryPermission(Wallet.Wallet wallet, Category category)

        {
            if (!Wallets.Contains(wallet))
            {
                throw new UserException("can not switch categories if you are not owner");
            }
            if (!Categories.Contains(category))
            {
                throw new UserException("user hasn't this category");
            }
            if (wallet is null)
            {
                throw new UserException("user hasn't this wallet");
            }

            if (wallet.RestrictedCategories.Contains(category))
            {
                wallet.RestrictedCategories.Remove(category);
            }
            else
            {
                wallet.RestrictedCategories.Add(category);
            }
        }
コード例 #11
0
        /// <summary>
        /// Creates a cold staking account and ensures that it has at least one address.
        /// If the account already exists then the existing account is returned.
        /// </summary>
        /// <remarks>
        /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s
        /// with indexes starting from the value defined in <see cref="Wallet.Wallet.SpecialPurposeAccountIndexesStart"/>.
        /// </para><para>
        /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when
        /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this
        /// method.
        /// </para></remarks>
        /// <param name="walletName">The name of the wallet where we wish to create the account.</param>
        /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param>
        /// <param name="walletPassword">The wallet password which will be used to create the account.</param>
        /// <returns>The new or existing cold staking account.</returns>
        internal HdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWalletAccount, string walletPassword)
        {
            Wallet.Wallet wallet = this.GetWallet(walletName);

            HdAccount account = this.GetColdStakingAccount(wallet, isColdWalletAccount);

            if (account != null)
            {
                this.logger.LogTrace("(-)[ACCOUNT_ALREADY_EXIST]:'{0}'", account.Name);
                return(account);
            }

            this.logger.LogDebug("The {0} wallet account for '{1}' does not exist and will now be created.", isColdWalletAccount ? "cold" : "hot", wallet.Name);

            int    accountIndex;
            string accountName;

            if (isColdWalletAccount)
            {
                accountIndex = ColdWalletAccountIndex;
                accountName  = ColdWalletAccountName;
            }
            else
            {
                accountIndex = HotWalletAccountIndex;
                accountName  = HotWalletAccountName;
            }

            account = wallet.AddNewAccount(walletPassword, accountIndex, accountName, this.dateTimeProvider.GetTimeOffset());

            this.logger.LogTrace("(-):'{0}'", account.Name);
            return(account);
        }
コード例 #12
0
        public IActionResult StartStaking([FromBody] StartStakingRequest request)
        {
            Guard.NotNull(request, nameof(request));

            try
            {
                if (!this.ModelState.IsValid)
                {
                    IEnumerable <string> errors = this.ModelState.Values.SelectMany(e => e.Errors.Select(m => m.ErrorMessage));
                    return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Formatting error", string.Join(Environment.NewLine, errors)));
                }

                Wallet.Wallet wallet = this.walletManager.GetWallet(request.Name);

                // Check the password
                try
                {
                    Key.Parse(wallet.EncryptedSeed, request.Password, wallet.Network);
                }
                catch (Exception ex)
                {
                    throw new SecurityException(ex.Message);
                }

                this.fullNode.NodeFeature <MiningFeature>(true).StartStaking(request.Name, request.Password);
                return(this.Ok());
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
コード例 #13
0
        public Transaction CreateColdStakingWithdrawalTransaction(Wallet.Wallet wallet, string password, HdAddress spendingAddress, PubKey destinationPubKey, Script changeScript, Money amount, Money fee)
        {
            TransactionData spendingTransaction = spendingAddress.Transactions.ElementAt(0);
            var             coin = new Coin(spendingTransaction.Id, (uint)spendingTransaction.Index, spendingTransaction.Amount, spendingTransaction.ScriptPubKey);

            Key privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network);

            Script script = destinationPubKey.ScriptPubKey;

            var builder = new TransactionBuilder(wallet.Network);

            builder.Extensions.Add(new ColdStakingBuilderExtension(false));
            Transaction tx = builder
                             .AddCoins(new List <Coin> {
                coin
            })
                             .AddKeys(new ExtKey(privateKey, wallet.ChainCode).Derive(new KeyPath(spendingAddress.HdPath)).GetWif(wallet.Network))
                             .Send(script, amount)
                             .SetChange(changeScript)
                             .SendFees(fee)
                             .BuildTransaction(true);

            if (!builder.Verify(tx))
            {
                throw new WalletException("Could not build transaction, please make sure you entered the correct data.");
            }

            return(tx);
        }
コード例 #14
0
        /// <summary>
        /// Adds a spendable cold staking transaction to a normal account, as oppose to dedicated special account.
        /// </summary>
        /// <param name="wallet">Wallet to add the transaction to.</param>
        /// <returns>The spendable transaction that was added to the wallet.</returns>
        private Transaction AddSpendableColdstakingTransactionToNormalWallet(Wallet.Wallet wallet, bool script = false)
        {
            // This will always be added to the secondary address.
            HdAddress address = wallet.GetAllAddresses().ToArray()[1];

            var transaction = this.Network.CreateTransaction();

            // Use the normal wallet address here.
            TxDestination hotPubKey  = BitcoinAddress.Create(address.Address, wallet.Network).ScriptPubKey.GetDestination(wallet.Network);
            TxDestination coldPubKey = BitcoinAddress.Create(coldWalletAddress2, wallet.Network).ScriptPubKey.GetDestination(wallet.Network);

            var scriptPubKey = new Script(OpcodeType.OP_DUP, OpcodeType.OP_HASH160, OpcodeType.OP_ROT, OpcodeType.OP_IF,
                                          OpcodeType.OP_CHECKCOLDSTAKEVERIFY, Op.GetPushOp(hotPubKey.ToBytes()), OpcodeType.OP_ELSE, Op.GetPushOp(coldPubKey.ToBytes()),
                                          OpcodeType.OP_ENDIF, OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG);

            transaction.Outputs.Add(new TxOut(Money.Coins(202), script ? scriptPubKey.WitHash.ScriptPubKey : scriptPubKey));

            address.Transactions.Add(new TransactionData()
            {
                Hex             = transaction.ToHex(this.Network),
                Amount          = transaction.Outputs[0].Value,
                Id              = transaction.GetHash(),
                BlockHeight     = 0,
                Index           = 0,
                IsCoinBase      = false,
                IsCoinStake     = false,
                IsColdCoinStake = true,
                IsPropagated    = true,
                BlockHash       = this.Network.GenesisHash,
                ScriptPubKey    = script ? scriptPubKey.WitHash.ScriptPubKey : scriptPubKey,
            });

            return(transaction);
        }
コード例 #15
0
        public bool StartStaking(string walletName, string walletPassword)
        {
            this.logger.LogTrace("({0}:{1})", nameof(walletName), walletName);

            WalletManager walletManager = this.fullNode.NodeService <IWalletManager>() as WalletManager;

            Wallet.Wallet wallet = walletManager.Wallets.FirstOrDefault(w => w.Name == walletName);

            if (wallet == null)
            {
                this.logger.LogError("Exception occurred: {0}", $"The specified wallet is unknown: '{walletName}'");
                throw new RPCServerException(NBitcoin.RPC.RPCErrorCode.RPC_INVALID_REQUEST, "Wallet not found");
            }
            else
            {
                // Check the password
                try
                {
                    Key.Parse(wallet.EncryptedSeed, walletPassword, wallet.Network);
                }
                catch (Exception ex)
                {
                    throw new SecurityException(ex.Message);
                }
            }

            this.fullNode.NodeFeature <MiningFeature>(true).StartStaking(walletName, walletPassword);

            return(true);
        }
コード例 #16
0
        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);
        }
コード例 #17
0
 private void calculateOutputs(Wallet.Wallet wallet)
 {
     if (Inputs != null)
     {
         long balance = BalanceHelper.GetBalanceOfAddresses(Inputs.Select(i => i.Key).ToArray());
         Outputs.Add(new Output(wallet.NewAddress().Key, balance - TransactionFee - Outputs.Select(o => o.Amount).Sum()));
     }
 }
コード例 #18
0
 public Transaction(List <Input> inputs, Wallet.Wallet wallet, List <Output> outputs, long transactionFee = 0, byte[] data = null)
 {
     Inputs         = inputs;
     Data           = data;
     Outputs        = outputs;
     TransactionFee = transactionFee;
     calculateOutputs(wallet);
     signInputs(wallet);
 }
コード例 #19
0
        /// <summary>
        /// Add cold staking cold account when a wallet is recovered, this means every recovered wallet will automatical
        /// track addresses under the <see cref="ColdWalletAccountIndex"/> HD account.
        /// </summary>
        /// <inheritdoc />
        public override Wallet.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int?coinType = null)
        {
            Wallet.Wallet wallet = base.RecoverWallet(password, name, mnemonic, creationTime, passphrase, coinType);

            this.GetOrCreateColdStakingAccount(wallet.Name, false, password);
            this.GetOrCreateColdStakingAccount(wallet.Name, true, password);

            return(wallet);
        }
コード例 #20
0
 public Wallet.Wallet CreateNewWallet(string name,
                                      decimal startBalance,
                                      string description,
                                      string currency, Guid guid)
 {
     //create wallet and assign it to user
     Wallet.Wallet wallet = Wallet.Wallet.CreateWalletForUser(this, name, startBalance, description, currency, guid);
     return(wallet);
 }
コード例 #21
0
ファイル: WalletTests.cs プロジェクト: mdhatmaker/PrimeTrader
 public async void Unarchive_NullAddress_ArgumentNulException()
 {
     await Assert.ThrowsAsync <ArgumentNullException>(async() =>
     {
         using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper())
         {
             Wallet.Wallet wallet = this.GetWallet(apiHelper);
             await wallet.UnarchiveAddressAsync(null);
         }
     });
 }
コード例 #22
0
ファイル: WalletTests.cs プロジェクト: mdhatmaker/PrimeTrader
 public async void GetAddress_BadParameters_ArgumentExceptions()
 {
     await Assert.ThrowsAsync <ArgumentNullException>(async() =>
     {
         using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper())
         {
             Wallet.Wallet wallet = this.GetWallet(apiHelper);
             await wallet.GetAddressAsync(null);
         }
     });
 }
コード例 #23
0
        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);
        }
コード例 #24
0
 public async void ListAddresses_NegativeConfirmations_ArgumentOutOfRangeException()
 {
     await Assert.ThrowsAsync <ArgumentOutOfRangeException>(async() =>
     {
         using (BlockchainApiHelper apiHelper = UnitTestUtil.GetFakeHelper())
         {
             Wallet.Wallet wallet = this.GetWallet(apiHelper);
             await wallet.ListAddressesAsync(-1);
         }
     });
 }
コード例 #25
0
ファイル: WalletTests.cs プロジェクト: mdhatmaker/PrimeTrader
        public async void SendPayment_SendBtc_NoFreeOutputs()
        {
            ServerApiException apiException = await Assert.ThrowsAsync <ServerApiException>(async() => {
                using (BlockchainApiHelper apiHelper = new BlockchainApiHelper())
                {
                    Wallet.Wallet wallet = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2);
                    await wallet.SendAsync(WalletTests.FIRST_ADDRESS, BitcoinValue.FromBtc(1));
                }
            });

            Assert.Contains("No free", apiException.Message);
        }
コード例 #26
0
ファイル: WalletTests.cs プロジェクト: mdhatmaker/PrimeTrader
        public async void GetAddresses_Valid()
        {
            using (BlockchainApiHelper apiHelper = new BlockchainApiHelper())
            {
                Wallet.Wallet        wallet    = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2);
                List <WalletAddress> addresses = await wallet.ListAddressesAsync();

                Assert.NotNull(addresses);
                Assert.NotEmpty(addresses);
                Assert.True(addresses.Any(a => string.Equals(a.AddressStr, WalletTests.FIRST_ADDRESS)));
            }
        }
コード例 #27
0
ファイル: WalletTests.cs プロジェクト: mdhatmaker/PrimeTrader
        public async void Unarchive_BadAddress_ServerApiException()
        {
            ServerApiException apiException = await Assert.ThrowsAsync <ServerApiException>(async() => {
                using (BlockchainApiHelper apiHelper = new BlockchainApiHelper())
                {
                    Wallet.Wallet walletHelper = apiHelper.InitializeWallet(WalletTests.WALLET_ID, WalletTests.WALLET_PASSWORD, WalletTests.WALLET_PASSWORD2);
                    await walletHelper.UnarchiveAddressAsync("BadAddress");
                }
            });

            Assert.Contains("Checksum", apiException.Message);
        }
コード例 #28
0
        /// <summary>
        /// Gets a cold staking account.
        /// </summary>
        /// <remarks>
        /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s
        /// with indexes starting from the value defined in <see cref="Wallet.SpecialPurposeAccountIndexesStart"/>.
        /// </para><para>
        /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when
        /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this
        /// method.
        /// </para></remarks>
        /// <param name="wallet">The wallet where we wish to create the account.</param>
        /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param>
        /// <returns>The cold staking account or <c>null</c> if the account does not exist.</returns>
        internal HdAccount GetColdStakingAccount(Wallet.Wallet wallet, bool isColdWalletAccount)
        {
            HdAccount account = wallet.GetAccount(isColdWalletAccount ? ColdWalletAccountName : HotWalletAccountName);

            if (account == null)
            {
                this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null");
                return(null);
            }

            this.logger.LogTrace("(-):'{0}'", account.Name);
            return(account);
        }
コード例 #29
0
        /// <summary>
        /// Returns information related to cold staking.
        /// </summary>
        /// <param name="walletName">The wallet to return the information for.</param>
        /// <returns>A <see cref="Models.GetColdStakingInfoResponse"/> object containing the information.</returns>
        internal Models.GetColdStakingInfoResponse GetColdStakingInfo(string walletName)
        {
            Wallet.Wallet wallet = this.GetWalletByName(walletName);

            var response = new Models.GetColdStakingInfoResponse()
            {
                ColdWalletAccountExists = this.GetColdStakingAccount(wallet, true) != null,
                HotWalletAccountExists  = this.GetColdStakingAccount(wallet, false) != null
            };

            this.logger.LogTrace("(-):'{0}'", response);
            return(response);
        }
コード例 #30
0
        /// <summary>
        /// Gets a cold staking account.
        /// </summary>
        /// <remarks>
        /// <para>In order to keep track of cold staking addresses and balances we are using <see cref="HdAccount"/>'s
        /// with indexes starting from the value defined in <see cref="Wallet.SpecialPurposeAccountIndexesStart"/>.
        /// </para><para>
        /// We are using two such accounts, one when the wallet is in the role of cold wallet, and another one when
        /// the wallet is in the role of hot wallet. For this reason we specify the required account when calling this
        /// method.
        /// </para></remarks>
        /// <param name="wallet">The wallet where we wish to create the account.</param>
        /// <param name="isColdWalletAccount">Indicates whether we need the cold wallet account (versus the hot wallet account).</param>
        /// <returns>The cold staking account or <c>null</c> if the account does not exist.</returns>
        public HdAccount GetColdStakingAccount(Wallet.Wallet wallet, bool isColdWalletAccount)
        {
            var       coinType = wallet.Network.Consensus.CoinType;
            HdAccount account  = wallet.GetAccount(isColdWalletAccount ? ColdWalletAccountName : HotWalletAccountName);

            if (account == null)
            {
                this.logger.LogTrace("(-)[ACCOUNT_DOES_NOT_EXIST]:null");
                return(null);
            }

            this.logger.LogTrace("(-):'{0}'", account.Name);
            return(account);
        }