//BlockChainのテスト(分岐がある場合・採掘・順番通りに追加されなかった場合) public static void Test22() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); BlockchainAccessDB bcadb = new BlockchainAccessDB(basepath); string bcadbPath = bcadb.GetPath(); if (File.Exists(bcadbPath)) File.Delete(bcadbPath); BlockManagerDB bmdb = new BlockManagerDB(basepath); string bmdbPath = bmdb.GetPath(); if (File.Exists(bmdbPath)) File.Delete(bmdbPath); BlockDB bdb = new BlockDB(basepath); string bdbPath = bdb.GetPath(0); if (File.Exists(bdbPath)) File.Delete(bdbPath); BlockFilePointersDB bfpdb = new BlockFilePointersDB(basepath); string bfpPath = bfpdb.GetPath(); if (File.Exists(bfpPath)) File.Delete(bfpPath); UtxoFileAccessDB ufadb = new UtxoFileAccessDB(basepath); string ufadbPath = ufadb.GetPath(); if (File.Exists(ufadbPath)) File.Delete(ufadbPath); UtxoFilePointersDB ufpdb = new UtxoFilePointersDB(basepath); string ufpdbPath = ufpdb.GetPath(); if (File.Exists(ufpdbPath)) File.Delete(ufpdbPath); UtxoFilePointersTempDB ufptempdb = new UtxoFilePointersTempDB(basepath); string ufptempdbPath = ufptempdb.GetPath(); if (File.Exists(ufptempdbPath)) File.Delete(ufptempdbPath); UtxoDB utxodb = new UtxoDB(basepath); string utxodbPath = utxodb.GetPath(); if (File.Exists(utxodbPath)) File.Delete(utxodbPath); BlockChain blockchain = new BlockChain(bcadb, bmdb, bdb, bfpdb, ufadb, ufpdb, ufptempdb, utxodb); BlockGenerator bg = new BlockGenerator(); Block[] blks = new Block[10]; double[] cumulativeDiffs0 = new double[blks.Length]; BlockContext[] blkCons = new BlockContext[blks.Length]; for (int i = 0; i < blks.Length; i++) { blkCons[i] = bg.CreateNextValidBlock(); blks[i] = blkCons[i].block; cumulativeDiffs0[i] = i == 0 ? blks[i].Difficulty.Diff : cumulativeDiffs0[i - 1] + blks[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + " created."); } Block[] blks2 = new Block[blks.Length]; double[] cumulativeDiffs1 = new double[blks.Length]; byte[] nonce = null; Func<long, TransactionalBlock> _indexToBlock = (index) => blks2[index] as TransactionalBlock; for (int i = 0; i < blks.Length; i++) { if (i == 0) { blks2[i] = blks[i]; cumulativeDiffs1[i] = blks2[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_1 " + blks2[i].Difficulty.Diff.ToString() + " " + cumulativeDiffs1[i].ToString()); continue; } TransactionalBlock tblk = blks[i] as TransactionalBlock; TransactionalBlock tblk2 = TransactionalBlock.GetBlockTemplate(tblk.Index, tblk.coinbaseTxToMiner, tblk.transferTxs, _indexToBlock, 0); nonce = new byte[10]; while (true) { tblk2.UpdateTimestamp(DateTime.Now); tblk2.UpdateNonce(nonce); if (tblk2.Id.CompareTo(tblk2.header.difficulty.Target) <= 0) { blks2[i] = tblk2; cumulativeDiffs1[i] = cumulativeDiffs1[i - 1] + blks2[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_1 mined. " + blks2[i].Difficulty.Diff.ToString() + " " + cumulativeDiffs1[i].ToString()); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } int forkIndex1 = 0; int forkIndex2 = 0; int[] forkIndexes = (blks.Length - 1).RandomNums(); if (forkIndexes[0] < forkIndexes[1]) { forkIndex1 = forkIndexes[0] + 1; forkIndex2 = forkIndexes[1] + 1; } else { forkIndex1 = forkIndexes[1] + 1; forkIndex2 = forkIndexes[0] + 1; } Block[] blks3 = new Block[blks.Length]; double[] cumulativeDiffs2 = new double[blks.Length]; Func<long, TransactionalBlock> _indexToBlock2 = (index) => index >= forkIndex1 ? blks3[index] as TransactionalBlock : blks2[index] as TransactionalBlock; for (int i = forkIndex1; i < blks.Length; i++) { TransactionalBlock tblk = blks[i] as TransactionalBlock; TransactionalBlock tblk3 = TransactionalBlock.GetBlockTemplate(tblk.Index, tblk.coinbaseTxToMiner, tblk.transferTxs, _indexToBlock2, 0); nonce = new byte[10]; while (true) { tblk3.UpdateTimestamp(DateTime.Now); tblk3.UpdateNonce(nonce); if (tblk3.Id.CompareTo(tblk3.header.difficulty.Target) <= 0) { blks3[i] = tblk3; if (i == forkIndex1) cumulativeDiffs2[i] = cumulativeDiffs1[i - 1] + blks3[i].Difficulty.Diff; else cumulativeDiffs2[i] = cumulativeDiffs2[i - 1] + blks3[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_2 mined. " + blks3[i].Difficulty.Diff.ToString() + " " + cumulativeDiffs2[i].ToString()); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } Block[] blks4 = new Block[blks.Length]; double[] cumulativeDiffs3 = new double[blks.Length]; Func<long, TransactionalBlock> _indexToBlock3 = (index) => index >= forkIndex2 ? blks4[index] as TransactionalBlock : blks2[index] as TransactionalBlock; for (int i = forkIndex2; i < blks.Length; i++) { TransactionalBlock tblk = blks[i] as TransactionalBlock; TransactionalBlock tblk3 = TransactionalBlock.GetBlockTemplate(tblk.Index, tblk.coinbaseTxToMiner, tblk.transferTxs, _indexToBlock3, 0); nonce = new byte[10]; while (true) { tblk3.UpdateTimestamp(DateTime.Now); tblk3.UpdateNonce(nonce); if (tblk3.Id.CompareTo(tblk3.header.difficulty.Target) <= 0) { blks4[i] = tblk3; if (i == forkIndex2) cumulativeDiffs3[i] = cumulativeDiffs1[i - 1] + blks4[i].Difficulty.Diff; else cumulativeDiffs3[i] = cumulativeDiffs3[i - 1] + blks4[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_3 mined. " + blks4[i].Difficulty.Diff.ToString() + " " + cumulativeDiffs3[i].ToString()); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } bool?[] map1 = new bool?[blks.Length]; bool?[] map2 = new bool?[blks.Length]; bool?[] map3 = new bool?[blks.Length]; bool?[] map4 = new bool?[blks.Length]; for (int i = 0; i < blks.Length; i++) { map1[i] = i == 0 ? (bool?)null : false; map2[i] = i == 0 ? (bool?)null : false; map3[i] = i < forkIndex1 ? (bool?)null : false; map4[i] = i < forkIndex2 ? (bool?)null : false; } blockchain.UpdateChain(blks[0]); int[] randomnums = (4 * blks.Length).RandomNums(); double cumulativeDiff = 0.0; int main = 0; int rejectedIndex = 0; for (int i = 0; i < randomnums.Length; i++) { int keiretsu = randomnums[i] / blks.Length; int index = randomnums[i] % blks.Length; if ((keiretsu == 0 && map1[index] == null) || (keiretsu == 1 && map2[index] == null) || (keiretsu == 2 && map3[index] == null) || (keiretsu == 3 && map4[index] == null)) continue; if (keiretsu == 0) { BlockChain.UpdateChainReturnType type = blockchain.UpdateChain(blks[index]); bool flag = false; for (int j = index - 1; j > 0; j--) if (!map1[j].Value) { flag = true; break; } if (!flag && index != 1) { if (type != BlockChain.UpdateChainReturnType.rejected) throw new Exception("test22_1"); } else { if (!flag) { int headIndex = index; for (int j = index + 1; j < blks.Length; j++) if (map1[j].Value) headIndex = j; else break; if (cumulativeDiff >= cumulativeDiffs0[headIndex]) flag = true; else rejectedIndex = headIndex; } if (flag && type != BlockChain.UpdateChainReturnType.pending) throw new Exception("test22_2"); if (!flag && type != BlockChain.UpdateChainReturnType.updatedAndRejected) throw new Exception("test22_3"); } map1[index] = true; } else if (keiretsu == 1) { BlockChain.UpdateChainReturnType type = blockchain.UpdateChain(blks2[index]); bool flag = false; for (int j = index - 1; j > 0; j--) if (!map2[j].Value) { flag = true; break; } if (!flag) { int headIndex1 = index; for (int j = index + 1; j < blks.Length; j++) if (map2[j].Value) headIndex1 = j; else break; double cdiff = cumulativeDiffs1[headIndex1]; int m = 1; if (headIndex1 + 1 >= forkIndex1 && map3[forkIndex1].Value) { int headIndex2 = forkIndex1; for (int j = forkIndex1 + 1; j < blks.Length; j++) if (map3[j].Value) headIndex2 = j; else break; //<未実装>等しい場合の対処 if (cumulativeDiffs2[headIndex2] > cdiff) { cdiff = cumulativeDiffs2[headIndex2]; m = 2; } else if (cumulativeDiffs2[headIndex2] == cdiff) { Console.WriteLine("not_implemented_test_case"); return; } } if (headIndex1 + 1 >= forkIndex2 && map4[forkIndex2].Value) { int headIndex3 = forkIndex2; for (int j = forkIndex2 + 1; j < blks.Length; j++) if (map4[j].Value) headIndex3 = j; else break; //<未実装>等しい場合の対処 if (cumulativeDiffs3[headIndex3] > cdiff) { cdiff = cumulativeDiffs3[headIndex3]; m = 3; } else if (cumulativeDiffs3[headIndex3] == cdiff) { Console.WriteLine("not_implemented_test_case"); return; } } if (cumulativeDiff >= cdiff) flag = true; else { cumulativeDiff = cdiff; main = m; } } if (flag && type != BlockChain.UpdateChainReturnType.pending) throw new Exception("test22_4"); if (!flag && type != BlockChain.UpdateChainReturnType.updated) throw new Exception("test22_5"); map2[index] = true; } else if (keiretsu == 2) { BlockChain.UpdateChainReturnType type = blockchain.UpdateChain(blks3[index]); bool flag = false; for (int j = index - 1; j >= forkIndex1; j--) if (!map3[j].Value) { flag = true; break; } if (!flag) for (int j = forkIndex1 - 1; j > 0; j--) if (!map2[j].Value) { flag = true; break; } if (!flag) { int headIndex = index; for (int j = index + 1; j < blks.Length; j++) if (map3[j].Value) headIndex = j; else break; if (cumulativeDiff >= cumulativeDiffs2[headIndex]) flag = true; else { cumulativeDiff = cumulativeDiffs2[headIndex]; main = 2; } } if (flag && type != BlockChain.UpdateChainReturnType.pending) throw new Exception("test22_6"); if (!flag && type != BlockChain.UpdateChainReturnType.updated) throw new Exception("test22_7"); map3[index] = true; } else if (keiretsu == 3) { BlockChain.UpdateChainReturnType type = blockchain.UpdateChain(blks4[index]); bool flag = false; for (int j = index - 1; j >= forkIndex2; j--) if (!map4[j].Value) { flag = true; break; } if (!flag) for (int j = forkIndex2 - 1; j > 0; j--) if (!map2[j].Value) { flag = true; break; } if (!flag) { int headIndex = index; for (int j = index + 1; j < blks.Length; j++) if (map4[j].Value) headIndex = j; else break; if (cumulativeDiff >= cumulativeDiffs3[headIndex]) flag = true; else { cumulativeDiff = cumulativeDiffs3[headIndex]; main = 3; } } if (flag && type != BlockChain.UpdateChainReturnType.pending) throw new Exception("test22_8"); if (!flag && type != BlockChain.UpdateChainReturnType.updated) throw new Exception("test22_9"); map4[index] = true; } bool flag2 = true; for (int j = 1; j < blks.Length; j++) { if (map1[j].Value) { if (flag2 && j <= rejectedIndex) { if (blockchain.rejectedBlocks[j + 1] == null || !blockchain.rejectedBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_10"); if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_11"); } else { if (blockchain.rejectedBlocks[j + 1] != null && blockchain.rejectedBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_12"); if (blockchain.pendingBlocks[j + 1] == null || !blockchain.pendingBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_13"); } } else { flag2 = false; if (blockchain.rejectedBlocks[j + 1] != null && blockchain.rejectedBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_14"); if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks[j].Id)) throw new Exception("test22_15"); } } bool flag3 = true; for (int j = 1; j < blks.Length; j++) { if (blockchain.rejectedBlocks[j + 1] != null && blockchain.rejectedBlocks[j + 1].Keys.Contains(blks2[j].Id)) throw new Exception("test22_16"); if (map2[j].Value) { if (flag3 && (main == 1 || (main == 2 && j < forkIndex1) || (main == 3 && j < forkIndex2))) { if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks2[j].Id)) throw new Exception("test22_17"); } else { if (blockchain.pendingBlocks[j + 1] == null || !blockchain.pendingBlocks[j + 1].Keys.Contains(blks2[j].Id)) throw new Exception("test22_18"); } } else { flag3 = false; if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks2[j].Id)) throw new Exception("test22_19"); } } bool flag4 = true; for (int j = forkIndex1; j < blks.Length; j++) { if (blockchain.rejectedBlocks[j + 1] != null && blockchain.rejectedBlocks[j + 1].Keys.Contains(blks3[j].Id)) throw new Exception("test22_20"); if (map3[j].Value) { if (flag4 && main == 2) { if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks3[j].Id)) throw new Exception("test22_21"); } else { if (blockchain.pendingBlocks[j + 1] == null || !blockchain.pendingBlocks[j + 1].Keys.Contains(blks3[j].Id)) throw new Exception("test22_22"); } } else { flag4 = false; if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks3[j].Id)) throw new Exception("test22_23"); } } bool flag5 = true; for (int j = forkIndex2; j < blks.Length; j++) { if (blockchain.rejectedBlocks[j + 1] != null && blockchain.rejectedBlocks[j + 1].Keys.Contains(blks4[j].Id)) throw new Exception("test22_24"); if (map4[j].Value) { if (flag5 && main == 3) { if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks4[j].Id)) throw new Exception("test22_25"); } else { if (blockchain.pendingBlocks[j + 1] == null || !blockchain.pendingBlocks[j + 1].Keys.Contains(blks4[j].Id)) throw new Exception("test22_26"); } } else { flag5 = false; if (blockchain.pendingBlocks[j + 1] != null && blockchain.pendingBlocks[j + 1].Keys.Contains(blks4[j].Id)) throw new Exception("test22_27"); } } } Block headBlock = blockchain.GetHeadBlock(); if (main == 1) { if (!headBlock.Id.Equals(blks2[9].Id)) throw new Exception("test22_28"); } else if (main == 2) { if (!headBlock.Id.Equals(blks3[9].Id)) throw new Exception("test22_29"); } else if (main == 3) { if (!headBlock.Id.Equals(blks4[9].Id)) throw new Exception("test22_30"); } else throw new InvalidOperationException(); utxodb.Open(); foreach (var address in blkCons[9].unspentTxOuts.Keys) foreach (var toc in blkCons[9].unspentTxOuts[address]) if (blockchain.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) == null) throw new Exception("test22_31"); foreach (var address in blkCons[9].spentTxOuts.Keys) foreach (var toc in blkCons[9].spentTxOuts[address]) if (blockchain.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) != null) throw new Exception("test22_32"); utxodb.Close(); Console.WriteLine("test22_succeeded"); }