public async Task Can_UnBan_Peer_From_ApiAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var nodeA = builder.CreateStratisPosNode(network, "nc-2-nodeA").Start(); var nodeB_Ip = "127.0.0.2"; var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip); var nodeB_EndPoint = new IPEndPoint(nodeB_IpAddress, 0); var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>(); nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback); var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>(); peerBanning.BanAndDisconnectPeer(nodeB_EndPoint); Assert.True(peerBanning.IsBanned(nodeB_EndPoint)); var unBanPeerModel = new SetBanPeerViewModel() { BanCommand = "remove", PeerAddress = nodeB_Ip }; await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/setban").PostJsonAsync(unBanPeerModel); Assert.False(peerBanning.IsBanned(nodeB_EndPoint)); } }
public void Mempool_SendTransactionWithEarlyTimestamp_ShouldRejectByMempool() { var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); // Use timestamp value that is definitely earlier than the input's timestamp ((PosTransaction)trx).Time = 1; // Sign trx again after mutating timestamp trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal("timestamp earlier than input", entry.ErrorMessage); } }
public void Mempool_SendPosTransaction_AheadOfFutureDrift_ShouldRejectByMempool() { var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); // This should make the mempool reject a POS trx. ((PosTransaction)trx).Time = Utils.DateTimeToUnixTime(Utils.UnixTimeToDateTime(((PosTransaction)trx).Time).AddMinutes(5)); // Sign trx again after changing the time property. trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal("time-too-new", entry.ErrorMessage); } }
public void Mempool_SendOversizeTransaction_ShouldRejectByMempool() { var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); // Add nonsense script to make tx large. Script script = Script.FromBytesUnsafe(new string('A', network.Consensus.Options.MaxStandardTxWeight).Select(c => (byte)c).ToArray()); trx.Outputs.Add(new TxOut(new Money(1), script)); // Sign trx again after adding an output trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal("tx-size", entry.ErrorMessage); } }
public void SBFNMinesBlocksXSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); CoreNode stratisNode = builder.CreateStratisPosNode(network).WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); // TODO: Need to troubleshoot why TestHelper.Connect() does not work here, possibly unsupported RPC method. stratisXRpc.AddNode(stratisNode.Endpoint, false); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); // TODO: Similarly, the 'generate' RPC call is problematic on X. Possibly returning an unexpected JSON format. TestHelper.MineBlocks(stratisNode, 10); // As we are not actually sending transactions, it does not // matter that the datetime provider is substituted for this // test. The blocks get accepted by X despite getting generated // very rapidly. var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == stratisXNode.CreateRPCClient().GetBestBlockHash(), cancellationToken: cancellationToken); } }
public void SBFNMinesBlocks_XSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); CoreNode sbfnNode = builder.CreateStratisPosNode(network).WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient sbfnNodeRpc = sbfnNode.CreateRPCClient(); // TODO: Need to troubleshoot why TestHelper.Connect() does not work here, possibly unsupported RPC method (it seems that addnode does not work for X). sbfnNodeRpc.AddNode(stratisXNode.Endpoint, false); // TODO: Similarly, the 'generate' RPC call is problematic on X. Possibly returning an unexpected JSON format. TestHelper.MineBlocks(sbfnNode, 10); var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => sbfnNodeRpc.GetBlockCount() >= 10, cancellationToken: cancellationToken); TestBase.WaitLoop(() => sbfnNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: cancellationToken); } }
private static Transaction CreateTransactionThatSpendCoinstake(StratisRegTest network, CoreNode minerA, CoreNode minerB, TxIn coinstake, Transaction txWithBigPremine) { Transaction txThatSpendCoinstake = network.CreateTransaction(); txThatSpendCoinstake.AddInput(new TxIn(new OutPoint(txWithBigPremine, 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(minerA.MinerSecret.PubKey))); txThatSpendCoinstake.AddOutput(new TxOut { Value = txWithBigPremine.Outputs[0].Value - new Money(1, MoneyUnit.BTC), ScriptPubKey = minerB.MinerHDAddress.ScriptPubKey }); var dateTimeProvider = minerA.FullNode.NodeService <IDateTimeProvider>(); if (txThatSpendCoinstake is IPosTransactionWithTime posTrx) { posTrx.Time = (uint)dateTimeProvider.GetAdjustedTimeAsUnixTimestamp(); } Coin spentCoin = new Coin(txWithBigPremine, 0); List <ICoin> coins = new List <ICoin> { spentCoin }; txThatSpendCoinstake.Sign(minerA.FullNode.Network, minerA.MinerSecret, coins[0]); return(txThatSpendCoinstake); }
private Network InitRegTest() { Network network = new StratisRegTest(); network.MoneyUnits = GetMoneyUnitsTest(); return(network); }
public void XMinesBlocks_SBFNSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); CoreNode stratisNode = builder.CreateStratisPosNode(network).WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); stratisXRpc.SendCommand(RPCOperations.generate, 10); var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestHelper.WaitLoop(() => stratisXRpc.GetBlockCount() >= 10, cancellationToken: cancellationToken); TestHelper.WaitLoop(() => stratisXRpc.GetBestBlockHash() == stratisNodeRpc.GetBestBlockHash(), cancellationToken: cancellationToken); } }
public void Transaction_CreatedByXNode_TraversesSBFN_ReachesSecondXNode() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode xNode1 = builder.CreateStratisXNode(version: "2.0.0.5").Start(); var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC()); var config = new NodeConfigParameters(); config.Add("whitelist", xNode1.Endpoint.ToString()); config.Add("gateway", "1"); CoreNode sbfnNode2 = builder .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config) .WithWallet().Start(); CoreNode xNode3 = builder.CreateStratisXNode(version: "2.0.0.5").Start(); RPCClient xRpc1 = xNode1.CreateRPCClient(); RPCClient sbfnRpc2 = sbfnNode2.CreateRPCClient(); RPCClient xRpc3 = xNode3.CreateRPCClient(); // Connect the nodes linearly. X does not appear to respond properly to the addnode RPC so SBFN needs to initiate. sbfnRpc2.AddNode(xNode1.Endpoint, false); sbfnRpc2.AddNode(xNode3.Endpoint, false); xRpc1.SendCommand(RPCOperations.generate, 11); var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 11, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == sbfnRpc2.GetBestBlockHash(), cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == xRpc3.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Send transaction to arbitrary address. var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); xRpc1.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1); TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); } }
public void ConsensusManager_Fork_Occurs_When_Same_Coins_Are_Staked_On_Different_Chains() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var minerA = builder.CreateStratisPosNode(network, "cm-11-minerA").OverrideDateTimeProvider().WithWallet().Start(); var minerB = builder.CreateStratisPosNode(network, "cm-11-minerB").OverrideDateTimeProvider().Start(); minerB.FullNode.WalletManager().CreateWallet(Password, WalletName, Passphrase, minerA.Mnemonic); var coinbaseMaturity = (int)network.Consensus.CoinbaseMaturity; // MinerA mines maturity +2 blocks to get the big premine coin and make it stakable. TestHelper.MineBlocks(minerA, coinbaseMaturity + 2); // Sync the peers A and B (height 12) TestHelper.ConnectAndSync(minerA, minerB); // Disconnect Miner A and B. TestHelper.DisconnectAll(minerA, minerB); // Miner A stakes one coin. (height 13) var minterA = minerA.FullNode.NodeService <IPosMinting>(); var minterAHeigh = minerA.FullNode.ConsensusManager().Tip.Height; minterA.Stake(new WalletSecret() { WalletName = WalletName, WalletPassword = Password }); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, minterAHeigh + 1)); minterA.StopStake(); var minterB = minerB.FullNode.NodeService <IPosMinting>(); var minterBHeigh = minerB.FullNode.ConsensusManager().Tip.Height; minterB.Stake(new WalletSecret() { WalletName = WalletName, WalletPassword = Password }); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, minterBHeigh + 1)); minterB.StopStake(); // MinerB mines 1 block on its own fork. (heightB 13) TestHelper.MineBlocks(minerA, 2); TestHelper.MineBlocks(minerB, 3); TestHelper.ConnectAndSync(minerA, minerB); TestBase.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.HashBlock == minerB.FullNode.ConsensusManager().Tip.HashBlock); Assert.True(minerA.FullNode.ConsensusManager().Tip.HashBlock == minerB.FullNode.ConsensusManager().Tip.HashBlock); } }
public void Mempool_SendTransactionWithLargeOpReturn_ShouldRejectByMempool() { var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver. var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); context.OpReturnData = "1"; context.OpReturnAmount = Money.Coins(0.01m); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); foreach (TxOut output in trx.Outputs) { if (output.ScriptPubKey.IsUnspendable) { int[] data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; var ops = new Op[data.Length + 1]; ops[0] = OpcodeType.OP_RETURN; for (int i = 0; i < data.Length; i++) { ops[1 + i] = Op.GetPushOp(data[i]); } output.ScriptPubKey = new Script(ops); } } // Sign trx again after lengthening nulldata output. trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal("scriptpubkey", entry.ErrorMessage); } }
public void ConsensusManager_Fork_Occurs_When_Stake_Coins_Are_Mined_And_Found_In_Rewind_Data() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var sharedMnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve).ToString(); // MinerA requires an physical wallet to stake with. var minerA = builder.CreateStratisPosNode(network, "cm-10-minerA").OverrideDateTimeProvider().WithWallet(walletMnemonic: sharedMnemonic).Start(); var minerB = builder.CreateStratisPosNode(network, "cm-10-minerB").OverrideDateTimeProvider().WithWallet(walletMnemonic: sharedMnemonic).Start(); // MinerA mines 2 blocks to get the big premine coin and mature them (regtest maturity is 10). TestHelper.MineBlocks(minerA, 12); // Sync the peers A and B (height 12) TestHelper.ConnectAndSync(minerA, minerB); // Disconnect Miner A and B. TestHelper.DisconnectAll(minerA, minerB); // Miner A stakes one coin. (height 13) var minterA = minerA.FullNode.NodeService <IPosMinting>(); minterA.Stake(new WalletSecret() { WalletName = "mywallet", WalletPassword = "******" }); TestBase.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.Height == 13); minterA.StopStake(); TestHelper.MineBlocks(minerB, 2); // this will push minerB total work to be highest var minterB = minerB.FullNode.NodeService <IPosMinting>(); minterB.Stake(new WalletSecret() { WalletName = WalletName, WalletPassword = Password }); TestBase.WaitLoop(() => minerB.FullNode.ConsensusManager().Tip.Height == 15); minterB.StopStake(); var expectedValidChainHeight = minerB.FullNode.ConsensusManager().Tip.Height; // Sync the network, minerA should switch to minerB. TestHelper.ConnectAndSync(minerA, minerB); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, expectedValidChainHeight)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, expectedValidChainHeight)); } }
public void MiningAndPropagatingPOS_MineBlockCheckPeerHasNewBlock() { using (NodeBuilder nodeBuilder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode node = nodeBuilder.CreateStratisPosNode(network).WithDummyWallet().Start(); CoreNode syncer = nodeBuilder.CreateStratisPosNode(network).Start(); TestHelper.MineBlocks(node, 1); Assert.NotEqual(node.FullNode.ConsensusManager().Tip, syncer.FullNode.ConsensusManager().Tip); TestHelper.ConnectAndSync(node, syncer); Assert.Equal(node.FullNode.ConsensusManager().Tip, syncer.FullNode.ConsensusManager().Tip); } }
public async Task TestScanRPCCapabilitiesOnStratisNetworkAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new StratisRegTest(); var node = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); RPCCapabilities capabilities = await rpcClient.ScanRPCCapabilitiesAsync(); capabilities.SupportEstimateSmartFee.Should().BeFalse(); capabilities.SupportGetNetworkInfo.Should().BeTrue(); capabilities.SupportScanUTXOSet.Should().BeFalse(); capabilities.SupportSignRawTransactionWith.Should().BeFalse(); capabilities.SupportSegwit.Should().BeTrue(); capabilities.SupportGenerateToAddress.Should().BeTrue(); } }
public async Task Can_BanAndDisconnect_Peer_From_ApiAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var nodeA = builder.CreateStratisPosNode(network, "nc-1-nodeA").Start(); var nodeBIp = "127.0.0.2"; var nodeBIpAddress = IPAddress.Parse(nodeBIp); var nodeBConfig = new NodeConfigParameters { { "-externalip", nodeBIp } }; var nodeB = builder.CreateStratisPosNode(network, agent: "nc-1-nodeB", configParameters: nodeBConfig).Start(); var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>(); nodeAaddressManager.AddPeer(new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port), IPAddress.Loopback); TestHelper.Connect(nodeA, nodeB); var banPeerModel = new SetBanPeerViewModel() { BanDurationSeconds = 100, BanCommand = "add", PeerAddress = nodeBIp }; await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/setban").PostJsonAsync(banPeerModel); TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(nodeA, nodeB)); var nodeBEndPoint = new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port); var addressManager = nodeA.FullNode.NodeService <IPeerAddressManager>(); var peer = nodeAaddressManager.FindPeer(nodeBEndPoint); var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>(); Assert.True(peerBanning.IsBanned(nodeBEndPoint)); } }
public void XMinesBlocks_SBFNSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this).WithLogsEnabled()) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC()); var config = new NodeConfigParameters(); config.Add("whitelist", stratisXNode.Endpoint.ToString()); config.Add("gateway", "1"); CoreNode stratisNode = builder .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config) .WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); stratisXRpc.SendCommand(RPCOperations.generate, 10); var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 10, cancellationToken: cancellationToken); TestBase.WaitLoop(() => stratisXRpc.GetBestBlockHash() == stratisNodeRpc.GetBestBlockHash(), cancellationToken: cancellationToken); } }
public void PullerVsMinerRaceCondition() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var stratisRegTest = new StratisRegTest(); // This represents local node. CoreNode stratisMinerLocal = builder.CreateStratisPosNode(stratisRegTest).OverrideDateTimeProvider().WithDummyWallet().Start(); // This represents remote, which blocks are received by local node using its puller. CoreNode stratisMinerRemote = builder.CreateStratisPosNode(stratisRegTest).OverrideDateTimeProvider().WithDummyWallet().Start(); // Let's mine block Ap and Bp. TestHelper.MineBlocks(stratisMinerRemote, 2); // Wait for block repository for block sync to work. TestHelper.ConnectAndSync(stratisMinerLocal, stratisMinerRemote); // Now disconnect the peers and mine block C2p on remote. TestHelper.Disconnect(stratisMinerLocal, stratisMinerRemote); // Mine block C2p. TestHelper.MineBlocks(stratisMinerRemote, 1); Thread.Sleep(2000); // Now reconnect nodes and mine block C1s before C2p arrives. TestHelper.Connect(stratisMinerLocal, stratisMinerRemote); TestHelper.MineBlocks(stratisMinerLocal, 1); // Mine block Dp. uint256 dpHash = TestHelper.MineBlocks(stratisMinerRemote, 1, false).BlockHashes[0]; // Now we wait until the local node's chain tip has correct hash of Dp. TestHelper.WaitLoop(() => stratisMinerLocal.FullNode.Chain.Tip.HashBlock.Equals(dpHash)); // Then give it time to receive the block from the puller. Thread.Sleep(2500); // Check that local node accepted the Dp as consensus tip. Assert.Equal(stratisMinerLocal.FullNode.ChainBehaviorState.ConsensusTip.HashBlock, dpHash); } }
public async Task Can_GetBannedPeers_From_ApiAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var nodeA = builder.CreateStratisPosNode(network, "nc-4-nodeA").Start(); var nodeB_Ip = "127.0.0.2"; var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip); var nodeB_EndPoint = new IPEndPoint(nodeB_IpAddress, 0); var nodeB_Ip2 = "127.0.0.3"; var nodeB_IpAddress2 = IPAddress.Parse(nodeB_Ip2); var nodeB_EndPoint2 = new IPEndPoint(nodeB_IpAddress2, 0); var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>(); nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback); var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>(); peerBanning.BanAndDisconnectPeer(nodeB_EndPoint, "This peer is banned because of a reason"); Assert.True(peerBanning.IsBanned(nodeB_EndPoint)); peerBanning.BanAndDisconnectPeer(nodeB_EndPoint2, "This peer is banned because of another reason"); Assert.True(peerBanning.IsBanned(nodeB_EndPoint2)); var bannedPeers = await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/getbans").GetJsonAsync <List <BannedPeerModel> >(); Assert.Equal(2, bannedPeers.Count); bannedPeers = bannedPeers.OrderBy(b => b.EndPoint).ToList(); var bannedPeer = bannedPeers[0]; Assert.Equal("This peer is banned because of a reason", bannedPeer.BanReason); Assert.True(DateTime.UtcNow < bannedPeer.BanUntil.Value); Assert.Equal("[::ffff:127.0.0.2]:0", bannedPeer.EndPoint); bannedPeer = bannedPeers[1]; Assert.Equal("This peer is banned because of another reason", bannedPeer.BanReason); Assert.True(DateTime.UtcNow < bannedPeer.BanUntil.Value); Assert.Equal("[::ffff:127.0.0.3]:0", bannedPeer.EndPoint); } }
public void correctly_identify_mainchain() { var stratisRegTest = new StratisRegTest(); var chain = stratisRegTest.ToChain(); chain.Should().Be(Chain.Mainchain); chain.Should().NotBe(Chain.Sidechain); var stratisTest = new StratisTest(); chain = stratisTest.ToChain(); chain.Should().Be(Chain.Mainchain); chain.Should().NotBe(Chain.Sidechain); var stratisMain = new StratisMain(); chain = stratisMain.ToChain(); chain.Should().Be(Chain.Mainchain); chain.Should().NotBe(Chain.Sidechain); }
public void ConsensusManager_Block_That_Failed_Partial_Validation_Is_Rejected() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); // MinerA requires a physical wallet to stake with. var minerA = builder.CreateStratisPosNode(network, "minerA").WithWallet().Start(); var minerB = builder.CreateStratisPosNode(network, "minerB").Start(); var minerC = builder.CreateStratisPosNode(network, "minerC").Start(); // MinerA mines to height 5. TestHelper.MineBlocks(minerA, 5); // Connect and sync minerA and minerB. TestHelper.ConnectAndSync(minerA, minerB); TestHelper.Disconnect(minerA, minerB); // Mark block 5 as invalid by changing the signature of the block in memory. (minerB.FullNode.ChainIndexer.GetHeader(5).Block as PosBlock).BlockSignature.Signature = new byte[] { 0 }; // Connect and sync minerB and minerC. TestHelper.ConnectNoCheck(minerB, minerC); // TODO: when signaling failed blocks is enabled we should check this here. // Wait for the nodes to disconnect due to invalid block. TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(minerB, minerC)); Assert.True(minerC.FullNode.NodeService <IPeerBanning>().IsBanned(minerB.Endpoint)); minerC.FullNode.NodeService <IPeerBanning>().UnBanPeer(minerA.Endpoint); TestHelper.ConnectAndSync(minerC, minerA); TestBase.WaitLoop(() => TestHelper.AreNodesSyncedMessage(minerA, minerC).Passed); } }
public void Mempool_SendPosTransaction_WithFutureLockTime_ShouldBeRejectedByMempool() { // See AcceptToMemoryPool_TxFinalCannotMine_ReturnsFalseAsync for the 'unit test' version var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver. var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); // Treat the locktime as absolute, not relative. trx.Inputs.First().Sequence = new Sequence(Sequence.SEQUENCE_LOCKTIME_DISABLE_FLAG); // Set the nLockTime to be ahead of the current tip so that locktime has not elapsed. trx.LockTime = new LockTime(stratisSender.FullNode.ChainIndexer.Height + 1); // Sign trx again after changing the nLockTime. trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx).GetAwaiter().GetResult(); var entry = broadcaster.GetTransaction(trx.GetHash()); Assert.Equal("non-final", entry.ErrorMessage); } }
public void Mempool_SendPosTransaction_WithElapsedLockTime_ShouldBeAcceptedByMempool() { // See CheckFinalTransaction_WithElapsedLockTime_ReturnsTrueAsync for the 'unit test' version var network = new StratisRegTest(); using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisSender = builder.CreateStratisPosNode(network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest10Miner).Start(); TestHelper.MineBlocks(stratisSender, 5); // Send coins to the receiver. var context = WalletTests.CreateContext(network, new WalletAccountReference(WalletName, Account), Password, new Key().PubKey.GetAddress(network).ScriptPubKey, Money.COIN * 100, FeeType.Medium, 1); Transaction trx = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(context); // Treat the locktime as absolute, not relative. trx.Inputs.First().Sequence = new Sequence(Sequence.SEQUENCE_LOCKTIME_DISABLE_FLAG); // Set the nLockTime to be behind the current tip so that locktime has elapsed. trx.LockTime = new LockTime(stratisSender.FullNode.ChainIndexer.Height - 1); // Sign trx again after changing the nLockTime. trx = context.TransactionBuilder.SignTransaction(trx); // Enable standard policy relay. stratisSender.FullNode.NodeService <MempoolSettings>().RequireStandard = true; var broadcaster = stratisSender.FullNode.NodeService <IBroadcasterManager>(); broadcaster.BroadcastTransactionAsync(trx); TestBase.WaitLoop(() => stratisSender.CreateRPCClient().GetRawMempool().Length == 1); } }
public async Task Can_ClearAll_Banned_PeersAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); var nodeA = builder.CreateStratisPosNode(network, "nc-3-nodeA").Start(); var nodeB_Ip = "127.0.0.2"; var nodeB_IpAddress = IPAddress.Parse(nodeB_Ip); var nodeB_EndPoint = new IPEndPoint(nodeB_IpAddress, 0); var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>(); nodeAaddressManager.AddPeer(new IPEndPoint(nodeB_IpAddress, 0), IPAddress.Loopback); var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>(); peerBanning.BanAndDisconnectPeer(nodeB_EndPoint); Assert.True(peerBanning.IsBanned(nodeB_EndPoint)); await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/clearbanned").PostJsonAsync(null); Assert.False(peerBanning.IsBanned(nodeB_EndPoint)); } }
public void Staking_Wallet_Can_Mint_New_Coins() { using (var builder = NodeBuilder.Create(this)) { var configParameters = new NodeConfigParameters { { "savetrxhex", "true" } }; var network = new StratisRegTest(); var minerA = builder.CreateStratisPosNode(network, "stake-1-minerA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start(); var addressUsed = TestHelper.MineBlocks(minerA, (int)network.Consensus.PremineHeight).AddressUsed; // Since the pre-mine will not be immediately spendable, the transactions have to be counted directly from the address. addressUsed.Transactions.Count().Should().Be((int)network.Consensus.PremineHeight); addressUsed.Transactions.Sum(s => s.Amount).Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward); // Mine blocks to maturity TestHelper.MineBlocks(minerA, (int)network.Consensus.CoinbaseMaturity + 10); // Get set of transaction IDs present in wallet before staking is started. this.transactionsBeforeStaking.Clear(); foreach (TransactionData transactionData in this.GetTransactionsSnapshot(minerA)) { this.transactionsBeforeStaking.Add(transactionData.Id); } // Start staking on the node. var minter = minerA.FullNode.NodeService <IPosMinting>(); minter.Stake(new WalletSecret() { WalletName = "mywallet", WalletPassword = "******" }); // If new transactions are appearing in the wallet, staking has been successful. Due to coin maturity settings the // spendable balance of the wallet actually drops after staking, so the wallet balance should not be used to // determine whether staking occurred. TestBase.WaitLoop(() => { List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA); foreach (TransactionData transactionData in transactions) { if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false)) { return(true); } } return(false); }); // build a dictionary of coinstake tx's indexed by tx id. foreach (var tx in this.GetTransactionsSnapshot(minerA)) { this.transactionLookup[tx.Id] = tx; } TestBase.WaitLoop(() => { List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA); foreach (TransactionData transactionData in transactions) { if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false)) { Transaction coinstakeTransaction = minerA.FullNode.Network.CreateTransaction(transactionData.Hex); var balance = new Money(0); // Add coinstake outputs to balance. foreach (TxOut output in coinstakeTransaction.Outputs) { balance += output.Value; } // Subtract coinstake inputs from balance. foreach (TxIn input in coinstakeTransaction.Inputs) { this.transactionLookup.TryGetValue(input.PrevOut.Hash, out TransactionData prevTransactionData); if (prevTransactionData == null) { continue; } Transaction prevTransaction = minerA.FullNode.Network.CreateTransaction(prevTransactionData.Hex); balance -= prevTransaction.Outputs[input.PrevOut.N].Value; } Assert.Equal(minerA.FullNode.Network.Consensus.ProofOfStakeReward, balance); return(true); } } return(false); }); } }
public void Transaction_TraversesNodes_AndIsMined_AndNodesSync() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode xNode1 = builder.CreateStratisXNode(version: "2.0.0.5").Start(); var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC()); var config = new NodeConfigParameters(); config.Add("whitelist", xNode1.Endpoint.ToString()); config.Add("gateway", "1"); CoreNode sbfnNode2 = builder .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config) .WithWallet().Start(); CoreNode xNode3 = builder.CreateStratisXNode(version: "2.0.0.5").Start(); RPCClient xRpc1 = xNode1.CreateRPCClient(); RPCClient sbfnRpc2 = sbfnNode2.CreateRPCClient(); RPCClient xRpc3 = xNode3.CreateRPCClient(); sbfnRpc2.AddNode(xNode1.Endpoint, false); sbfnRpc2.AddNode(xNode3.Endpoint, false); xRpc1.SendCommand(RPCOperations.generate, 11); var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 11, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == sbfnRpc2.GetBestBlockHash(), cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == xRpc3.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Send transaction to arbitrary address. var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); xRpc1.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1); TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // TODO: Until #2468 is fixed we need an X node to mine the block so it doesn't get rejected. xRpc1.SendCommand(RPCOperations.generate, 1); TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 12, cancellationToken: shortCancellationToken); // We expect that SBFN and the other X node will sync correctly. TestBase.WaitLoop(() => sbfnRpc2.GetBestBlockHash() == xRpc1.GetBestBlockHash(), cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc3.GetBestBlockHash() == xRpc1.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Sanity check - mempools should all become empty. TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); } }
public void XMinesTransaction_SBFNSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC()); var config = new NodeConfigParameters(); config.Add("whitelist", stratisXNode.Endpoint.ToString()); config.Add("gateway", "1"); CoreNode stratisNode = builder .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config) .WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); stratisXRpc.AddNode(stratisNode.Endpoint, false); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); stratisXRpc.SendCommand(RPCOperations.generate, 11); var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token; // Without this there seems to be a race condition between the blocks all getting generated and SBFN syncing high enough to fall through the getbestblockhash check. TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 11, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Send transaction to arbitrary address from X side. var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); stratisXRpc.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1); TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // Transaction should percolate through to SBFN's mempool. TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // Now X must mine the block. stratisXRpc.SendCommand(RPCOperations.generate, 1); TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 12, cancellationToken: shortCancellationToken); // We expect that SBFN will sync correctly. TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Sanity check - mempools should both become empty. TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); } }
public void SBFNCreatesOpReturnTransaction_XSyncs() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); // We do not want the datetime provider to be substituted, // so a custom builder callback has to be used. var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC() .UseTestChainedHeaderTree() .MockIBD()); CoreNode stratisNode = builder.CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION).WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); stratisXRpc.AddNode(stratisNode.Endpoint, false); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); TestHelper.MineBlocks(stratisNode, 11); // It takes a reasonable amount of time for blocks to be generated without // the datetime provider substitution. var longCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(15)).Token; var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: longCancellationToken); // Send transaction to arbitrary address from SBFN side. var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); //stratisNodeRpc.WalletPassphrase("password", 60); var transactionBuildContext = new TransactionBuildContext(stratisNode.FullNode.Network) { AccountReference = new WalletAccountReference("mywallet", "account 0"), MinConfirmations = 1, OpReturnData = "test", OpReturnAmount = Money.Coins(0.01m), WalletPassword = "******", Recipients = new List <Recipient>() { new Recipient() { Amount = Money.Coins(1), ScriptPubKey = aliceAddress.ScriptPubKey } } }; var transaction = stratisNode.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext); stratisNode.FullNode.NodeController <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex())); TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // Transaction should percolate through to X's mempool. TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); } }
public void SBFNMinesTransaction_XSyncs() { // TODO: Currently fails due to issue #2468 (coinbase // reward on stratisX cannot be >4. No fees are allowed) if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Add the necessary executables for Linux & OSX return; } using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new StratisRegTest(); CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start(); // We do not want the datetime provider to be substituted, // so a custom builder callback has to be used. var callback = new Action <IFullNodeBuilder>(build => build .UseBlockStore() .UsePosConsensus() .UseMempool() .UseWallet() .AddPowPosMining() .AddRPC() .UseTestChainedHeaderTree() .MockIBD()); CoreNode stratisNode = builder.CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION).WithWallet().Start(); RPCClient stratisXRpc = stratisXNode.CreateRPCClient(); RPCClient stratisNodeRpc = stratisNode.CreateRPCClient(); stratisXRpc.AddNode(stratisNode.Endpoint, false); stratisNodeRpc.AddNode(stratisXNode.Endpoint, false); TestHelper.MineBlocks(stratisNode, 11); // It takes a reasonable amount of time for blocks to be generated without // the datetime provider substitution. var longCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(15)).Token; var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token; TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: longCancellationToken); // Send transaction to arbitrary address from SBFN side. var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); stratisNodeRpc.WalletPassphrase("password", 60); stratisNodeRpc.SendToAddress(aliceAddress, Money.Coins(1.0m)); TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // Transaction should percolate through to X's mempool. TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken); // Now SBFN must mine the block. TestHelper.MineBlocks(stratisNode, 1); // We expect that X will sync correctly. TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: shortCancellationToken); // Sanity check - mempools should both become empty. TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken); } }
public void Staking_Wont_Include_Time_Ahead_Of_Coinstake_Timestamp() { using (var builder = NodeBuilder.Create(this)) { var configParameters = new NodeConfigParameters { { "savetrxhex", "true" } }; var network = new StratisRegTest(); var minerA = builder.CreateStratisPosNode(network, "stake-1-minerA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start(); var addressUsed = TestHelper.MineBlocks(minerA, (int)network.Consensus.PremineHeight).AddressUsed; var wallet = minerA.FullNode.WalletManager().Wallets.Single(w => w.Name == "mywallet"); var allTrx = wallet.walletStore.GetForAddress(addressUsed.Address); // Since the pre-mine will not be immediately spendable, the transactions have to be counted directly from the address. allTrx.Count().Should().Be((int)network.Consensus.PremineHeight); allTrx.Sum(s => s.Amount).Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward); var balance = minerA.FullNode.WalletManager().GetAddressBalance(addressUsed.Address); balance.AmountConfirmed.Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward); // Mine blocks to maturity. TestHelper.MineBlocks(minerA, (int)network.Consensus.CoinbaseMaturity + 1); // Create a transaction and set its timestamp to one that will be rejected from the block. Transaction tx = minerA.FullNode.WalletTransactionHandler().BuildTransaction(new TransactionBuildContext(network) { Recipients = new List <Recipient>() { new Recipient { ScriptPubKey = addressUsed.ScriptPubKey, Amount = Money.Coins(1m) } }, AccountReference = new WalletAccountReference(minerA.WalletName, "account 0"), WalletPassword = minerA.WalletPassword, Time = (uint)minerA.FullNode.DateTimeProvider.GetAdjustedTimeAsUnixTimestamp() }); minerA.AddToStratisMempool(tx); TestBase.WaitLoop(() => minerA.FullNode.MempoolManager().InfoAll().Count == 1); // Get our height right now. int currentHeight = minerA.FullNode.ChainIndexer.Height; // Start staking on the node. var minter = minerA.FullNode.NodeService <IPosMinting>(); minter.Stake(new WalletSecret() { WalletName = minerA.WalletName, WalletPassword = minerA.WalletPassword }); // Ensure we've staked a block. TestBase.WaitLoop(() => minerA.FullNode.ChainIndexer.Height > currentHeight); // Get the staked block. ChainedHeader header = minerA.FullNode.ChainIndexer.GetHeader(currentHeight + 1); Block block = minerA.FullNode.BlockStore().GetBlock(header.HashBlock); // The transaction should not be in it. Assert.DoesNotContain(block.Transactions, x => x.GetHash() == tx.GetHash()); } }