public void WhenRefreshWhitelist_AndInactivePeersInWhitelist_ThenWhitelistDoesNotContainInactivePeers() { // Arrange. Mock <IDateTimeProvider> mockDateTimeProvider = new Mock <IDateTimeProvider>(); Mock <ILogger> mockLogger = new Mock <ILogger>(); Mock <ILoggerFactory> mockLoggerFactory = new Mock <ILoggerFactory>(); mockLoggerFactory.Setup(l => l.CreateLogger(It.IsAny <string>())).Returns(mockLogger.Object); ILoggerFactory loggerFactory = mockLoggerFactory.Object; mockDateTimeProvider.Setup(d => d.GetTimeOffset()).Returns(new DateTimeOffset(new DateTime(2017, 8, 30, 1, 2, 3))).Verifiable(); IDateTimeProvider dateTimeProvider = mockDateTimeProvider.Object; int inactiveTimePeriod = 3000; IPAddress activeIpAddressOne = IPAddress.Parse("::ffff:192.168.0.1"); NetworkAddress activeNetworkAddressOne = new NetworkAddress(activeIpAddressOne, 80); IPAddress activeIpAddressTwo = IPAddress.Parse("::ffff:192.168.0.2"); NetworkAddress activeNetworkAddressTwo = new NetworkAddress(activeIpAddressTwo, 80); IPAddress activeIpAddressThree = IPAddress.Parse("::ffff:192.168.0.3"); NetworkAddress activeNetworkAddressThree = new NetworkAddress(activeIpAddressThree, 80); IPAddress activeIpAddressFour = IPAddress.Parse("::ffff:192.168.0.4"); NetworkAddress activeNetworkAddressFour = new NetworkAddress(activeIpAddressFour, 80); List <Tuple <NetworkAddress, DateTimeOffset> > activeTestDataSet = new List <Tuple <NetworkAddress, DateTimeOffset> >() { new Tuple <NetworkAddress, DateTimeOffset> (activeNetworkAddressOne, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(10)), new Tuple <NetworkAddress, DateTimeOffset>(activeNetworkAddressTwo, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(20)), new Tuple <NetworkAddress, DateTimeOffset>(activeNetworkAddressThree, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(30)), new Tuple <NetworkAddress, DateTimeOffset>(activeNetworkAddressFour, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(40)) }; IPAddress inactiveIpAddressOne = IPAddress.Parse("::ffff:192.168.100.1"); NetworkAddress inactiveNetworkAddressOne = new NetworkAddress(inactiveIpAddressOne, 80); IPAddress inactiveIpAddressTwo = IPAddress.Parse("::ffff:192.168.100.2"); NetworkAddress inactiveNetworkAddressTwo = new NetworkAddress(inactiveIpAddressTwo, 80); IPAddress inactiveIpAddressThree = IPAddress.Parse("::ffff:192.168.100.3"); NetworkAddress inactiveNetworkAddressThree = new NetworkAddress(inactiveIpAddressThree, 80); List <Tuple <NetworkAddress, DateTimeOffset> > inactiveTestDataSet = new List <Tuple <NetworkAddress, DateTimeOffset> >() { new Tuple <NetworkAddress, DateTimeOffset> (inactiveNetworkAddressOne, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(-10)), new Tuple <NetworkAddress, DateTimeOffset>(inactiveNetworkAddressTwo, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(-20)), new Tuple <NetworkAddress, DateTimeOffset>(inactiveNetworkAddressThree, dateTimeProvider.GetTimeOffset().AddSeconds(-inactiveTimePeriod).AddSeconds(-30)) }; IPeerAddressManager peerAddressManager = this.CreateTestPeerAddressManager(activeTestDataSet.Concat(inactiveTestDataSet).ToList()); IMasterFile spiedMasterFile = null; Mock <IDnsServer> mockDnsServer = new Mock <IDnsServer>(); mockDnsServer.Setup(d => d.SwapMasterfile(It.IsAny <IMasterFile>())) .Callback <IMasterFile>(m => { spiedMasterFile = m; }) .Verifiable(); NodeSettings nodeSettings = NodeSettings.Default(); DnsSettings dnsSettings = new Mock <DnsSettings>().Object; dnsSettings.DnsPeerBlacklistThresholdInSeconds = inactiveTimePeriod; dnsSettings.DnsHostName = "stratis.test.com"; ConnectionManagerSettings connectionSettings = new ConnectionManagerSettings(); connectionSettings.Load(nodeSettings); WhitelistManager whitelistManager = new WhitelistManager(dateTimeProvider, loggerFactory, peerAddressManager, mockDnsServer.Object, connectionSettings, dnsSettings); // Act. whitelistManager.RefreshWhitelist(); // Assert. spiedMasterFile.Should().NotBeNull(); Question question = new Question(new Domain(dnsSettings.DnsHostName), RecordType.AAAA); IList <IResourceRecord> resourceRecords = spiedMasterFile.Get(question); resourceRecords.Should().NotBeNullOrEmpty(); IList <IPAddressResourceRecord> ipAddressResourceRecords = resourceRecords.OfType <IPAddressResourceRecord>().ToList(); ipAddressResourceRecords.Should().HaveSameCount(activeTestDataSet); foreach (Tuple <NetworkAddress, DateTimeOffset> testData in activeTestDataSet) { ipAddressResourceRecords.SingleOrDefault(i => i.IPAddress.Equals(testData.Item1.Endpoint.Address)).Should().NotBeNull("the ip address is active and should be in DNS"); } foreach (Tuple <NetworkAddress, DateTimeOffset> testData in inactiveTestDataSet) { ipAddressResourceRecords.SingleOrDefault(i => i.IPAddress.Equals(testData.Item1.Endpoint.Address)).Should().BeNull("the ip address is inactive and should not be returned from DNS"); } }
public void BuildTransactionNoChangeAdressesLeftCreatesNewChangeAddress() { DataFolder dataFolder = CreateDataFolder(this); var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var address = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = spendingKeys.Address.ToString(), Pubkey = spendingKeys.PubKey.ScriptPubKey, ScriptPubKey = spendingKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var chain = new ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); var addressTransaction = address.Transactions.First(); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress>() }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chain, NodeSettings.Default(), dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; var context = CreateContext(walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0); var transactionResult = walletTransactionHandler.BuildTransaction(context); var result = new Transaction(transactionResult.ToHex()); var expectedChangeAddressKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "1/0"); Assert.Single(result.Inputs); Assert.Equal(addressTransaction.Id, result.Inputs[0].PrevOut.Hash); Assert.Equal(2, result.Outputs.Count); var output = result.Outputs[0]; Assert.Equal((addressTransaction.Amount - context.TransactionFee - 7500), output.Value); Assert.Equal(expectedChangeAddressKeys.Address.ScriptPubKey, output.ScriptPubKey); output = result.Outputs[1]; Assert.Equal(7500, output.Value); Assert.Equal(destinationKeys.PubKey.ScriptPubKey, output.ScriptPubKey); Assert.Equal(addressTransaction.Amount - context.TransactionFee, result.TotalOut); Assert.NotNull(transactionResult.GetHash()); Assert.Equal(result.GetHash(), transactionResult.GetHash()); }
public void Given_AnInvalidAccountIsUsed_When_GetMaximumSpendableAmountIsCalled_Then_AnExceptionIsThrown() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new Mock <ConcurrentChain>().Object, NodeSettings.Default(), dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, It.IsAny <ConcurrentChain>(), walletManager, It.IsAny <WalletFeePolicy>(), Network.Main); var wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { WalletTestsHelpers.CreateAccount("account 1") } }); walletManager.Wallets.Add(wallet); Exception ex = Assert.Throws <WalletException>(() => walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "noaccount"), FeeType.Low, true)); Assert.NotNull(ex); Assert.NotNull(ex.Message); Assert.NotEqual(string.Empty, ex.Message); Assert.IsType <WalletException>(ex); }
public void VerifyCheckpoints_StratisMainnet() { var verifyableCheckpoints = new Dictionary <int, CheckpointInfo> { { 0, new CheckpointInfo(new uint256("0x0000066e91e46e5a264d42c89e1204963b2ee6be230b443e9159020539d972af"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, { 2, new CheckpointInfo(new uint256("0xbca5936f638181e74a5f1e9999c95b0ce77da48c2688399e72bcc53a00c61eff"), new uint256("0x7d61c139a471821caa6b7635a4636e90afcfe5e195040aecbc1ad7d24924db1e")) }, // Premine { 50, new CheckpointInfo(new uint256("0x0353b43f4ce80bf24578e7c0141d90d7962fb3a4b4b4e5a17925ca95e943b816"), new uint256("0x7c2af3b10d13f9d2bc6063baaf7f0860d90d870c994378144f9bf85d0d555061")) }, { 100, new CheckpointInfo(new uint256("0x688468a8aa48cd1c2197e42e7d8acd42760b7e2ac4bcab9d18ac149a673e16f6"), new uint256("0xcf2b1e9e76aaa3d96f255783eb2d907bf6ccb9c1deeb3617149278f0e4a1ab1b")) }, { 150, new CheckpointInfo(new uint256("0xe4ae9663519abec15e28f68bdb2cb89a739aee22f53d1573048d69141db6ee5d"), new uint256("0xa6c17173e958dc716cc0892ce33dad8bc327963d78a16c436264ceae43d584ce")) }, { 127500, new CheckpointInfo(new uint256("0x4773ca7512489df22de03aa03938412fab5b46154b05df004b97bcbeaa184078"), new uint256("0x619743c02ebaff06b90fcc5c60c52dba8aa3fdb6ba3800aae697cbb3c5483f17")) }, { 128943, new CheckpointInfo(new uint256("0x36bcaa27a53d3adf22b2064150a297adb02ac39c24263a5ceb73856832d49679"), new uint256("0xa3a6fd04e41fcaae411a3990aaabcf5e086d2d06c72c849182b27b4de8c2c42a")) }, { 136601, new CheckpointInfo(new uint256("0xf5c5210c55ff1ef9c04715420a82728e1647f3473e31dc478b3745a97b4a6d10"), new uint256("0x42058fabe21f7b118a9e358eaf9ef574dadefd024244899e71f2f6d618161e16")) }, // Hardfork to V2 - Drifting Bug Fix { 170000, new CheckpointInfo(new uint256("0x22b10952e0cf7e85bfc81c38f1490708f195bff34d2951d193cc20e9ca1fc9d5"), new uint256("0xa4942a6c99cba397cf2b18e4b912930fe1e64a7413c3d97c5a926c2af9073091")) }, { 200000, new CheckpointInfo(new uint256("0x2391dd493be5d0ff0ef57c3b08c73eefeecc2701b80f983054bb262f7a146989"), new uint256("0x253152d129e82c30c584197deb6833502eff3ec2f30014008f75842d7bb48453")) }, { 250000, new CheckpointInfo(new uint256("0x681c70fab7c1527246138f0cf937f0eb013838b929fbe9a831af02a60fc4bf55"), new uint256("0x24eed95e00c90618aa9d137d2ee273267285c444c9cde62a25a3e880c98a3685")) }, { 300000, new CheckpointInfo(new uint256("0xd10ca8c2f065a49ae566c7c9d7a2030f4b8b7f71e4c6fc6b2a02509f94cdcd44"), new uint256("0x39c4dd765b49652935524248b4de4ccb604df086d0723bcd81faf5d1c2489304")) }, { 350000, new CheckpointInfo(new uint256("0xe2b76d1a068c4342f91db7b89b66e0f2146d3a4706c21f3a262737bb7339253a"), new uint256("0xd1dd94985eaaa028c893687a7ddf89143dcf0176918f958c2d01f33d64910399")) }, { 390000, new CheckpointInfo(new uint256("0x4682737abc2a3257fdf4c3c119deb09cbac75981969e2ffa998b4f76b7c657bb"), new uint256("0xd84b204ee94499ff65262328a428851fb4f4d2741e928cdd088fdf1deb5413b8")) }, { 394000, new CheckpointInfo(new uint256("0x42857fa2bc15d45cdcaae83411f755b95985da1cb464ee23f6d40936df523e9f"), new uint256("0x2314b336906a2ed2a39cbdf6fc0622530709c62dbb3a3729de17154fc9d1a7c4")) }, { 400000, new CheckpointInfo(new uint256("0x4938d5cf450b4e2d9072558971223555055aa3987b634a8bb2e97f95d1a3c501"), new uint256("0x1756c127f0ac7029cf095a6c3ed9b7d206d0e36744d8b3cef306002f9f901a31")) }, { 450000, new CheckpointInfo(new uint256("0x7699e07ac18c25ac042deb6b985e2decfd6034cb6361de2152a2d704ef785bac"), new uint256("0xa140a86a03c4f852d8a651f6386a02a0262e7bbf841ede8b54541c011c51ba0e")) }, { 500000, new CheckpointInfo(new uint256("0x558700d99239e64017d10910466719fe1edc6f863bd3de254b89ba828818ea47"), new uint256("0x6a0b7dab4a7aa9ea2477cddffe5a976c9423454835054a39c19d37613002638f")) }, { 550000, new CheckpointInfo(new uint256("0x83d074957f509772b1fbbfaeb7bdc52932c540d54e205b92a7d4e92f68957eb4"), new uint256("0x012b63ad7d50606f2cafb1a7806ea90f4981c56b5407725aeeff34e3c584433c")) }, { 600000, new CheckpointInfo(new uint256("0xcd05c75c0c47060d78508095c0766452f80e2defb6a4641ac603742a2ccf2207"), new uint256("0x1f25507e09b199a71d5879811376856e5fb3da1da3d522204c017eec3b6c4dad")) }, { 650000, new CheckpointInfo(new uint256("0xa2814a439b33662f43bdbc8ab089d368524975bb53a08326395e57456cba8d39"), new uint256("0x192a2ef70e2280cf05aa5655f496a109b2445d0ddda62531e9bce9aaced1fe54")) }, { 700000, new CheckpointInfo(new uint256("0x782b2506bb67bb448ff56aa946f7aad6b63a6b27d8c5818725a56b568f25b9ce"), new uint256("0xf23dc64b130d80790a83a86913f619afaeef10e1fd24e4b42af9387ec935edd6")) }, { 750000, new CheckpointInfo(new uint256("0x4db98bd41a2f9ee845cc89ac03109686f615f4d0dcd81e0488005c1616fa692c"), new uint256("0x9f620af75bc27a0e4b503deaf7f052ba112a49bb74fb6446350642bc2ac9d93b")) }, { 800000, new CheckpointInfo(new uint256("0x161da1d97d35d6897dbdae110617bb839805f8b02d33ac23d227a87cacbfac78"), new uint256("0xe95049a313345f26bfa90094ceb6400f43359fc43fc5f1471918d98bc4ab3bac")) }, { 850000, new CheckpointInfo(new uint256("0xc3a249b01795b22858aa00fd0973471fcd769a14f4f9cf0abe6651ac3e6ade19"), new uint256("0x5de8766ed4cfcc3ce9d74f38196596c6f91b9ff62cbd20abbfa991dca54d2bd4")) } }; var checkpoints = new Checkpoints(KnownNetworks.StratisMain, new ConsensusSettings(NodeSettings.Default(KnownNetworks.StratisTest)) { UseCheckpoints = true }); VerifyCheckpoints(checkpoints, verifyableCheckpoints); }
public void GetLastCheckPointHeight_BitcoinRegTestNet_DoesNotLoadCheckpoints() { var checkpoints = new Checkpoints(KnownNetworks.RegTest, new ConsensusSettings(NodeSettings.Default(KnownNetworks.StratisTest)) { UseCheckpoints = true }); int result = checkpoints.GetLastCheckpointHeight(); Assert.Equal(0, result); }
private static MempoolManager CreateTestMempool(NodeSettings settings, out TxMempool txMemPool) { IDateTimeProvider dateTimeProvider = DateTimeProvider.Default; txMemPool = new TxMempool(new FeeRate(1000), dateTimeProvider, new BlockPolicyEstimator(new FeeRate(1000), NodeSettings.Default(), new LoggerFactory()), new LoggerFactory()); var mempoolLock = new MempoolAsyncLock(); var coins = new InMemoryCoinView(settings.Network.GenesisHash); var chain = new ConcurrentChain(Network.Main.GetGenesis().Header); var mempoolPersistence = new MempoolPersistence(settings, new LoggerFactory()); NBitcoin.Network.Main.Consensus.Options = new PosConsensusOptions(); var consensusValidator = new PowConsensusValidator(NBitcoin.Network.Main); var mempoolValidator = new MempoolValidator(txMemPool, mempoolLock, consensusValidator, dateTimeProvider, settings, chain, coins, new LoggerFactory()); var mempoolOrphans = new MempoolOrphans(mempoolLock, txMemPool, chain, new Bitcoin.Signals.Signals(), mempoolValidator, consensusValidator, coins, dateTimeProvider, settings, new LoggerFactory()); return(new MempoolManager(mempoolLock, txMemPool, mempoolValidator, mempoolOrphans, dateTimeProvider, settings, mempoolPersistence, new LoggerFactory())); }
public void GetCheckPoint_CheckpointExists_PoSChain_ReturnsCheckpoint() { var checkpoints = new Checkpoints(KnownNetworks.StratisMain, new ConsensusSettings(NodeSettings.Default(KnownNetworks.StratisTest)) { UseCheckpoints = true }); CheckpointInfo result = checkpoints.GetCheckpoint(2); Assert.Equal(new uint256("0xbca5936f638181e74a5f1e9999c95b0ce77da48c2688399e72bcc53a00c61eff"), result.Hash); Assert.Equal(new uint256("0x7d61c139a471821caa6b7635a4636e90afcfe5e195040aecbc1ad7d24924db1e"), result.StakeModifierV2); }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoTransactions_Then_MaxAmountReturnsAsZero() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, new ConcurrentChain(this.Network), NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), this.Network, this.standardTransactionPolicy); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); walletManager.Wallets.Add(wallet); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, true); Assert.Equal(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void BuildTransactionFeeTooLowThrowsWalletException() { Assert.Throws <WalletException>(() => { var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(0)); Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); (ExtKey ExtKey, string ExtPubKey)accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); (PubKey PubKey, BitcoinPubKeyAddress Address)spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); (PubKey PubKey, BitcoinPubKeyAddress Address)changeKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "1/0"); var address = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = spendingKeys.Address.ToString(), Pubkey = spendingKeys.PubKey.ScriptPubKey, ScriptPubKey = spendingKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var chain = new ConcurrentChain(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress> { new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/1/0", Address = changeKeys.Address.ToString(), Pubkey = changeKeys.PubKey.ScriptPubKey, ScriptPubKey = changeKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() } } }); string dataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionFeeTooLowThrowsWalletException"; var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, NodeSettings.Default(), new Mock <WalletSettings>().Object, new DataFolder(new NodeSettings(args: new string[] { $"-datadir={dataDir}" }).DataDir), walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(this.Network, walletReference, "password", destinationKeys.PubKey.ScriptPubKey, new Money(7500), FeeType.Low, 0)); }); }
public void BuildTransactionNoSpendableTransactionsThrowsWalletException() { Assert.Throws <WalletException>(() => { Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Add( new HdAccount { Name = "account1", ExternalAddresses = new List <HdAddress>(), InternalAddresses = new List <HdAddress>() }); BlockHeader blockHeader = this.Network.Consensus.ConsensusFactory.CreateBlockHeader(); var chain = new ConcurrentChain(this.Network, new ChainedHeader(blockHeader, blockHeader.GetHash(), 1)); string dataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionNoSpendableTransactionsThrowsWalletException"; var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, NodeSettings.Default(), new Mock <WalletSettings>().Object, new DataFolder(new NodeSettings(args: new string[] { $"-datadir={dataDir}" }).DataDir), new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default, new ScriptAddressReader()); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, new Mock <IWalletFeePolicy>().Object, this.Network, new StandardTransactionPolicy(this.Network)); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(this.Network, walletReference, "password", new Script(), new Money(500), FeeType.Medium, 2)); }); }
public void Given_GetMaximumSpendableAmountIsCalled_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsTheSumOfUnconfirmedTxs() { DataFolder dataFolder = CreateDataFolder(this); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, new ConcurrentChain(this.Network), NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null, null, null, new Key().ScriptPubKey)); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null, null, null, new Key().ScriptPubKey)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null, null, null, new Key().ScriptPubKey)); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null, null, null, new Key().ScriptPubKey)); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); walletManager.Wallets.Add(wallet); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, true); Assert.Equal(new Money(165000), result.max + result.fee); }
WalletAccountReference walletReference) SetupWallet() { DataFolder dataFolder = CreateDataFolder(this); Wallet wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); (ExtKey ExtKey, string ExtPubKey)accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); (PubKey PubKey, BitcoinPubKeyAddress Address)spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); (PubKey PubKey, BitcoinPubKeyAddress Address)destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var address = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = spendingKeys.Address.ToString(), Pubkey = spendingKeys.PubKey.ScriptPubKey, ScriptPubKey = spendingKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; var chain = new ConcurrentChain(wallet.Network); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address); TransactionData addressTransaction = address.Transactions.First(); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress>() }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())) .Returns(new FeeRate(20000)); var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, chain, NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default, this.scriptAddressReader); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, walletFeePolicy.Object, this.Network, this.standardTransactionPolicy); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; return(wallet, accountKeys, destinationKeys, addressTransaction, walletTransactionHandler, walletReference); }
/// <summary> /// Initializes an instance of the object from the default configuration. /// </summary> public MempoolSettings() : this(NodeSettings.Default()) { }
public void Given_GetMaximumSpendableAmountIsCalledForConfirmedTransactions_When_ThereAreNoConfirmedSpendableFound_Then_MaxAmountReturnsAsZero() { DataFolder dataFolder = CreateDataFolder(this); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, new ConcurrentChain(Network.Main), NodeSettings.Default(), new Mock <WalletSettings>().Object, dataFolder, new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, walletManager, It.IsAny <WalletFeePolicy>(), Network.Main); HdAccount account = WalletTestsHelpers.CreateAccount("account 1"); HdAddress accountAddress1 = WalletTestsHelpers.CreateAddress(); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(1), new Money(15000), null)); accountAddress1.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(2), new Money(10000), null)); HdAddress accountAddress2 = WalletTestsHelpers.CreateAddress(); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(3), new Money(20000), null)); accountAddress2.Transactions.Add(WalletTestsHelpers.CreateTransaction(new uint256(4), new Money(120000), null)); account.ExternalAddresses.Add(accountAddress1); account.InternalAddresses.Add(accountAddress2); Wallet wallet = WalletTestsHelpers.CreateWallet("wallet1"); wallet.AccountsRoot.Add(new AccountRoot() { Accounts = new List <HdAccount> { account } }); walletManager.Wallets.Add(wallet); (Money max, Money fee)result = walletTransactionHandler.GetMaximumSpendableAmount(new WalletAccountReference("wallet1", "account 1"), FeeType.Low, false); Assert.Equal(Money.Zero, result.max); Assert.Equal(Money.Zero, result.fee); }
public void MempoolAncestorIndexingTest() { var settings = NodeSettings.Default(); var pool = new TxMempool(DateTimeProvider.Default, new BlockPolicyEstimator(new MempoolSettings(settings), settings.LoggerFactory, settings), settings.LoggerFactory, settings); var entry = new TestMemPoolEntryHelper(); /* 3rd highest fee */ Transaction tx1 = new Transaction(); tx1.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx1.GetHash(), entry.Fee(new Money(10000L)).Priority(10.0).FromTx(tx1)); /* highest fee */ Transaction tx2 = new Transaction(); tx2.AddOutput(new TxOut(new Money(2 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx2.GetHash(), entry.Fee(new Money(20000L)).Priority(9.0).FromTx(tx2)); var tx2Size = tx2.GetVirtualSize(); /* lowest fee */ Transaction tx3 = new Transaction(); tx3.AddOutput(new TxOut(new Money(5 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx3.GetHash(), entry.Fee(new Money(0L)).Priority(100.0).FromTx(tx3)); /* 2nd highest fee */ Transaction tx4 = new Transaction(); tx4.AddOutput(new TxOut(new Money(6 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx4.GetHash(), entry.Fee(new Money(15000L)).Priority(1.0).FromTx(tx4)); /* equal fee rate to tx1, but newer */ Transaction tx5 = new Transaction(); tx5.AddOutput(new TxOut(new Money(11 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx5.GetHash(), entry.Fee(new Money(10000L)).Priority(1.0).FromTx(tx5)); // assert size Assert.Equal(5, pool.Size); List <string> sortedOrder = new List <string>(5); sortedOrder.Insert(0, tx2.GetHash().ToString()); // 20000 sortedOrder.Insert(1, tx4.GetHash().ToString()); // 15000 // tx1 and tx5 are both 10000 // Ties are broken by hash, not timestamp, so determine which // hash comes first. if (tx1.GetHash() < tx5.GetHash()) { sortedOrder.Insert(2, tx1.GetHash().ToString()); sortedOrder.Insert(3, tx5.GetHash().ToString()); } else { sortedOrder.Insert(2, tx5.GetHash().ToString()); sortedOrder.Insert(3, tx1.GetHash().ToString()); } sortedOrder.Insert(4, tx3.GetHash().ToString()); // 0 this.CheckSort(pool, pool.MapTx.AncestorScore.ToList(), sortedOrder); /* low fee parent with high fee child */ /* tx6 (0) -> tx7 (high) */ Transaction tx6 = new Transaction(); tx6.AddOutput(new TxOut(new Money(20 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx6.GetHash(), entry.Fee(new Money(0L)).FromTx(tx6)); var tx6Size = tx6.GetVirtualSize(); Assert.Equal(6, pool.Size); // Ties are broken by hash if (tx3.GetHash() < tx6.GetHash()) { sortedOrder.Add(tx6.GetHash().ToString()); } else { sortedOrder.Insert(sortedOrder.Count - 1, tx6.GetHash().ToString()); } this.CheckSort(pool, pool.MapTx.AncestorScore.ToList(), sortedOrder); Transaction tx7 = new Transaction(); tx7.AddInput(new TxIn(new OutPoint(tx6.GetHash(), 0), new Script(OpcodeType.OP_11))); tx7.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); var tx7Size = tx7.GetVirtualSize(); Money fee = (20000 / tx2Size) * (tx7Size + tx6Size) - 1; pool.AddUnchecked(tx7.GetHash(), entry.Fee(fee).FromTx(tx7)); Assert.Equal(7, pool.Size); sortedOrder.Insert(1, tx7.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.AncestorScore.ToList(), sortedOrder); /* after tx6 is mined, tx7 should move up in the sort */ List <Transaction> vtx = new List <Transaction>(new[] { tx6 }); pool.RemoveForBlock(vtx, 1); sortedOrder.RemoveAt(1); // Ties are broken by hash if (tx3.GetHash() < tx6.GetHash()) { sortedOrder.Remove(sortedOrder.Last()); } else { sortedOrder.RemoveAt(sortedOrder.Count - 2); } sortedOrder.Insert(0, tx7.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.AncestorScore.ToList(), sortedOrder); }
public static PowBlockDefinition AssemblerForTest(TestContext testContext) { return(new PowBlockDefinition(testContext.consensus, testContext.DateTimeProvider, new LoggerFactory(), testContext.mempool, testContext.mempoolLock, new MinerSettings(NodeSettings.Default(testContext.network)), testContext.network, testContext.ConsensusRules, new NodeDeployments(testContext.network, testContext.ChainIndexer))); }
public void MempoolSizeLimitTest() { var settings = NodeSettings.Default(); var dateTimeSet = new DateTimeProviderSet(); var pool = new TxMempool(dateTimeSet, new BlockPolicyEstimator(new MempoolSettings(settings), settings.LoggerFactory, settings), settings.LoggerFactory, settings); var entry = new TestMemPoolEntryHelper(); entry.Priority(10.0); Transaction tx1 = new Transaction(); tx1.AddInput(new TxIn(new Script(OpcodeType.OP_1))); tx1.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_1, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx1.GetHash(), entry.Fee(10000L).FromTx(tx1, pool)); Transaction tx2 = new Transaction(); tx2.AddInput(new TxIn(new Script(OpcodeType.OP_2))); tx2.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_2, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx2.GetHash(), entry.Fee(5000L).FromTx(tx2, pool)); pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing Assert.True(pool.Exists(tx1.GetHash())); Assert.True(pool.Exists(tx2.GetHash())); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction Assert.True(pool.Exists(tx1.GetHash())); Assert.True(!pool.Exists(tx2.GetHash())); pool.AddUnchecked(tx2.GetHash(), entry.FromTx(tx2, pool)); Transaction tx3 = new Transaction(); tx3.AddInput(new TxIn(new OutPoint(tx2.GetHash(), 0), new Script(OpcodeType.OP_2))); tx3.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_3, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx3.GetHash(), entry.Fee(20000L).FromTx(tx3, pool)); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP) Assert.True(!pool.Exists(tx1.GetHash())); Assert.True(pool.Exists(tx2.GetHash())); Assert.True(pool.Exists(tx3.GetHash())); pool.TrimToSize(tx1.GetVirtualSize()); // mempool is limited to tx1's size in memory usage, so nothing fits Assert.True(!pool.Exists(tx1.GetHash())); Assert.True(!pool.Exists(tx2.GetHash())); Assert.True(!pool.Exists(tx3.GetHash())); FeeRate maxFeeRateRemoved = new FeeRate(25000, tx3.GetVirtualSize() + tx2.GetVirtualSize()); Assert.Equal(pool.GetMinFee(1).FeePerK, maxFeeRateRemoved.FeePerK + 1000); Transaction tx4 = new Transaction(); tx4.AddInput(new TxIn(new Script(OpcodeType.OP_4))); tx4.AddInput(new TxIn(new Script(OpcodeType.OP_4))); tx4.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_4, OpcodeType.OP_EQUAL))); tx4.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_4, OpcodeType.OP_EQUAL))); Transaction tx5 = new Transaction(); tx5.AddInput(new TxIn(new OutPoint(tx4.GetHash(), 0), new Script(OpcodeType.OP_4))); tx5.AddInput(new TxIn(new Script(OpcodeType.OP_5))); tx5.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_5, OpcodeType.OP_EQUAL))); tx5.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_5, OpcodeType.OP_EQUAL))); Transaction tx6 = new Transaction(); tx6.AddInput(new TxIn(new OutPoint(tx4.GetHash(), 0), new Script(OpcodeType.OP_4))); tx6.AddInput(new TxIn(new Script(OpcodeType.OP_6))); tx6.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_6, OpcodeType.OP_EQUAL))); tx6.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_6, OpcodeType.OP_EQUAL))); Transaction tx7 = new Transaction(); tx7.AddInput(new TxIn(new OutPoint(tx5.GetHash(), 0), new Script(OpcodeType.OP_5))); tx7.AddInput(new TxIn(new OutPoint(tx6.GetHash(), 0), new Script(OpcodeType.OP_6))); tx7.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_7, OpcodeType.OP_EQUAL))); tx7.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_7, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx4.GetHash(), entry.Fee(7000L).FromTx(tx4, pool)); pool.AddUnchecked(tx5.GetHash(), entry.Fee(1000L).FromTx(tx5, pool)); pool.AddUnchecked(tx6.GetHash(), entry.Fee(1100L).FromTx(tx6, pool)); pool.AddUnchecked(tx7.GetHash(), entry.Fee(9000L).FromTx(tx7, pool)); // we only require this remove, at max, 2 txn, because its not clear what we're really optimizing for aside from that pool.TrimToSize(pool.DynamicMemoryUsage() - 1); Assert.True(pool.Exists(tx4.GetHash())); Assert.True(pool.Exists(tx6.GetHash())); Assert.True(!pool.Exists(tx7.GetHash())); if (!pool.Exists(tx5.GetHash())) { pool.AddUnchecked(tx5.GetHash(), entry.Fee(1000L).FromTx(tx5, pool)); } pool.AddUnchecked(tx7.GetHash(), entry.Fee(9000L).FromTx(tx7, pool)); pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7 Assert.True(pool.Exists(tx4.GetHash())); Assert.True(!pool.Exists(tx5.GetHash())); Assert.True(pool.Exists(tx6.GetHash())); Assert.True(!pool.Exists(tx7.GetHash())); pool.AddUnchecked(tx5.GetHash(), entry.Fee(1000L).FromTx(tx5, pool)); pool.AddUnchecked(tx7.GetHash(), entry.Fee(9000L).FromTx(tx7, pool)); List <Transaction> vtx = new List <Transaction>(); dateTimeSet.time = 42 + TxMempool.RollingFeeHalflife; Assert.Equal(pool.GetMinFee(1).FeePerK.Satoshi, maxFeeRateRemoved.FeePerK.Satoshi + 1000); // ... we should keep the same min fee until we get a block pool.RemoveForBlock(vtx, 1); dateTimeSet.time = 42 + 2 * +TxMempool.RollingFeeHalflife; Assert.Equal(pool.GetMinFee(1).FeePerK.Satoshi, (maxFeeRateRemoved.FeePerK.Satoshi + 1000) / 2); // ... then feerate should drop 1/2 each halflife dateTimeSet.time = 42 + 2 * TxMempool.RollingFeeHalflife + TxMempool.RollingFeeHalflife / 2; Assert.Equal(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).FeePerK.Satoshi, (maxFeeRateRemoved.FeePerK.Satoshi + 1000) / 4); // ... with a 1/2 halflife when mempool is < 1/2 its target size dateTimeSet.time = 42 + 2 * TxMempool.RollingFeeHalflife + TxMempool.RollingFeeHalflife / 2 + TxMempool.RollingFeeHalflife / 4; Assert.Equal(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).FeePerK.Satoshi, (maxFeeRateRemoved.FeePerK.Satoshi + 1000) / 8); // ... with a 1/4 halflife when mempool is < 1/4 its target size dateTimeSet.time = 42 + 7 * TxMempool.RollingFeeHalflife + TxMempool.RollingFeeHalflife / 2 + TxMempool.RollingFeeHalflife / 4; Assert.Equal(1000, pool.GetMinFee(1).FeePerK.Satoshi); // ... but feerate should never drop below 1000 dateTimeSet.time = 42 + 8 * TxMempool.RollingFeeHalflife + TxMempool.RollingFeeHalflife / 2 + TxMempool.RollingFeeHalflife / 4; Assert.Equal(0, pool.GetMinFee(1).FeePerK); // ... unless it has gone all the way to 0 (after getting past 1000/2) }
public void EnsureTimestampIsNotTooNew() { long timestamp = new DateTimeProvider().GetUtcNow().ToUnixTimestamp() / this.consensusOptions.TargetSpacingSeconds * this.consensusOptions.TargetSpacingSeconds; DateTime time = DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime; // Pretend we receive the next block right on its timestamp var provider = new Mock <IDateTimeProvider>(); provider.Setup(x => x.GetAdjustedTime()).Returns(time + TimeSpan.FromSeconds(this.consensusOptions.TargetSpacingSeconds)); this.rulesEngine = new PoAConsensusRuleEngine(this.network, this.loggerFactory, provider.Object, this.ChainIndexer, new NodeDeployments(this.network, this.ChainIndexer), this.consensusSettings, new Checkpoints(this.network, this.consensusSettings), new Mock <ICoinView>().Object, new ChainState(), new InvalidBlockHashStore(provider.Object), new NodeStats(provider.Object, NodeSettings.Default(this.network), new Mock <IVersionProvider>().Object), this.slotsManager, this.poaHeaderValidator, this.votingManager, this.federationManager, this.asyncProvider, new ConsensusRulesContainer(), null); this.timeChecksRule.Parent = this.rulesEngine; this.timeChecksRule.Initialize(); var validationContext = new ValidationContext() { ChainedHeaderToValidate = this.currentHeader }; var ruleContext = new RuleContext(validationContext, time); ChainedHeader prevHeader = this.currentHeader.Previous; prevHeader.Header.BlockTime = time; // There is no "valid future offset" as the time is restricted to be accurate within 1 target spacing. this.currentHeader.Header.BlockTime = prevHeader.Header.BlockTime + TimeSpan.FromSeconds(this.consensusOptions.TargetSpacingSeconds); this.timeChecksRule.Run(ruleContext); // Send a block too far into the future, more than a targetspacing away this.currentHeader.Header.BlockTime = this.currentHeader.Header.BlockTime + TimeSpan.FromSeconds(this.consensusOptions.TargetSpacingSeconds); Assert.Throws <ConsensusErrorException>(() => this.timeChecksRule.Run(ruleContext)); try { this.timeChecksRule.Run(ruleContext); } catch (ConsensusErrorException exception) { Assert.Equal(ConsensusErrors.TimeTooNew, exception.ConsensusError); } }
public void WhiteListedEndpoint_CanBeMappedAndRoutedTo_OtherNode() { IPEndPoint endpointA = null; IPEndPoint endpointB = null; IPEndPoint endpointOut = null; var connectionManagerSettings = new ConnectionManagerSettings(NodeSettings.Default(this.Network)); var networkEndpoints = connectionManagerSettings.Bind.Select(x => x.Endpoint).ToList(); // IPV4: 127.0.0.1:16178 != 0.0.0.0:16178 (both are considered local endpoints) endpointA = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 16178; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV6: [::1]:16178 != [::]:16178 endpointA = new IPEndPoint(IPAddress.Parse("[::1]"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("[::]"), 16178); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 16178; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // 127.0.0.1:16178 != 0.0.0.0:44556 endpointA = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 44556); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 44556; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // 0.0.0.0:16178 == 127.0.0.1:16178 endpointA = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 16178); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 16178; Assert.True(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV4: 0.0.0.0:16178 == 127.0.0.2:16178 endpointA = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("127.0.0.2"), 16178); connectionManagerSettings.Port = 16178; networkEndpoints = new List <IPEndPoint>() { endpointB }; Assert.True(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV6: [::]:16178 == [::1]:16178 endpointA = new IPEndPoint(IPAddress.Parse("[::]"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("[::1]"), 16178); connectionManagerSettings.Port = 16178; networkEndpoints = new List <IPEndPoint>() { endpointB }; Assert.True(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV4: 0.0.0.0:16178 == 127.0.0.2:999 endpointA = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("127.0.0.2"), 999); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 999; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV6: [::]:16178 != [::2]:999 endpointA = new IPEndPoint(IPAddress.Parse("[::]"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("[::2]"), 999); connectionManagerSettings.Port = 999; networkEndpoints = new List <IPEndPoint>() { endpointB }; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // IPV6: [::1] != [fe80::d111:a4c4:ce4:2bc7%21] (Localhost -> Network address). endpointA = new IPEndPoint(IPAddress.Parse("[::1]"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("[fe80::d111:a4c4:ce4:2bc7%21]"), 16178); connectionManagerSettings.Port = 16178; networkEndpoints = new List <IPEndPoint>() { endpointB }; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // 10.0.0.1:16178 != 192.168.1.1:16178 (Bound to any but whitelisting local). endpointA = new IPEndPoint(IPAddress.Parse("192.168.1.1"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 16178); networkEndpoints = new List <IPEndPoint>() { endpointB }; connectionManagerSettings.Port = 16178; Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // Using whitebind = 0.0.0.0:16178 and connecting from local or remote IP address on port 16178 should be whitebinded. endpointA = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("10.0.0.1"), 16178); Assert.True(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // Using whitebind = 100.64.1.1:16178 and connecting from local or remote IP address(other than 100.64.1.1) on port 16178 should not be whitebinded. endpointA = new IPEndPoint(IPAddress.Parse("100.64.1.1"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("100.64.1.2"), 16178); Assert.False(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); // Using whitebind = 0.0.0.0:16178 and connecting from local or remote IP address on port other than 16178 should be not whitebinded. endpointA = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 16178); endpointB = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 16179); Assert.True(endpointA.CanBeMappedTo(networkEndpoints, out endpointOut)); }
public void BlockPolicyEstimates() { var dateTimeSet = new DateTimeProviderSet(); NodeSettings settings = NodeSettings.Default(); var mpool = new TxMempool(DateTimeProvider.Default, new BlockPolicyEstimator(new MempoolSettings(settings), settings.LoggerFactory, settings), settings.LoggerFactory, settings); var entry = new TestMemPoolEntryHelper(); var basefee = new Money(2000); var deltaFee = new Money(100); var feeV = new List <Money>(); // Populate vectors of increasing fees for (int j = 0; j < 10; j++) { feeV.Add(basefee * (j + 1)); } // Store the hashes of transactions that have been // added to the mempool by their associate fee // txHashes[j] is populated with transactions either of // fee = basefee * (j+1) var txHashes = new List <uint256> [10]; for (int i = 0; i < txHashes.Length; i++) { txHashes[i] = new List <uint256>(); } // Create a transaction template var garbage = new Script(Enumerable.Range(0, 128).Select(i => (byte)1).ToArray()); var txf = new Transaction(); txf.AddInput(new TxIn(garbage)); txf.AddOutput(new TxOut(0L, Script.Empty)); var baseRate = new FeeRate(basefee, txf.GetVirtualSize()); // Create a fake block var block = new List <Transaction>(); int blocknum = 0; int answerFound; // Loop through 200 blocks // At a decay .998 and 4 fee transactions per block // This makes the tx count about 1.33 per bucket, above the 1 threshold while (blocknum < 200) { for (int j = 0; j < 10; j++) { // For each fee for (int k = 0; k < 4; k++) { // add 4 fee txs Transaction tx = txf.Clone(false, Network.Main); tx.Inputs[0].PrevOut.N = (uint)(10000 * blocknum + 100 * j + k); // make transaction unique uint256 hash = tx.GetHash(); mpool.AddUnchecked(hash, entry.Fee(feeV[j]).Time(dateTimeSet.GetTime()).Priority(0).Height(blocknum).FromTx(tx, mpool)); txHashes[j].Add(hash); } } //Create blocks where higher fee txs are included more often for (int h = 0; h <= blocknum % 10; h++) { // 10/10 blocks add highest fee transactions // 9/10 blocks add 2nd highest and so on until ... // 1/10 blocks add lowest fee transactions while (txHashes[9 - h].Count > 0) { Transaction ptx = mpool.Get(txHashes[9 - h].Last()); if (ptx != null) { block.Add(ptx); } txHashes[9 - h].Remove(txHashes[9 - h].Last()); } } mpool.RemoveForBlock(block, ++blocknum); block.Clear(); if (blocknum == 30) { // At this point we should need to combine 5 buckets to get enough data points // So estimateFee(1,2,3) should fail and estimateFee(4) should return somewhere around // 8*baserate. estimateFee(4) %'s are 100,100,100,100,90 = average 98% Assert.True(mpool.EstimateFee(1) == new FeeRate(0)); Assert.True(mpool.EstimateFee(2) == new FeeRate(0)); Assert.True(mpool.EstimateFee(3) == new FeeRate(0)); Assert.True(mpool.EstimateFee(4).FeePerK < 8 * baseRate.FeePerK + deltaFee); Assert.True(mpool.EstimateFee(4).FeePerK > 8 * baseRate.FeePerK - deltaFee); Assert.True(mpool.EstimateSmartFee(1, out answerFound) == mpool.EstimateFee(4) && answerFound == 4); Assert.True(mpool.EstimateSmartFee(3, out answerFound) == mpool.EstimateFee(4) && answerFound == 4); Assert.True(mpool.EstimateSmartFee(4, out answerFound) == mpool.EstimateFee(4) && answerFound == 4); Assert.True(mpool.EstimateSmartFee(8, out answerFound) == mpool.EstimateFee(8) && answerFound == 8); } } var origFeeEst = new List <Money>(); // Highest feerate is 10*baseRate and gets in all blocks, // second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%, // third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%, // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure // Second highest feerate has 100% chance of being included by 2 blocks, // so estimateFee(2) should return 9*baseRate etc... for (int i = 1; i < 10; i++) { origFeeEst.Add(mpool.EstimateFee(i).FeePerK); if (i > 2) { // Fee estimates should be monotonically decreasing Assert.True(origFeeEst[i - 1] <= origFeeEst[i - 2]); } int mult = 11 - i; if (i > 1) { Assert.True(origFeeEst[i - 1] < mult * baseRate.FeePerK + deltaFee); Assert.True(origFeeEst[i - 1] > mult * baseRate.FeePerK - deltaFee); } else { Assert.True(origFeeEst[i - 1] == new FeeRate(0).FeePerK); } } // Mine 50 more blocks with no transactions happening, estimates shouldn't change // We haven't decayed the moving average enough so we still have enough data points in every bucket while (blocknum < 250) { mpool.RemoveForBlock(block, ++blocknum); } Assert.True(mpool.EstimateFee(1) == new FeeRate(0)); for (int i = 2; i < 10; i++) { Assert.True(mpool.EstimateFee(i).FeePerK < origFeeEst[i - 1] + deltaFee); Assert.True(mpool.EstimateFee(i).FeePerK > origFeeEst[i - 1] - deltaFee); } // Mine 15 more blocks with lots of transactions happening and not getting mined // Estimates should go up while (blocknum < 265) { for (int j = 0; j < 10; j++) { // For each fee multiple for (int k = 0; k < 4; k++) { // add 4 fee txs Transaction tx = txf.Clone(false, Network.Main); tx.Inputs[0].PrevOut.N = (uint)(10000 * blocknum + 100 * j + k); uint256 hash = tx.GetHash(); mpool.AddUnchecked(hash, entry.Fee(feeV[j]).Time(dateTimeSet.GetTime()).Priority(0).Height(blocknum).FromTx(tx, mpool)); txHashes[j].Add(hash); } } mpool.RemoveForBlock(block, ++blocknum); } for (int i = 1; i < 10; i++) { Assert.True(mpool.EstimateFee(i) == new FeeRate(0) || mpool.EstimateFee(i).FeePerK > origFeeEst[i - 1] - deltaFee); Assert.True(mpool.EstimateSmartFee(i, out answerFound).FeePerK > origFeeEst[answerFound - 1] - deltaFee); } // Mine all those transactions // Estimates should still not be below original for (int j = 0; j < 10; j++) { while (txHashes[j].Count > 0) { Transaction ptx = mpool.Get(txHashes[j].Last()); if (ptx != null) { block.Add(ptx); } txHashes[j].Remove(txHashes[j].Last()); } } mpool.RemoveForBlock(block, 265); block.Clear(); Assert.True(mpool.EstimateFee(1) == new FeeRate(0)); for (int i = 2; i < 10; i++) { Assert.True(mpool.EstimateFee(i).FeePerK > origFeeEst[i - 1] - deltaFee); } // Mine 200 more blocks where everything is mined every block // Estimates should be below original estimates while (blocknum < 465) { for (int j = 0; j < 10; j++) { // For each fee multiple for (int k = 0; k < 4; k++) { // add 4 fee txs Transaction tx = txf.Clone(false, Network.Main); tx.Inputs[0].PrevOut.N = (uint)(10000 * blocknum + 100 * j + k); uint256 hash = tx.GetHash(); mpool.AddUnchecked(hash, entry.Fee(feeV[j]).Time(dateTimeSet.GetTime()).Priority(0).Height(blocknum).FromTx(tx, mpool)); Transaction ptx = mpool.Get(hash); if (ptx != null) { block.Add(ptx); } } } mpool.RemoveForBlock(block, ++blocknum); block.Clear(); } Assert.True(mpool.EstimateFee(1) == new FeeRate(0)); for (int i = 2; i < 10; i++) { Assert.True(mpool.EstimateFee(i).FeePerK < origFeeEst[i - 1] - deltaFee); } // Test that if the mempool is limited, estimateSmartFee won't return a value below the mempool min fee // and that estimateSmartPriority returns essentially an infinite value mpool.AddUnchecked(txf.GetHash(), entry.Fee(feeV[5]).Time(dateTimeSet.GetTime()).Priority(0).Height(blocknum).FromTx(txf, mpool)); // evict that transaction which should set a mempool min fee of minRelayTxFee + feeV[5] mpool.TrimToSize(1); Assert.True(mpool.GetMinFee(1).FeePerK > feeV[5]); for (int i = 1; i < 10; i++) { Assert.True(mpool.EstimateSmartFee(i, out answerFound).FeePerK >= mpool.EstimateFee(i).FeePerK); Assert.True(mpool.EstimateSmartFee(i, out answerFound).FeePerK >= mpool.GetMinFee(1).FeePerK); Assert.True(mpool.EstimateSmartPriority(i, out answerFound) == BlockPolicyEstimator.InfPriority); } }
public void VerifyCheckpoints_BitcoinTestnet() { var verifyableCheckpoints = new Dictionary <int, CheckpointInfo> { { 546, new CheckpointInfo(new uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")) }, { 1210000, new CheckpointInfo(new uint256("00000000461201277cf8c635fc10d042d6f0a7eaa57f6c9e8c099b9e0dbc46dc")) }, }; var checkpoints = new Checkpoints(KnownNetworks.TestNet, new ConsensusSettings(NodeSettings.Default(this.network)) { UseCheckpoints = true }); VerifyCheckpoints(checkpoints, verifyableCheckpoints); }
/// <summary> /// Initializes an instance of the object from the default node configuration. /// </summary> public RpcSettings() : this(NodeSettings.Default()) { }
public void VerifyCheckpoints_StratisTestnet() { var verifyableCheckpoints = new Dictionary <int, CheckpointInfo> { { 0, new CheckpointInfo(new uint256("0x00000e246d7b73b88c9ab55f2e5e94d9e22d471def3df5ea448f5576b1d156b9"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, { 2, new CheckpointInfo(new uint256("0x56959b1c8498631fb0ca5fe7bd83319dccdc6ac003dccb3171f39f553ecfa2f2"), new uint256("0x13f4c27ca813aefe2d9018077f8efeb3766796b9144fcc4cd51803bf4376ab02")) }, { 50000, new CheckpointInfo(new uint256("0xb42c18eacf8fb5ed94eac31943bd364451d88da0fd44cc49616ffea34d530ad4"), new uint256("0x824934ddc5f935e854ac59ae7f5ed25f2d29a7c3914cac851f3eddb4baf96d78")) }, { 100000, new CheckpointInfo(new uint256("0xf9e2f7561ee4b92d3bde400d251363a0e8924204c326da7f4ad9ccc8863aad79"), new uint256("0xdef8d92d20becc71f662ee1c32252aca129f1bf4744026b116d45d9bfe67e9fb")) }, { 150000, new CheckpointInfo(new uint256("0x08b7c20a450252ddf9ce41dbeb92ecf54932beac9090dc8250e933ad3a175381"), new uint256("0xf05dad15f733ae0acbd34adc449be9429099dbee5fa9ecd8e524cf28e9153adb")) }, { 200000, new CheckpointInfo(new uint256("0x8609cc873222a0573615788dc32e377b88bfd6a0015791f627d969ee3a415115"), new uint256("0xfa28c1f20a8162d133607c6a1c8997833befac3efd9076567258a7683ac181fa")) }, { 250000, new CheckpointInfo(new uint256("0xdd664e15ac679a6f3b96a7176303956661998174a697ad8231f154f1e32ff4a3"), new uint256("0x19fc0fa29418f8b19cbb6557c1c79dfd0eff6779c0eaaec5d245c5cdf3c96d78")) }, { 300000, new CheckpointInfo(new uint256("0x2409eb5ae72c80d5b37c77903d75a8e742a33843ab633935ce6e5264db962e23"), new uint256("0xf5ec7af55516b8e264ed280e9a5dba0180a4a9d3713351bfea275b18f3f1514e")) }, { 350000, new CheckpointInfo(new uint256("0x36811041e9060f4b4c26dc20e0850dca5efaabb60618e3456992e9c0b1b2120e"), new uint256("0xbfda55ef0756bcee8485e15527a2b8ca27ca877aa09c88e363ef8d3253cdfd1c")) }, { 400000, new CheckpointInfo(new uint256("0xb6abcb933d3e3590345ca5d3abb697461093313f8886568ac8ae740d223e56f6"), new uint256("0xfaf5fcebee3ec0df5155393a99da43de18b12e620fef5edb111a791ecbfaa63a")) } }; var checkpoints = new Checkpoints(KnownNetworks.StratisTest, new ConsensusSettings(NodeSettings.Default(KnownNetworks.StratisTest)) { UseCheckpoints = true }); VerifyCheckpoints(checkpoints, verifyableCheckpoints); }
/// <summary> /// Makes the full node builder use the default node settings. /// </summary> /// <param name="builder">Full node builder to change node settings for.</param> /// <returns>Interface to allow fluent code.</returns> public static IFullNodeBuilder UseDefaultNodeSettings(this IFullNodeBuilder builder) { return(builder.UseNodeSettings(NodeSettings.Default(builder.Network))); }
public void GetLastCheckPointHeight_StratisTestnet_ReturnsLastCheckPointHeight() { var checkpoints = new Checkpoints(KnownNetworks.StratisTest, new ConsensusSettings(NodeSettings.Default(KnownNetworks.StratisTest)) { UseCheckpoints = true }); int result = checkpoints.GetLastCheckpointHeight(); Assert.Equal(1150000, result); }
public void MempoolIndexingTest() { var settings = NodeSettings.Default(); var pool = new TxMempool(DateTimeProvider.Default, new BlockPolicyEstimator(new MempoolSettings(settings), settings.LoggerFactory, settings), settings.LoggerFactory, settings); var entry = new TestMemPoolEntryHelper(); /* 3rd highest fee */ Transaction tx1 = new Transaction(); tx1.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx1.GetHash(), entry.Fee(new Money(10000L)).Priority(10.0).FromTx(tx1)); /* highest fee */ Transaction tx2 = new Transaction(); tx2.AddOutput(new TxOut(new Money(2 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx2.GetHash(), entry.Fee(new Money(20000L)).Priority(9.0).FromTx(tx2)); /* lowest fee */ Transaction tx3 = new Transaction(); tx3.AddOutput(new TxOut(new Money(5 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx3.GetHash(), entry.Fee(new Money(0L)).Priority(100.0).FromTx(tx3)); /* 2nd highest fee */ Transaction tx4 = new Transaction(); tx4.AddOutput(new TxOut(new Money(6 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx4.GetHash(), entry.Fee(new Money(15000L)).Priority(1.0).FromTx(tx4)); /* equal fee rate to tx1, but newer */ Transaction tx5 = new Transaction(); tx5.AddOutput(new TxOut(new Money(11 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx5.GetHash(), entry.Fee(new Money(10000L)).Priority(10.0).Time(1).FromTx(tx5)); // assert size Assert.Equal(5, pool.Size); List <string> sortedOrder = new List <string>(5); sortedOrder.Insert(0, tx3.GetHash().ToString()); // 0 sortedOrder.Insert(1, tx5.GetHash().ToString()); // 10000 sortedOrder.Insert(2, tx1.GetHash().ToString()); // 10000 sortedOrder.Insert(3, tx4.GetHash().ToString()); // 15000 sortedOrder.Insert(4, tx2.GetHash().ToString()); // 20000 this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); /* low fee but with high fee child */ /* tx6 -> tx7 -> tx8, tx9 -> tx10 */ Transaction tx6 = new Transaction(); tx6.AddOutput(new TxOut(new Money(20 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx6.GetHash(), entry.Fee(new Money(0L)).FromTx(tx6)); // assert size Assert.Equal(6, pool.Size); // Check that at this point, tx6 is sorted low sortedOrder.Insert(0, tx6.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); TxMempool.SetEntries setAncestors = new TxMempool.SetEntries(); setAncestors.Add(pool.MapTx.TryGet(tx6.GetHash())); Transaction tx7 = new Transaction(); tx7.AddInput(new TxIn(new OutPoint(tx6.GetHash(), 0), new Script(OpcodeType.OP_11))); tx7.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); tx7.AddOutput(new TxOut(new Money(1 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); TxMempool.SetEntries setAncestorsCalculated = new TxMempool.SetEntries(); string dummy; Assert.True(pool.CalculateMemPoolAncestors(entry.Fee(2000000L).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, out dummy)); Assert.True(setAncestorsCalculated.Equals(setAncestors)); pool.AddUnchecked(tx7.GetHash(), entry.FromTx(tx7), setAncestors); Assert.Equal(7, pool.Size); // Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ... sortedOrder.RemoveAt(0); sortedOrder.Add(tx6.GetHash().ToString()); sortedOrder.Add(tx7.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); /* low fee child of tx7 */ Transaction tx8 = new Transaction(); tx8.AddInput(new TxIn(new OutPoint(tx7.GetHash(), 0), new Script(OpcodeType.OP_11))); tx8.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); setAncestors.Add(pool.MapTx.TryGet(tx7.GetHash())); pool.AddUnchecked(tx8.GetHash(), entry.Fee(0L).Time(2).FromTx(tx8), setAncestors); // Now tx8 should be sorted low, but tx6/tx both high sortedOrder.Insert(0, tx8.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); /* low fee child of tx7 */ Transaction tx9 = new Transaction(); tx9.AddInput(new TxIn(new OutPoint(tx7.GetHash(), 1), new Script(OpcodeType.OP_11))); tx9.AddOutput(new TxOut(new Money(1 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); pool.AddUnchecked(tx9.GetHash(), entry.Fee(0L).Time(3).FromTx(tx9), setAncestors); // tx9 should be sorted low Assert.Equal(9, pool.Size); sortedOrder.Insert(0, tx9.GetHash().ToString()); this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); List <string> snapshotOrder = sortedOrder.ToList(); setAncestors.Add(pool.MapTx.TryGet(tx8.GetHash())); setAncestors.Add(pool.MapTx.TryGet(tx9.GetHash())); /* tx10 depends on tx8 and tx9 and has a high fee*/ Transaction tx10 = new Transaction(); tx10.AddInput(new TxIn(new OutPoint(tx8.GetHash(), 0), new Script(OpcodeType.OP_11))); tx10.AddInput(new TxIn(new OutPoint(tx9.GetHash(), 0), new Script(OpcodeType.OP_11))); tx10.AddOutput(new TxOut(new Money(10 * Money.COIN), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); setAncestorsCalculated.Clear(); Assert.True(pool.CalculateMemPoolAncestors(entry.Fee(200000L).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, out dummy)); Assert.True(setAncestorsCalculated.Equals(setAncestors)); pool.AddUnchecked(tx10.GetHash(), entry.FromTx(tx10), setAncestors); /** * tx8 and tx9 should both now be sorted higher * Final order after tx10 is added: * * tx3 = 0 (1) * tx5 = 10000 (1) * tx1 = 10000 (1) * tx4 = 15000 (1) * tx2 = 20000 (1) * tx9 = 200k (2 txs) * tx8 = 200k (2 txs) * tx10 = 200k (1 tx) * tx6 = 2.2M (5 txs) * tx7 = 2.2M (4 txs) */ sortedOrder.RemoveRange(0, 2); // take out tx9, tx8 from the beginning sortedOrder.Insert(5, tx9.GetHash().ToString()); sortedOrder.Insert(6, tx8.GetHash().ToString()); sortedOrder.Insert(7, tx10.GetHash().ToString()); // tx10 is just before tx6 this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), sortedOrder); // there should be 10 transactions in the mempool Assert.Equal(10, pool.Size); // Now try removing tx10 and verify the sort order returns to normal pool.RemoveRecursive(pool.MapTx.TryGet(tx10.GetHash()).Transaction); this.CheckSort(pool, pool.MapTx.DescendantScore.ToList(), snapshotOrder); pool.RemoveRecursive(pool.MapTx.TryGet(tx9.GetHash()).Transaction); pool.RemoveRecursive(pool.MapTx.TryGet(tx8.GetHash()).Transaction); /* Now check the sort on the mining score index. * Final order should be: * * tx7 (2M) * tx2 (20k) * tx4 (15000) * tx1/tx5 (10000) * tx3/6 (0) * (Ties resolved by hash) */ sortedOrder.Clear(); sortedOrder.Add(tx7.GetHash().ToString()); sortedOrder.Add(tx2.GetHash().ToString()); sortedOrder.Add(tx4.GetHash().ToString()); if (tx1.GetHash() < tx5.GetHash()) { sortedOrder.Add(tx5.GetHash().ToString()); sortedOrder.Add(tx1.GetHash().ToString()); } else { sortedOrder.Add(tx1.GetHash().ToString()); sortedOrder.Add(tx5.GetHash().ToString()); } if (tx3.GetHash() < tx6.GetHash()) { sortedOrder.Add(tx6.GetHash().ToString()); sortedOrder.Add(tx3.GetHash().ToString()); } else { sortedOrder.Add(tx3.GetHash().ToString()); sortedOrder.Add(tx6.GetHash().ToString()); } this.CheckSort(pool, pool.MapTx.MiningScore.ToList(), sortedOrder); }
public void FundTransaction_Given__a_wallet_has_enough_inputs__When__adding_inputs_to_an_existing_transaction__Then__the_transaction_is_funded_successfully() { DataFolder dataFolder = CreateDataFolder(this); var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); var accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); var spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0"); var destinationKeys1 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1"); var destinationKeys2 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/2"); var destinationKeys3 = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/3"); var address = new HdAddress { Index = 0, HdPath = $"m/44'/0'/0'/0/0", Address = spendingKeys.Address.ToString(), Pubkey = spendingKeys.PubKey.ScriptPubKey, ScriptPubKey = spendingKeys.Address.ScriptPubKey, Transactions = new List <TransactionData>() }; // wallet with 4 coinbase outputs of 50 = 200 Bitcoin var chain = new ConcurrentChain(wallet.Network.GetGenesis().Header); WalletTestsHelpers.AddBlocksWithCoinbaseToChain(wallet.Network, chain, address, 4); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, ExternalAddresses = new List <HdAddress> { address }, InternalAddresses = new List <HdAddress>() }); var walletFeePolicy = new Mock <IWalletFeePolicy>(); walletFeePolicy.Setup(w => w.GetFeeRate(FeeType.Low.ToConfirmations())).Returns(new FeeRate(20000)); var overrideFeeRate = new FeeRate(20000); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chain, NodeSettings.Default(), dataFolder, walletFeePolicy.Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain, walletManager, walletFeePolicy.Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; // create a trx with 3 outputs 50 + 50 + 49 = 149 BTC var context = new TransactionBuildContext(walletReference, new[] { new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destinationKeys1.PubKey.ScriptPubKey }, new Recipient { Amount = new Money(50, MoneyUnit.BTC), ScriptPubKey = destinationKeys2.PubKey.ScriptPubKey }, new Recipient { Amount = new Money(49, MoneyUnit.BTC), ScriptPubKey = destinationKeys3.PubKey.ScriptPubKey } } .ToList(), "password") { MinConfirmations = 0, FeeType = FeeType.Low }; var fundTransaction = walletTransactionHandler.BuildTransaction(context); Assert.Equal(3, fundTransaction.Inputs.Count); // 3 inputs Assert.Equal(4, fundTransaction.Outputs.Count); // 3 outputs with change // remove the change output fundTransaction.Outputs.Remove(fundTransaction.Outputs.First(f => f.ScriptPubKey == context.ChangeAddress.ScriptPubKey)); // remove 2 inputs they will be added back by fund transaction fundTransaction.Inputs.RemoveAt(2); fundTransaction.Inputs.RemoveAt(1); Assert.Single(fundTransaction.Inputs); // 3 inputs var fundTransactionClone = fundTransaction.Clone(); var fundContext = new TransactionBuildContext(walletReference, new List <Recipient>(), "password") { MinConfirmations = 0, FeeType = FeeType.Low }; fundContext.OverrideFeeRate = overrideFeeRate; walletTransactionHandler.FundTransaction(fundContext, fundTransaction); foreach (var input in fundTransactionClone.Inputs) // all original inputs are still in the trx { Assert.Contains(fundTransaction.Inputs, a => a.PrevOut == input.PrevOut); } Assert.Equal(3, fundTransaction.Inputs.Count); // we expect 3 inputs Assert.Equal(4, fundTransaction.Outputs.Count); // we expect 4 outputs Assert.Equal(new Money(150, MoneyUnit.BTC) - fundContext.TransactionFee, fundTransaction.TotalOut); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys1.PubKey.ScriptPubKey); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys2.PubKey.ScriptPubKey); Assert.Contains(fundTransaction.Outputs, a => a.ScriptPubKey == destinationKeys3.PubKey.ScriptPubKey); }
public void MempoolRemoveTest() { TestMemPoolEntryHelper entry = new TestMemPoolEntryHelper(); // Parent transaction with three children, // and three grand-children: Transaction txParent = new Transaction(); txParent.AddInput(new TxIn()); txParent.Inputs[0].ScriptSig = new Script(OpcodeType.OP_11); for (int i = 0; i < 3; i++) { txParent.AddOutput(new TxOut(new Money(33000L), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); } Transaction[] txChild = new Transaction[3]; for (int i = 0; i < 3; i++) { txChild[i] = new Transaction(); txChild[i].AddInput(new TxIn(new OutPoint(txParent, i), new Script(OpcodeType.OP_11))); txChild[i].AddOutput(new TxOut(new Money(11000L), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); } Transaction[] txGrandChild = new Transaction[3]; for (int i = 0; i < 3; i++) { txGrandChild[i] = new Transaction(); txGrandChild[i].AddInput(new TxIn(new OutPoint(txChild[i], 0), new Script(OpcodeType.OP_11))); txGrandChild[i].AddOutput(new TxOut(new Money(11000L), new Script(OpcodeType.OP_11, OpcodeType.OP_EQUAL))); } var settings = NodeSettings.Default(); TxMempool testPool = new TxMempool(DateTimeProvider.Default, new BlockPolicyEstimator(new MempoolSettings(settings), settings.LoggerFactory, settings), settings.LoggerFactory, settings); // Nothing in pool, remove should do nothing: var poolSize = testPool.Size; testPool.RemoveRecursive(txParent); Assert.Equal(testPool.Size, poolSize); // Just the parent: testPool.AddUnchecked(txParent.GetHash(), entry.FromTx(txParent)); poolSize = testPool.Size; testPool.RemoveRecursive(txParent); Assert.Equal(testPool.Size, poolSize - 1); // Parent, children, grandchildren: testPool.AddUnchecked(txParent.GetHash(), entry.FromTx(txParent)); for (int i = 0; i < 3; i++) { testPool.AddUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i])); testPool.AddUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i])); } // Remove Child[0], GrandChild[0] should be removed: poolSize = testPool.Size; testPool.RemoveRecursive(txChild[0]); Assert.Equal(testPool.Size, poolSize - 2); // ... make sure grandchild and child are gone: poolSize = testPool.Size; testPool.RemoveRecursive(txGrandChild[0]); Assert.Equal(testPool.Size, poolSize); poolSize = testPool.Size; testPool.RemoveRecursive(txChild[0]); Assert.Equal(testPool.Size, poolSize); // Remove parent, all children/grandchildren should go: poolSize = testPool.Size; testPool.RemoveRecursive(txParent); Assert.Equal(testPool.Size, poolSize - 5); Assert.Equal(0, testPool.Size); // Add children and grandchildren, but NOT the parent (simulate the parent being in a block) for (int i = 0; i < 3; i++) { testPool.AddUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i])); testPool.AddUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i])); } // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be // put into the mempool (maybe because it is non-standard): poolSize = testPool.Size; testPool.RemoveRecursive(txParent); Assert.Equal(poolSize - 6, testPool.Size); Assert.Equal(0, testPool.Size); }
public void BuildTransactionNoSpendableTransactionsThrowsWalletException() { Assert.Throws <WalletException>(() => { var wallet = WalletTestsHelpers.GenerateBlankWallet("myWallet1", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Add( new HdAccount { Name = "account1", ExternalAddresses = new List <HdAddress>(), InternalAddresses = new List <HdAddress>() }); var chain = new Mock <ConcurrentChain>(); chain.Setup(c => c.Tip).Returns(new ChainedBlock(new BlockHeader(), 1)); var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chain.Object, NodeSettings.Default(), new DataFolder(new NodeSettings { DataDir = "TestData/WalletTransactionHandlerTest/BuildTransactionNoSpendableTransactionsThrowsWalletException" }), new Mock <IWalletFeePolicy>().Object, new Mock <IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); var walletTransactionHandler = new WalletTransactionHandler(this.LoggerFactory.Object, chain.Object, walletManager, new Mock <IWalletFeePolicy>().Object, Network.Main); walletManager.Wallets.Add(wallet); var walletReference = new WalletAccountReference { AccountName = "account1", WalletName = "myWallet1" }; walletTransactionHandler.BuildTransaction(CreateContext(walletReference, "password", new Script(), new Money(500), FeeType.Medium, 2)); }); }
/// <summary> /// Initializes an instance of the object from the default configuration. /// </summary> public WalletSettings() : this(NodeSettings.Default()) { }