internal RuleList GetBlocksToTest(bool addSigExpensiveBlocks, bool runLargeReorgs) { List <Rule> blocks = new List <Rule>(); RuleList ret = new RuleList(blocks, hashHeaderMap, 10); Queue <TransactionOutPointWithValue> spendableOutputs = new Queue <TransactionOutPointWithValue>(); int chainHeadHeight = 1; Block chainHead = Network.GetGenesis().CreateNextBlockWithCoinbase(coinbaseOutKeyPubKey, Money.Parse("50")); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, chainHead, true, false, chainHead.GetHash(), 1, "Initial Block")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(chainHead.Transactions[0].GetHash(), 0), Money.Parse("50"), chainHead.Transactions[0].Outputs[0].ScriptPubKey)); for (int i = 1; i < Network.SpendableCoinbaseDepth; i++) { chainHead = chainHead.CreateNextBlockWithCoinbase(coinbaseOutKeyPubKey, Money.Parse("50")); chainHeadHeight++; blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, chainHead, true, false, chainHead.GetHash(), i + 1, "Initial Block chain output generation")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(chainHead.Transactions[0].GetHash(), 0), Money.Parse("50"), chainHead.Transactions.First().Outputs.First().ScriptPubKey)); } // Start by building a couple of blocks on top of the genesis block. Block b1 = createNextBlock(chainHead, chainHeadHeight + 1, spendableOutputs.Dequeue(), null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b1, true, false, b1.GetHash(), chainHeadHeight + 1, "b1")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b1.Transactions[0].GetHash(), 0), b1.Transactions[0].Outputs[0].Value, b1.Transactions[0].Outputs[0].ScriptPubKey)); TransactionOutPointWithValue out1 = spendableOutputs.Dequeue(); Assert.True(out1 != null); Block b2 = createNextBlock(b1, chainHeadHeight + 2, out1, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b2, true, false, b2.GetHash(), chainHeadHeight + 2, "b2")); // Make sure nothing funky happens if we try to re-add b2 blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b2, true, false, b2.GetHash(), chainHeadHeight + 2, "b2")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b2.Transactions[0].GetHash(), 0), b2.Transactions[0].Outputs[0].Value, b2.Transactions[0].Outputs[0].ScriptPubKey)); // We now have the following chain (which output is spent is in parentheses): // genesis -> b1 (0) -> b2 (1) // // so fork like this: // // genesis -> b1 (0) -> b2 (1) // \-> b3 (1) // // Nothing should happen at this point. We saw b2 first so it takes priority. Block b3 = createNextBlock(b1, chainHeadHeight + 2, out1, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b3, true, false, b2.GetHash(), chainHeadHeight + 2, "b3")); // Make sure nothing breaks if we add b3 twice blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b3, true, false, b2.GetHash(), chainHeadHeight + 2, "b3")); // Now we add another block to make the alternative chain longer. TransactionOutPointWithValue out2 = spendableOutputs.Dequeue(); Assert.True(out2 != null); Block b4 = createNextBlock(b3, chainHeadHeight + 3, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b4, true, false, b4.GetHash(), chainHeadHeight + 3, "b4")); // // genesis -> b1 (0) -> b2 (1) // \-> b3 (1) -> b4 (2) // // ... and back to the first chain. Block b5 = createNextBlock(b2, chainHeadHeight + 3, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b5, true, false, b4.GetHash(), chainHeadHeight + 3, "b5")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b5.Transactions[0].GetHash(), 0), b5.Transactions[0].Outputs[0].Value, b5.Transactions[0].Outputs[0].ScriptPubKey)); TransactionOutPointWithValue out3 = spendableOutputs.Dequeue(); Block b6 = createNextBlock(b5, chainHeadHeight + 4, out3, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b6, true, false, b6.GetHash(), chainHeadHeight + 4, "b6")); // // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) // \-> b3 (1) -> b4 (2) // // Try to create a fork that double-spends // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) // \-> b7 (3) -> b8 (4) // \-> b3 (1) -> b4 (2) // Block b7 = createNextBlock(b5, chainHeadHeight + 4, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b7, true, false, b6.GetHash(), chainHeadHeight + 4, "b7")); TransactionOutPointWithValue out4 = spendableOutputs.Dequeue(); Block b8 = createNextBlock(b7, chainHeadHeight + 5, out4, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b8, false, true, b6.GetHash(), chainHeadHeight + 4, "b8")); return(ret); }
internal RuleList GetBlocksToTest(bool addSigExpensiveBlocks, bool runLargeReorgs) { List<Rule> blocks = new List<Rule>(); RuleList ret = new RuleList(blocks, hashHeaderMap, 10); Queue<TransactionOutPointWithValue> spendableOutputs = new Queue<TransactionOutPointWithValue>(); int chainHeadHeight = 1; Block chainHead = Network.GetGenesis().CreateNextBlockWithCoinbase(coinbaseOutKeyPubKey, Money.Parse("50")); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, chainHead, true, false, chainHead.GetHash(), 1, "Initial Block")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(chainHead.Transactions[0].GetHash(), 0), Money.Parse("50"), chainHead.Transactions[0].Outputs[0].ScriptPubKey)); for(int i = 1 ; i < Network.SpendableCoinbaseDepth ; i++) { chainHead = chainHead.CreateNextBlockWithCoinbase(coinbaseOutKeyPubKey, Money.Parse("50")); chainHeadHeight++; blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, chainHead, true, false, chainHead.GetHash(), i + 1, "Initial Block chain output generation")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(chainHead.Transactions[0].GetHash(), 0), Money.Parse("50"), chainHead.Transactions.First().Outputs.First().ScriptPubKey)); } // Start by building a couple of blocks on top of the genesis block. Block b1 = createNextBlock(chainHead, chainHeadHeight + 1, spendableOutputs.Dequeue(), null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b1, true, false, b1.GetHash(), chainHeadHeight + 1, "b1")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b1.Transactions[0].GetHash(), 0), b1.Transactions[0].Outputs[0].Value, b1.Transactions[0].Outputs[0].ScriptPubKey)); TransactionOutPointWithValue out1 = spendableOutputs.Dequeue(); Assert.True(out1 != null); Block b2 = createNextBlock(b1, chainHeadHeight + 2, out1, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b2, true, false, b2.GetHash(), chainHeadHeight + 2, "b2")); // Make sure nothing funky happens if we try to re-add b2 blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b2, true, false, b2.GetHash(), chainHeadHeight + 2, "b2")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b2.Transactions[0].GetHash(), 0), b2.Transactions[0].Outputs[0].Value, b2.Transactions[0].Outputs[0].ScriptPubKey)); // We now have the following chain (which output is spent is in parentheses): // genesis -> b1 (0) -> b2 (1) // // so fork like this: // // genesis -> b1 (0) -> b2 (1) // \-> b3 (1) // // Nothing should happen at this point. We saw b2 first so it takes priority. Block b3 = createNextBlock(b1, chainHeadHeight + 2, out1, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b3, true, false, b2.GetHash(), chainHeadHeight + 2, "b3")); // Make sure nothing breaks if we add b3 twice blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b3, true, false, b2.GetHash(), chainHeadHeight + 2, "b3")); // Now we add another block to make the alternative chain longer. TransactionOutPointWithValue out2 = spendableOutputs.Dequeue(); Assert.True(out2 != null); Block b4 = createNextBlock(b3, chainHeadHeight + 3, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b4, true, false, b4.GetHash(), chainHeadHeight + 3, "b4")); // // genesis -> b1 (0) -> b2 (1) // \-> b3 (1) -> b4 (2) // // ... and back to the first chain. Block b5 = createNextBlock(b2, chainHeadHeight + 3, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b5, true, false, b4.GetHash(), chainHeadHeight + 3, "b5")); spendableOutputs.Enqueue(new TransactionOutPointWithValue( new OutPoint(b5.Transactions[0].GetHash(), 0), b5.Transactions[0].Outputs[0].Value, b5.Transactions[0].Outputs[0].ScriptPubKey)); TransactionOutPointWithValue out3 = spendableOutputs.Dequeue(); Block b6 = createNextBlock(b5, chainHeadHeight + 4, out3, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b6, true, false, b6.GetHash(), chainHeadHeight + 4, "b6")); // // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) // \-> b3 (1) -> b4 (2) // // Try to create a fork that double-spends // genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) // \-> b7 (3) -> b8 (4) // \-> b3 (1) -> b4 (2) // Block b7 = createNextBlock(b5, chainHeadHeight + 4, out2, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b7, true, false, b6.GetHash(), chainHeadHeight + 4, "b7")); TransactionOutPointWithValue out4 = spendableOutputs.Dequeue(); Block b8 = createNextBlock(b7, chainHeadHeight + 5, out4, null); blocks.Add(new BlockAndValidity(blockToHeightMap, hashHeaderMap, b8, false, true, b6.GetHash(), chainHeadHeight + 4, "b8")); return ret; }