public async Task <uint256> InsertMerkleProof() { var blockStream = await RpcClient.GetBlockAsStreamAsync(await RpcClient.GetBestBlockHashAsync()); var firstBlock = HelperTools.ParseByteStreamToBlock(blockStream); var block = firstBlock.CreateNextBlockWithCoinbase(firstBlock.Transactions.First().Outputs.First().ScriptPubKey.GetDestinationPublicKeys().First(), new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); var firstBlockHash = firstBlock.GetHash(); var tx = Transaction.Parse(Tx1Hex, Network.Main); block.AddTransaction(tx); tx = Transaction.Parse(Tx2Hex, Network.Main); block.AddTransaction(tx); tx = Transaction.Parse(Tx3Hex, Network.Main); block.AddTransaction(tx); tx = Transaction.Parse(Tx4Hex, Network.Main); block.AddTransaction(tx); tx = Transaction.Parse(Tx5Hex, Network.Main); block.AddTransaction(tx); rpcClientFactoryMock.AddKnownBlock((await RpcClient.GetBlockCountAsync()) + 1, block.ToBytes()); var node = NodeRepository.GetNodes().First(); var rpcClient = rpcClientFactoryMock.Create(node.Host, node.Port, node.Username, node.Password); PublishBlockHashToEventBus(await rpcClient.GetBestBlockHashAsync()); return(firstBlockHash); }
private async Task <uint256> AddBlocks(bool dsCheckMempool) { long blockCount = await RpcClient.GetBlockCountAsync(); var blockStream = await RpcClient.GetBlockAsStreamAsync(await RpcClient.GetBestBlockHashAsync()); var firstBlock = HelperTools.ParseByteStreamToBlock(blockStream); rpcClientFactoryMock.AddKnownBlock(blockCount++, firstBlock.ToBytes()); PublishBlockHashToEventBus(await RpcClient.GetBestBlockHashAsync()); var firstBlockHash = firstBlock.GetHash(); var pubKey = firstBlock.Transactions.First().Outputs.First().ScriptPubKey.GetDestinationPublicKeys().First(); var block1 = firstBlock.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); var tx = Transaction.Parse(Tx1Hex, Network.Main); block1.AddTransaction(tx); block1.Check(); long forkHeight = blockCount++; rpcClientFactoryMock.AddKnownBlock(forkHeight, block1.ToBytes()); PublishBlockHashToEventBus(await RpcClient.GetBestBlockHashAsync()); var block2 = block1.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); var tx2 = Transaction.Parse(Tx2Hex, Network.Main); block2.AddTransaction(tx2); block2.Check(); rpcClientFactoryMock.AddKnownBlock(blockCount++, block2.ToBytes()); PublishBlockHashToEventBus(await RpcClient.GetBestBlockHashAsync()); if (dsCheckMempool) { // Use already inserted tx2, but change Version so we get new hash var nextBlock = block1.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); var doubleSpendTx = Transaction.Parse(Tx2Hex, Network.Main); doubleSpendTx.Version = 2; doubleSpendTx.GetHash(); nextBlock.AddTransaction(doubleSpendTx); nextBlock.Check(); rpcClientFactoryMock.AddKnownBlock(forkHeight, nextBlock.ToBytes()); } // check if created successfully await CheckBlockPresentInDbAsync(firstBlockHash); return(firstBlockHash); }
public async Task TestBigBlocks(double txsCount) { var node = NodeRepository.GetNodes().First(); var rpcClient = rpcClientFactoryMock.Create(node.Host, node.Port, node.Username, node.Password); var stream = new MemoryStream(Encoders.Hex.DecodeData(File.ReadAllText(@"Data/16mb_tx.txt"))); var bStream = new BitcoinStream(stream, false) { MaxArraySize = unchecked ((int)uint.MaxValue) }; var tx = Transaction.Create(Network.Main); tx.ReadWrite(bStream); var txId = tx.GetHash(int.MaxValue).ToString(); _ = await CreateAndInsertTxAsync(false, true, 2, new string[] { txId.ToString() }); List <Transaction> txs = new(); for (int i = 0; i < txsCount; i++) { txs.Add(tx); } (_, string blockHash) = await CreateAndPublishNewBlockWithTxs(rpcClient, null, txs.ToArray(), true, true); var block = await TxRepositoryPostgres.GetBestBlockAsync(); Assert.IsFalse(HelperTools.AreByteArraysEqual(block.BlockHash, new uint256(blockHash).ToBytes())); PublishBlockHashToEventBus(blockHash); WaitUntilEventBusIsIdle(); block = await TxRepositoryPostgres.GetBestBlockAsync(); Assert.IsTrue(HelperTools.AreByteArraysEqual(block.BlockHash, new uint256(blockHash).ToBytes())); Assert.AreEqual(0, (await TxRepositoryPostgres.GetUnparsedBlocksAsync()).Length); // check if block was correctly parsed var blockStream = await RpcClient.GetBlockAsStreamAsync(await RpcClient.GetBestBlockHashAsync()); var parsedBlock = HelperTools.ParseByteStreamToBlock(blockStream); Assert.AreEqual(txsCount + 1, parsedBlock.Transactions.Count); }
public async Task <(Transaction doubleSpendTx, Transaction originalTx, uint256 firstBlockHash)> InsertDoubleSpend() { var node = NodeRepository.GetNodes().First(); var rpcClient = (Mock.RpcClientMock)rpcClientFactoryMock.Create(node.Host, node.Port, node.Username, node.Password); long blockCount = await RpcClient.GetBlockCountAsync(); var blockStream = await RpcClient.GetBlockAsStreamAsync(await RpcClient.GetBestBlockHashAsync()); var firstBlock = HelperTools.ParseByteStreamToBlock(blockStream); rpcClientFactoryMock.AddKnownBlock(blockCount++, firstBlock.ToBytes()); var firstBlockHash = firstBlock.GetHash(); var tx = Transaction.Parse(Tx1Hex, Network.Main); var(forkHeight, _) = await CreateAndPublishNewBlock(rpcClient, null, tx, true); var tx2 = Transaction.Parse(Tx2Hex, Network.Main); await CreateAndPublishNewBlock(rpcClient, null, tx2, true); tx = Transaction.Parse(Tx3Hex, Network.Main); await CreateAndPublishNewBlock(rpcClient, null, tx, true); tx = Transaction.Parse(Tx4Hex, Network.Main); await CreateAndPublishNewBlock(rpcClient, null, tx, true); tx = Transaction.Parse(Tx5Hex, Network.Main); var(_, blockHash) = await CreateAndPublishNewBlock(rpcClient, null, tx, true); PublishBlockHashToEventBus(blockHash); // Use already inserted tx2 with changing only Version so we get new TxId var doubleSpendTx = Transaction.Parse(Tx2Hex, Network.Main); doubleSpendTx.Version = 2; doubleSpendTx.GetHash(); await CreateAndPublishNewBlock(rpcClient, forkHeight, doubleSpendTx); return(doubleSpendTx, tx2, firstBlockHash); }
public virtual async Task TestSkipParsing() { var node = NodeRepository.GetNodes().First(); var rpcClient = (Mock.RpcClientMock)rpcClientFactoryMock.Create(node.Host, node.Port, node.Username, node.Password); long blockCount = await RpcClient.GetBlockCountAsync(); var blockStream = await RpcClient.GetBlockAsStreamAsync(await RpcClient.GetBestBlockHashAsync()); var firstBlock = HelperTools.ParseByteStreamToBlock(blockStream); rpcClientFactoryMock.AddKnownBlock(blockCount++, firstBlock.ToBytes()); var tx = Transaction.Parse(Tx1Hex, Network.Main); await CreateAndPublishNewBlock(rpcClient, null, tx, true); Assert.AreEqual(0, (await TxRepositoryPostgres.GetUnparsedBlocksAsync()).Length); var block = await TxRepositoryPostgres.GetBestBlockAsync(); // we publish same NewBlockAvailableInDB as before var block2Parse = block; EventBus.Publish(new NewBlockAvailableInDB { BlockDBInternalId = block2Parse.BlockInternalId, BlockHash = new uint256(block2Parse.BlockHash).ToString() }); WaitUntilEventBusIsIdle(); // best block must stay the same, since parsing was skipped var blockAfterRepublish = await TxRepositoryPostgres.GetBestBlockAsync(); Assert.AreEqual(block.BlockInternalId, blockAfterRepublish.BlockInternalId); Assert.AreEqual(block.ParsedForMerkleAt, blockAfterRepublish.ParsedForMerkleAt); Assert.AreEqual(block.ParsedForDSAt, blockAfterRepublish.ParsedForDSAt); }
public async Task <(long, string)> CreateAndPublishNewBlockWithTxs(IRpcClient rpcClient, long?blockHeightToStartFork, Transaction[] transactions, bool noPublish = false, bool bigBlock = false) { string blockHash = null; long blockHeight = await rpcClient.GetBlockCountAsync(); if (blockHeight == 0) { var blockStream = await rpcClient.GetBlockAsStreamAsync(await rpcClient.GetBestBlockHashAsync()); var firstBlock = HelperTools.ParseByteStreamToBlock(blockStream); rpcClientFactoryMock.AddKnownBlock(blockHeight, firstBlock.ToBytes()); PublishBlockHashToEventBus(await rpcClient.GetBestBlockHashAsync()); } PubKey pubKey = new Key().PubKey; if (transactions != null) { NBitcoin.Block lastBlock; if (blockHeightToStartFork.HasValue) { lastBlock = NBitcoin.Block.Load(await rpcClient.GetBlockByHeightAsBytesAsync(blockHeightToStartFork.Value), Network.Main); } else { lastBlock = HelperTools.ParseByteStreamToBlock(await rpcClient.GetBlockAsStreamAsync(await rpcClient.GetBestBlockHashAsync())); } var block = lastBlock.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); foreach (var transaction in transactions) { block.AddTransaction(transaction); } if (!bigBlock) { block.Check(); } if (blockHeightToStartFork.HasValue) { blockHeight = blockHeightToStartFork.Value; } if (bigBlock) { rpcClientFactoryMock.AddBigKnownBlock(++blockHeight, block); } else { rpcClientFactoryMock.AddKnownBlock(++blockHeight, block.ToBytes()); } blockHash = block.GetHash().ToString(); if (!noPublish) { PublishBlockHashToEventBus(block.GetHash().ToString()); } } return(blockHeight, blockHash); }