Ejemplo n.º 1
0
        //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");
        }