//UtxoManagerのテスト3 public static void Test6() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 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); UtxoManager utxom = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); int length = 100; Sha256Ripemd160Hash[] addrs = new Sha256Ripemd160Hash[length]; long[] bis = new long[length]; int[] tis = new int[length]; int[] tois = new int[length]; Creacoin[] cs = new Creacoin[length]; for (int i = 0; i < length; i++) { addrs[i] = new Sha256Ripemd160Hash(BitConverter.GetBytes(i)); bis[i] = 65536.RandomNum(); tis[i] = 65536.RandomNum(); tois[i] = 65536.RandomNum(); cs[i] = new Creacoin(65536.RandomNum()); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); utxodb.Open(); for (int i = 0; i < length; i++) utxom.AddUtxo(addrs[i], bis[i], tis[i], tois[i], cs[i]); utxom.SaveUFPTemp(); utxodb.Close(); stopwatch.Stop(); Console.WriteLine(string.Join(":", "test6_5", stopwatch.ElapsedMilliseconds.ToString() + "ms")); UtxoManager utxom2 = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); Utxo[] utxos = new Utxo[length]; stopwatch.Reset(); stopwatch.Start(); utxodb.Open(); for (int i = 0; i < length; i++) utxos[i] = utxom.FindUtxo(addrs[i], bis[i], tis[i], tois[i]); utxodb.Close(); stopwatch.Stop(); Console.WriteLine(string.Join(":", "test6_6", stopwatch.ElapsedMilliseconds.ToString() + "ms")); for (int i = 0; i < length; i++) { if (utxos[i].blockIndex != bis[i]) throw new Exception("test6_1"); if (utxos[i].txIndex != tis[i]) throw new Exception("test6_2"); if (utxos[i].txOutIndex != tois[i]) throw new Exception("test6_3"); if (utxos[i].amount.rawAmount != cs[i].rawAmount) throw new Exception("test6_4"); } }
public void StartSystem() { if (isSystemStarted) throw new InvalidOperationException("core_started"); ahdb = new AccountHoldersDatabase(databaseBasepath); thdb = new TransactionHistoriesDatabase(databaseBasepath); bcadb = new BlockchainAccessDB(databaseBasepath); bmdb = new BlockManagerDB(databaseBasepath); bdb = new BlockDB(databaseBasepath); bfpdb = new BlockFilePointersDB(databaseBasepath); ufadb = new UtxoFileAccessDB(databaseBasepath); ufpdb = new UtxoFilePointersDB(databaseBasepath); ufptempdb = new UtxoFilePointersTempDB(databaseBasepath); utxodb = new UtxoDB(databaseBasepath); accountHolders = new AccountHolders(); accountHoldersFactory = new AccountHoldersFactory(); byte[] ahDataBytes = ahdb.GetData(); if (ahDataBytes.Length != 0) accountHolders.FromBinary(ahDataBytes); else accountHolders.LoadVersion0(); transactionHistories = thdb.GetData().Pipe((data) => data.Length == 0 ? new TransactionHistories() : SHAREDDATA.FromBinary<TransactionHistories>(data)); transactionHistories.UnconfirmedTransactionAdded += (sender, e) => { foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) foreach (var prevTxOut in e.senders) if (account.Address.Equals(prevTxOut.Address)) account.accountStatus.unconfirmedAmount = new CurrencyUnit(account.accountStatus.unconfirmedAmount.rawAmount + prevTxOut.Amount.rawAmount); }; transactionHistories.UnconfirmedTransactionRemoved += (sender, e) => { foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) foreach (var prevTxOut in e.receivers) if (account.Address.Equals(prevTxOut.Address)) account.accountStatus.unconfirmedAmount = new CurrencyUnit(account.accountStatus.unconfirmedAmount.rawAmount - prevTxOut.Amount.rawAmount); }; usableBalanceCache = new CachedData<CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) rawAmount += account.accountStatus.usableAmount.rawAmount; return new CurrencyUnit(rawAmount); }); unusableBalanceCache = new CachedData<CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) rawAmount += account.accountStatus.unusableAmount.rawAmount; return new CurrencyUnit(rawAmount); }); unconfirmedBalanceCache = new CachedData<CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) rawAmount += account.accountStatus.unconfirmedAmount.rawAmount; return new CurrencyUnit(rawAmount); }); usableBalanceWithUnconfirmedCache = new CachedData<CurrencyUnit>(() => new CurrencyUnit(usableBalanceCache.Data.rawAmount - unconfirmedBalanceCache.Data.rawAmount)); unusableBalanceWithUnconformedCache = new CachedData<CurrencyUnit>(() => new CurrencyUnit(unusableBalanceCache.Data.rawAmount + unconfirmedBalanceCache.Data.rawAmount)); blockChain = new BlockChain(bcadb, bmdb, bdb, bfpdb, ufadb, ufpdb, ufptempdb, utxodb); blockChain.LoadTransactionHistories(transactionHistories); //<未改良>暫定? if (blockChain.headBlockIndex == -1) { blockChain.UpdateChain(new GenesisBlock()); this.RaiseNotification("genesis_block_generated", 5); } Dictionary<Account, EventHandler<Tuple<CurrencyUnit, CurrencyUnit>>> changeAmountDict = new Dictionary<Account, EventHandler<Tuple<CurrencyUnit, CurrencyUnit>>>(); Action<bool> _UpdateBalance = (isOnlyUnconfirmed) => { if (!isOnlyUnconfirmed) { usableBalanceCache.IsModified = true; unusableBalanceCache.IsModified = true; } unconfirmedBalanceCache.IsModified = true; usableBalanceWithUnconfirmedCache.IsModified = true; unusableBalanceWithUnconformedCache.IsModified = true; BalanceUpdated(this, EventArgs.Empty); }; Action<Account, bool> _AddAddressEvent = (account, isUpdatebalance) => { EventHandler<Tuple<CurrencyUnit, CurrencyUnit>> eh = (sender, e) => { account.accountStatus.usableAmount = e.Item1; account.accountStatus.unusableAmount = e.Item2; }; changeAmountDict.Add(account, eh); AddressEvent addressEvent = new AddressEvent(account.Address.Hash); addressEvent.BalanceUpdated += eh; blockChain.AddAddressEvent(addressEvent); long rawAmount = 0; foreach (var unconfirmedTh in transactionHistories.unconfirmedTransactionHistories.ToArray()) foreach (var prevTxOut in unconfirmedTh.senders) if (prevTxOut.Address.Equals(account.Address)) rawAmount += prevTxOut.Amount.rawAmount; account.accountStatus.unconfirmedAmount = new CurrencyUnit(rawAmount); if (isUpdatebalance) _UpdateBalance(false); }; EventHandler<Account> _AccountAdded = (sender, e) => { utxodb.Open(); _AddAddressEvent(e, true); utxodb.Close(); }; EventHandler<Account> _AccountRemoved = (sender, e) => { EventHandler<Tuple<CurrencyUnit, CurrencyUnit>> eh = changeAmountDict[e]; changeAmountDict.Remove(e); AddressEvent addressEvent = blockChain.RemoveAddressEvent(e.Address.Hash); addressEvent.BalanceUpdated -= eh; _UpdateBalance(false); }; utxodb.Open(); foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) _AddAddressEvent(account, false); accountHolder.AccountAdded += _AccountAdded; accountHolder.AccountRemoved += _AccountRemoved; } utxodb.Close(); accountHolders.AccountHolderAdded += (sender, e) => { e.AccountAdded += _AccountAdded; e.AccountRemoved += _AccountRemoved; }; accountHolders.AccountHolderRemoved += (semder, e) => { e.AccountAdded -= _AccountAdded; e.AccountRemoved -= _AccountRemoved; }; blockChain.BalanceUpdated += (sender, e) => _UpdateBalance(false); _UpdateBalance(false); unconfirmedTtxs = new Dictionary<TransferTransaction, TransactionOutput[]>(); mining = new Mining(); mining.FoundNonce += (sender, e) => creaNodeTest.DiffuseNewBlock(e); blockChain.Updated += (sender, e) => { foreach (var block in e) foreach (var tx in block.Transactions) foreach (var txIn in tx.TxInputs) { TransferTransaction contradiction = null; foreach (var unconfirmedTx in unconfirmedTtxs) { foreach (var unconfirmedTxIn in unconfirmedTx.Key.TxInputs) if (txIn.PrevTxBlockIndex == unconfirmedTxIn.PrevTxBlockIndex && txIn.PrevTxIndex == unconfirmedTxIn.PrevTxIndex && txIn.PrevTxOutputIndex == unconfirmedTxIn.PrevTxOutputIndex) { contradiction = unconfirmedTx.Key; break; } if (contradiction != null) break; } if (contradiction != null) unconfirmedTtxs.Remove(contradiction); } Mine(); }; Mine(); //creaNodeTest = new CreaNode(ps.NodePort, creaVersion, appnameWithVersion, new FirstNodeInfosDatabase(p2pDirectory)); creaNodeTest = new CreaNodeTest(blockChain, ps.NodePort, creaVersion, appnameWithVersion); creaNodeTest.ConnectionKeeped += (sender, e) => creaNodeTest.SyncronizeBlockchain(); creaNodeTest.ReceivedNewTransaction += (sender, e) => { TransferTransaction ttx = e as TransferTransaction; if (ttx == null) return; TransactionOutput[] prevTxOuts = new TransactionOutput[ttx.TxInputs.Length]; for (int i = 0; i < prevTxOuts.Length; i++) prevTxOuts[i] = blockChain.GetMainBlock(ttx.TxInputs[i].PrevTxBlockIndex).Transactions[ttx.TxInputs[i].PrevTxIndex].TxOutputs[ttx.TxInputs[i].PrevTxOutputIndex]; if (!ttx.Verify(prevTxOuts)) return; List<TransactionOutput> senders = new List<TransactionOutput>(); List<TransactionOutput> receivers = new List<TransactionOutput>(); long sentAmount = 0; long receivedAmount = 0; for (int i = 0; i < ttx.txInputs.Length; i++) foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) if (prevTxOuts[i].Address.Equals(account.Address.Hash)) { sentAmount += prevTxOuts[i].Amount.rawAmount; senders.Add(prevTxOuts[i]); } for (int i = 0; i < ttx.TxOutputs.Length; i++) foreach (var accountHolder in accountHolders.AllAccountHolders) foreach (var account in accountHolder.Accounts) if (ttx.TxOutputs[i].Address.Equals(account.Address.Hash)) { receivedAmount += ttx.TxOutputs[i].Amount.rawAmount; receivers.Add(ttx.TxOutputs[i]); } if (senders.Count > 0 || receivers.Count > 0) { TransactionHistoryType type = TransactionHistoryType.transfered; if (receivers.Count < ttx.TxOutputs.Length) type = TransactionHistoryType.sent; else if (senders.Count < ttx.TxInputs.Length) type = TransactionHistoryType.received; transactionHistories.AddTransactionHistory(new TransactionHistory(true, false, type, DateTime.MinValue, 0, ttx.Id, senders.ToArray(), receivers.ToArray(), ttx, prevTxOuts, new CurrencyUnit(sentAmount), new CurrencyUnit(receivedAmount - sentAmount))); } utxodb.Open(); for (int i = 0; i < ttx.TxInputs.Length; i++) if (blockChain.FindUtxo(prevTxOuts[i].Address, ttx.TxInputs[i].PrevTxBlockIndex, ttx.TxInputs[i].PrevTxIndex, ttx.TxInputs[i].PrevTxOutputIndex) == null) return; utxodb.Close(); foreach (var txIn in ttx.TxInputs) foreach (var unconfirmedTtx in unconfirmedTtxs) foreach (var unconfirmedTxIn in unconfirmedTtx.Key.TxInputs) if (txIn.PrevTxBlockIndex == unconfirmedTxIn.PrevTxBlockIndex && txIn.PrevTxIndex == unconfirmedTxIn.PrevTxIndex && txIn.PrevTxOutputIndex == unconfirmedTxIn.PrevTxOutputIndex) return; unconfirmedTtxs.Add(ttx, prevTxOuts); Mine(); }; creaNodeTest.ReceivedNewBlock += (sender, e) => blockChain.UpdateChain(e).Pipe((ret) => this.RaiseResult("blockchain_update", 5, ret.ToString())); //creaNodeTest.Start(); isSystemStarted = true; }
//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"); }
//UtxoManagerのテスト1 public static void Test4() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 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); UtxoManager utxom = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); if (File.Exists(ufadbPath)) throw new Exception("test4_9"); utxodb.Open(); Sha256Ripemd160Hash address1 = new Sha256Ripemd160Hash(new byte[] { 0 }); Sha256Ripemd160Hash address2 = new Sha256Ripemd160Hash(new byte[] { 1 }); Sha256Ripemd160Hash address3 = new Sha256Ripemd160Hash(new byte[] { 2 }); Utxo utxoNull = utxom.FindUtxo(address1, 65536.RandomNum(), 65536.RandomNum(), 65536.RandomNum()); if (utxoNull != null) throw new Exception("test4_1"); long bi1 = 65536.RandomNum(); int ti1 = 65536.RandomNum(); int toi1 = 65536.RandomNum(); Creacoin c1 = new Creacoin(65536.RandomNum()); long bi2 = 65536.RandomNum(); int ti2 = 65536.RandomNum(); int toi2 = 65536.RandomNum(); Creacoin c2 = new Creacoin(65536.RandomNum()); long bi3 = 65536.RandomNum(); int ti3 = 65536.RandomNum(); int toi3 = 65536.RandomNum(); Creacoin c3 = new Creacoin(65536.RandomNum()); utxom.AddUtxo(address1, bi1, ti1, toi1, c1); utxom.AddUtxo(address2, bi1, ti1, toi1, c1); utxom.AddUtxo(address3, bi1, ti1, toi1, c1); utxom.AddUtxo(address1, bi2, ti2, toi2, c2); utxom.AddUtxo(address2, bi2, ti2, toi2, c2); utxom.AddUtxo(address3, bi2, ti2, toi2, c2); utxom.AddUtxo(address1, bi3, ti3, toi3, c3); utxom.AddUtxo(address2, bi3, ti3, toi3, c3); utxom.AddUtxo(address3, bi3, ti3, toi3, c3); //2014/12/17追加 GetAllUtxosLatestFirstの試験 List<Utxo> utxos1 = utxom.GetAllUtxosLatestFirst(address1); List<Utxo> utxos2 = utxom.GetAllUtxosLatestFirst(address2); List<Utxo> utxos3 = utxom.GetAllUtxosLatestFirst(address3); if (utxos1.Count != 3) throw new Exception("test4_19"); if (utxos2.Count != 3) throw new Exception("test4_20"); if (utxos3.Count != 3) throw new Exception("test4_21"); long max = Math.Max(Math.Max(bi1, bi2), bi3); if (utxos1[0].blockIndex != max) throw new Exception("test4_22"); if (utxos2[0].blockIndex != max) throw new Exception("test4_23"); if (utxos3[0].blockIndex != max) throw new Exception("test4_24"); //2014/12/17追加(終) Utxo utxo1 = utxom.FindUtxo(address1, bi1, ti1, toi1); if (utxo1 == null) throw new Exception("test4_2"); if (utxo1.blockIndex != bi1) throw new Exception("test4_3"); if (utxo1.txIndex != ti1) throw new Exception("test4_4"); if (utxo1.txOutIndex != toi1) throw new Exception("test4_5"); if (utxo1.amount.rawAmount != c1.rawAmount) throw new Exception("test4_6"); utxom.AddUtxo(address1, bi1, ti1, toi1, c1); utxom.RemoveUtxo(address1, bi1, ti1, toi1); utxom.RemoveUtxo(address1, bi1, ti1, toi1); bool flag = false; try { utxom.RemoveUtxo(address1, bi1, ti1, toi1); } catch (InvalidOperationException) { flag = true; } if (!flag) throw new Exception("test4_7"); Utxo utxoNull2 = utxom.FindUtxo(address1, bi1, ti1, toi1); if (utxoNull2 != null) throw new Exception("test4_8"); utxom.SaveUFPTemp(); utxodb.Close(); if (!File.Exists(ufpdbPath)) throw new Exception("test4_9"); if (!File.Exists(ufptempdbPath)) throw new Exception("test4_10"); if (!File.Exists(utxodbPath)) throw new Exception("test4_11"); UtxoManager utxom2 = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); if (File.Exists(ufptempdbPath)) throw new Exception("test4_13"); utxodb.Open(); Utxo utxo2 = utxom.FindUtxo(address2, bi1, ti1, toi1); if (utxo2 == null) throw new Exception("test4_14"); if (utxo2.blockIndex != bi1) throw new Exception("test4_15"); if (utxo2.txIndex != ti1) throw new Exception("test4_16"); if (utxo2.txOutIndex != toi1) throw new Exception("test4_17"); if (utxo2.amount.rawAmount != c1.rawAmount) throw new Exception("test4_18"); utxodb.Close(); Console.WriteLine("test4_succeeded"); }
//BlockChainのテスト(分岐がない場合・採掘・順番通りに追加されなかった場合) public static void Test19() { 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[8]; BlockContext[] blkCons = new BlockContext[blks.Length]; for (int i = 0; i < blks.Length; i++) { blkCons[i] = bg.CreateNextValidBlock(); blks[i] = blkCons[i].block; Console.WriteLine("block" + i.ToString() + " created."); } Block[] blks2 = new Block[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]; 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; Console.WriteLine("block" + i.ToString() + " mined."); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } BlockChain.UpdateChainReturnType type = blockchain.UpdateChain(blks2[2]); if (type != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_1"); if (blockchain.blocksCurrent.value != 0) throw new Exception("test19_2"); for (int i = 0; i < blockchain.pendingBlocks.Length; i++) { if (i == 3) { if (blockchain.pendingBlocks[i] == null) throw new Exception("test19_3"); if (blockchain.pendingBlocks[i].Count != 1) throw new Exception("test19_4"); if (!blockchain.pendingBlocks[i].Keys.Contains(blks2[2].Id)) throw new Exception("test19_5"); } else { if (blockchain.pendingBlocks[i] != null) throw new Exception("test19_6"); } if (blockchain.rejectedBlocks[i] != null) throw new Exception("test19_7"); } BlockChain.UpdateChainReturnType type2 = blockchain.UpdateChain(blks2[1]); if (type2 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_8"); if (blockchain.blocksCurrent.value != 0) throw new Exception("test19_9"); for (int i = 0; i < blockchain.pendingBlocks.Length; i++) { if (i == 2) { if (blockchain.pendingBlocks[i] == null) throw new Exception("test19_10"); if (blockchain.pendingBlocks[i].Count != 1) throw new Exception("test19_11"); if (!blockchain.pendingBlocks[i].Keys.Contains(blks2[1].Id)) throw new Exception("test19_12"); } else if (i == 3) { if (blockchain.pendingBlocks[i] == null) throw new Exception("test19_13"); if (blockchain.pendingBlocks[i].Count != 1) throw new Exception("test19_14"); if (!blockchain.pendingBlocks[i].Keys.Contains(blks2[2].Id)) throw new Exception("test19_15"); } else { if (blockchain.pendingBlocks[i] != null) throw new Exception("test19_16"); } if (blockchain.rejectedBlocks[i] != null) throw new Exception("test19_17"); } BlockChain.UpdateChainReturnType type3 = blockchain.UpdateChain(blks2[0]); if (type3 != BlockChain.UpdateChainReturnType.updated) throw new Exception("test19_18"); if (blockchain.headBlockIndex != 2) throw new Exception("test19_19"); if (blockchain.blocksCurrent.value != 3) throw new Exception("test19_20"); for (int i = 0; i < blockchain.pendingBlocks.Length; i++) { if (i == 2 || i == 3) { if (blockchain.pendingBlocks[i] == null) throw new Exception("test19_21"); if (blockchain.pendingBlocks[i].Count != 0) throw new Exception("test19_22"); } else { if (blockchain.pendingBlocks[i] != null) throw new Exception("test19_23"); } if (blockchain.rejectedBlocks[i] != null) throw new Exception("test19_24"); } BlockChain.UpdateChainReturnType type4 = blockchain.UpdateChain(blks2[6]); BlockChain.UpdateChainReturnType type5 = blockchain.UpdateChain(blks2[7]); BlockChain.UpdateChainReturnType type6 = blockchain.UpdateChain(blks2[4]); BlockChain.UpdateChainReturnType type7 = blockchain.UpdateChain(blks2[5]); BlockChain.UpdateChainReturnType type8 = blockchain.UpdateChain(blks2[3]); if (type4 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_25"); if (type5 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_26"); if (type6 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_27"); if (type7 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test19_28"); if (type8 != BlockChain.UpdateChainReturnType.updated) throw new Exception("test19_29"); if (blockchain.headBlockIndex != 7) throw new Exception("test19_30"); utxodb.Open(); foreach (var address in blkCons[7].unspentTxOuts.Keys) foreach (var toc in blkCons[7].unspentTxOuts[address]) if (blockchain.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) == null) throw new Exception("test19_31"); foreach (var address in blkCons[7].spentTxOuts.Keys) foreach (var toc in blkCons[7].spentTxOuts[address]) if (blockchain.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) != null) throw new Exception("test19_32"); utxodb.Close(); Console.WriteLine("test19_succeeded"); }
//BlockChainのテスト(分岐がある場合・採掘・交互に追加していく場合) public static void Test21() { 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]; BlockContext[] blkCons = new BlockContext[blks.Length]; for (int i = 0; i < blks.Length; i++) { blkCons[i] = bg.CreateNextValidBlock(); blks[i] = blkCons[i].block; Console.WriteLine("block" + i.ToString() + " created."); } Block[] blks2 = new Block[blks.Length]; double cumulativeDiff1 = 0.0; 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]; cumulativeDiff1 += blks2[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_1 " + blks2[i].Difficulty.Diff.ToString() + " " + cumulativeDiff1.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; cumulativeDiff1 += blks2[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_1 mined. " + blks2[i].Difficulty.Diff.ToString() + " " + cumulativeDiff1.ToString()); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } Console.WriteLine(); Block[] blks3 = new Block[blks.Length]; double cumulativeDiff2 = 0.0; Func<long, TransactionalBlock> _indexToBlock2 = (index) => blks3[index] as TransactionalBlock; for (int i = 0; i < blks.Length; i++) { if (i == 0) { blks3[i] = blks[i]; cumulativeDiff2 += blks3[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_2 " + blks3[i].Difficulty.Diff.ToString() + " " + cumulativeDiff2.ToString()); continue; } 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; cumulativeDiff2 += blks3[i].Difficulty.Diff; Console.WriteLine("block" + i.ToString() + "_2 mined. " + blks3[i].Difficulty.Diff.ToString() + " " + cumulativeDiff2.ToString()); break; } int index = nonce.Length.RandomNum(); int value = 256.RandomNum(); nonce[index] = (byte)value; } } cumulativeDiff1 = 0.0; cumulativeDiff2 = 0.0; blockchain.UpdateChain(blks2[0]); for (int i = 1; i < blks.Length; i++) { cumulativeDiff1 += blks2[i].Difficulty.Diff; BlockChain.UpdateChainReturnType type1 = blockchain.UpdateChain(blks2[i]); if (cumulativeDiff1 > cumulativeDiff2) { if (type1 != BlockChain.UpdateChainReturnType.updated) throw new Exception("test21_1"); } else { if (type1 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test21_3"); } cumulativeDiff2 += blks3[i].Difficulty.Diff; BlockChain.UpdateChainReturnType type2 = blockchain.UpdateChain(blks3[i]); if (cumulativeDiff2 > cumulativeDiff1) { if (type2 != BlockChain.UpdateChainReturnType.updated) throw new Exception("test21_2"); } else { if (type2 != BlockChain.UpdateChainReturnType.pending) throw new Exception("test21_4"); } } 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("test21_5"); 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("test21_6"); utxodb.Close(); Console.WriteLine("test21_succeeded"); }
//UtxoDBのテスト public static void Test1() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); UtxoDB utxodb = new UtxoDB(basepath); string path = utxodb.GetPath(); if (File.Exists(path)) File.Delete(path); utxodb.Open(); byte[] emptyBytes = utxodb.GetUtxoData(0); if (emptyBytes.Length != 0) throw new Exception("test1_1"); byte[] utxoBytesIn1 = new byte[1024]; for (int i = 0; i < utxoBytesIn1.Length; i++) utxoBytesIn1[i] = (byte)256.RandomNum(); int overallLangth = utxoBytesIn1.Length + 4; long position1 = utxodb.AddUtxoData(utxoBytesIn1); if (position1 != 0) throw new Exception("test1_2"); long position2 = utxodb.AddUtxoData(utxoBytesIn1); if (position2 != overallLangth) throw new Exception("test1_3"); byte[] utxoBytesOut1 = utxodb.GetUtxoData(position1); if (!utxoBytesIn1.BytesEquals(utxoBytesOut1)) throw new Exception("test1_4"); byte[] utxoBytesOut2 = utxodb.GetUtxoData(position2); if (!utxoBytesIn1.BytesEquals(utxoBytesOut2)) throw new Exception("test1_5"); byte[] utxoBytesIn2 = new byte[utxoBytesIn1.Length]; for (int i = 0; i < utxoBytesIn2.Length; i++) utxoBytesIn2[i] = (byte)256.RandomNum(); utxodb.UpdateUtxoData(position1, utxoBytesIn2); byte[] utxoBytesOut3 = utxodb.GetUtxoData(position1); if (!utxoBytesIn2.BytesEquals(utxoBytesOut3)) throw new Exception("test1_6"); byte[] utxoBytesOut4 = utxodb.GetUtxoData(position2); if (!utxoBytesIn1.BytesEquals(utxoBytesOut4)) throw new Exception("test1_7"); utxodb.UpdateUtxoData(position2, utxoBytesIn2); byte[] utxoBytesOut5 = utxodb.GetUtxoData(position1); if (!utxoBytesIn2.BytesEquals(utxoBytesOut5)) throw new Exception("test1_8"); byte[] utxoBytesOut6 = utxodb.GetUtxoData(position2); if (!utxoBytesIn2.BytesEquals(utxoBytesOut6)) throw new Exception("test1_9"); byte[] emptyBytes2 = utxodb.GetUtxoData(overallLangth * 2); utxodb.Close(); Console.WriteLine("test1_succeeded"); }
//UtxoManagerのテスト5 public static void Test16() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 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); UtxoManager utxom = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); BlockGenerator bg = new BlockGenerator(); Block[] blks = new Block[100]; BlockContext[] blkCons = new BlockContext[blks.Length]; for (int i = 0; i < blks.Length; i++) { blkCons[i] = bg.CreateNextValidBlock(); blks[i] = blkCons[i].block; Console.WriteLine("block" + i.ToString() + " created."); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < blks.Length; i++) { utxodb.Open(); utxom.ApplyBlock(blks[i], blkCons[i].prevTxOutss); utxom.SaveUFPTemp(); utxodb.Close(); } stopwatch.Stop(); Console.WriteLine(string.Join(":", "test16_1", stopwatch.ElapsedMilliseconds.ToString() + "ms")); Console.WriteLine("test16_succeeded"); }
//UtxoManagerのテスト4 public static void Test15() { string basepath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 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); UtxoManager utxom = new UtxoManager(ufadb, ufpdb, ufptempdb, utxodb); BlockGenerator bg = new BlockGenerator(); Block[] blks = new Block[100]; BlockContext[] blkCons = new BlockContext[blks.Length]; for (int i = 0; i < blks.Length; i++) { blkCons[i] = bg.CreateNextValidBlock(); blks[i] = blkCons[i].block; Console.WriteLine("block" + i.ToString() + " created."); } for (int i = 0; i < blks.Length; i++) { utxodb.Open(); utxom.ApplyBlock(blks[i], blkCons[i].prevTxOutss); utxom.SaveUFPTemp(); utxodb.Close(); utxodb.Open(); foreach (var address in blkCons[i].unspentTxOuts.Keys) foreach (var toc in blkCons[i].unspentTxOuts[address]) if (utxom.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) == null) throw new Exception("test15_1"); foreach (var address in blkCons[i].spentTxOuts.Keys) foreach (var toc in blkCons[i].spentTxOuts[address]) if (utxom.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) != null) throw new Exception("test15_2"); utxodb.Close(); Console.WriteLine("block" + i.ToString() + " apply tested."); } for (int i = blks.Length - 1; i > 0; i--) { utxodb.Open(); utxom.RevertBlock(blks[i], blkCons[i].prevTxOutss); utxom.SaveUFPTemp(); utxodb.Close(); utxodb.Open(); foreach (var address in blkCons[i - 1].unspentTxOuts.Keys) foreach (var toc in blkCons[i - 1].unspentTxOuts[address]) if (utxom.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) == null) throw new Exception("test15_3"); foreach (var address in blkCons[i - 1].spentTxOuts.Keys) foreach (var toc in blkCons[i - 1].spentTxOuts[address]) if (utxom.FindUtxo(address, toc.bIndex, toc.txIndex, toc.txOutIndex) != null) throw new Exception("test15_4"); utxodb.Close(); Console.WriteLine("block" + i.ToString() + " revert tested."); } Console.WriteLine("test15_succeeded"); }
public void NewTransaction(IAccount iAccount, Sha256Ripemd160Hash address, CurrencyUnit amount, CurrencyUnit fee) { if (!isSystemStarted) { throw new InvalidOperationException("core_not_started"); } Account account = iAccount as Account; if (account == null) { throw new ArgumentException("iaccount_type"); } utxodb.Open(); List <Utxo> utxosList = blockChain.GetAllUtxos(account.Address.Hash); utxosList.Sort((a, b) => { if (a.blockIndex < b.blockIndex) { return(-1); } else if (a.blockIndex > b.blockIndex) { return(1); } if (a.txIndex < b.txIndex) { return(-1); } else if (a.txIndex > b.txIndex) { return(1); } if (a.txOutIndex < b.txOutIndex) { return(-1); } else if (a.txOutIndex > b.txOutIndex) { return(1); } return(0); }); Utxo[] utxos = utxosList.ToArray(); utxodb.Close(); List <TransactionInput> usedTxInList = new List <TransactionInput>(); foreach (var unconfirmedTh in transactionHistories.unconfirmedTransactionHistories.ToArray()) { for (int i = 0; i < unconfirmedTh.prevTxOuts.Length; i++) { if (unconfirmedTh.prevTxOuts[i].Address.Equals(account.Address.Hash)) { usedTxInList.Add(unconfirmedTh.transaction.TxInputs[i]); } } } usedTxInList.Sort((a, b) => { if (a.PrevTxBlockIndex < b.PrevTxBlockIndex) { return(-1); } else if (a.PrevTxBlockIndex > b.PrevTxBlockIndex) { return(1); } if (a.PrevTxIndex < b.PrevTxIndex) { return(-1); } else if (a.PrevTxIndex > b.PrevTxIndex) { return(1); } if (a.PrevTxOutputIndex < b.PrevTxOutputIndex) { return(-1); } else if (a.PrevTxOutputIndex > b.PrevTxOutputIndex) { return(1); } return(0); }); TransactionInput[] usedTxIns = usedTxInList.ToArray(); List <Utxo> unusedUtxosList = new List <Utxo>(); int position = -1; for (int i = 0; i < usedTxIns.Length; i++) { bool flag = false; while (position < utxos.Length) { position++; if (usedTxIns[i].PrevTxBlockIndex == utxos[position].blockIndex && usedTxIns[i].PrevTxIndex == utxos[position].txIndex && usedTxIns[i].PrevTxOutputIndex == utxos[position].txOutIndex) { flag = true; break; } else { unusedUtxosList.Add(utxos[position]); } } if (!flag) { throw new InvalidOperationException(); } } long rawFeeAndAmount = amount.rawAmount + fee.rawAmount; List <Utxo> useUtxosList = new List <Utxo>(); long rawFeeAndAmountAndChange = 0; bool flag2 = false; foreach (var utxo in unusedUtxosList) { useUtxosList.Add(utxo); if ((rawFeeAndAmountAndChange += utxo.amount.rawAmount) > rawFeeAndAmount) { flag2 = true; break; } } if (!flag2) { for (int i = position + 1; i < utxos.Length; i++) { useUtxosList.Add(utxos[i]); if ((rawFeeAndAmountAndChange += utxos[i].amount.rawAmount) > rawFeeAndAmount) { flag2 = true; break; } } } if (!flag2) { throw new InvalidOperationException(); } Utxo[] useUtxos = useUtxosList.ToArray(); TransactionInput[] txIns = new TransactionInput[useUtxos.Length]; for (int i = 0; i < txIns.Length; i++) { txIns[i] = new TransactionInput(); txIns[i].LoadVersion0(useUtxos[i].blockIndex, useUtxos[i].txIndex, useUtxos[i].txOutIndex, account.Ecdsa256KeyPair.pubKey); } long rawChange = rawFeeAndAmountAndChange - rawFeeAndAmount; TransactionOutput[] txOuts = new TransactionOutput[rawChange == 0 ? 1 : 2]; txOuts[0] = new TransactionOutput(); txOuts[0].LoadVersion0(address, amount); if (rawChange != 0) { txOuts[1] = new TransactionOutput(); txOuts[1].LoadVersion0(account.Address.Hash, new CurrencyUnit(rawChange)); } TransactionOutput[] prevTxOuts = new TransactionOutput[useUtxos.Length]; for (int i = 0; i < prevTxOuts.Length; i++) { prevTxOuts[i] = blockChain.GetMainBlock(txIns[i].PrevTxBlockIndex).Transactions[txIns[i].PrevTxIndex].TxOutputs[txIns[i].PrevTxOutputIndex]; } Ecdsa256PrivKey[] privKeys = new Ecdsa256PrivKey[useUtxos.Length]; for (int i = 0; i < privKeys.Length; i++) { privKeys[i] = account.Ecdsa256KeyPair.privKey; } TransferTransaction ttx = new TransferTransaction(); ttx.LoadVersion0(txIns, txOuts); ttx.Sign(prevTxOuts, privKeys); creaNodeTest.DiffuseNewTransaction(ttx); }
public void StartSystem() { if (isSystemStarted) { throw new InvalidOperationException("core_started"); } ahdb = new AccountHoldersDatabase(databaseBasepath); thdb = new TransactionHistoriesDatabase(databaseBasepath); bcadb = new BlockchainAccessDB(databaseBasepath); bmdb = new BlockManagerDB(databaseBasepath); bdb = new BlockDB(databaseBasepath); bfpdb = new BlockFilePointersDB(databaseBasepath); ufadb = new UtxoFileAccessDB(databaseBasepath); ufpdb = new UtxoFilePointersDB(databaseBasepath); ufptempdb = new UtxoFilePointersTempDB(databaseBasepath); utxodb = new UtxoDB(databaseBasepath); accountHolders = new AccountHolders(); accountHoldersFactory = new AccountHoldersFactory(); byte[] ahDataBytes = ahdb.GetData(); if (ahDataBytes.Length != 0) { accountHolders.FromBinary(ahDataBytes); } else { accountHolders.LoadVersion0(); } transactionHistories = thdb.GetData().Pipe((data) => data.Length == 0 ? new TransactionHistories() : SHAREDDATA.FromBinary <TransactionHistories>(data)); transactionHistories.UnconfirmedTransactionAdded += (sender, e) => { foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { foreach (var prevTxOut in e.senders) { if (account.Address.Equals(prevTxOut.Address)) { account.accountStatus.unconfirmedAmount = new CurrencyUnit(account.accountStatus.unconfirmedAmount.rawAmount + prevTxOut.Amount.rawAmount); } } } } }; transactionHistories.UnconfirmedTransactionRemoved += (sender, e) => { foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { foreach (var prevTxOut in e.receivers) { if (account.Address.Equals(prevTxOut.Address)) { account.accountStatus.unconfirmedAmount = new CurrencyUnit(account.accountStatus.unconfirmedAmount.rawAmount - prevTxOut.Amount.rawAmount); } } } } }; usableBalanceCache = new CachedData <CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { rawAmount += account.accountStatus.usableAmount.rawAmount; } } return(new CurrencyUnit(rawAmount)); }); unusableBalanceCache = new CachedData <CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { rawAmount += account.accountStatus.unusableAmount.rawAmount; } } return(new CurrencyUnit(rawAmount)); }); unconfirmedBalanceCache = new CachedData <CurrencyUnit>(() => { long rawAmount = 0; foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { rawAmount += account.accountStatus.unconfirmedAmount.rawAmount; } } return(new CurrencyUnit(rawAmount)); }); usableBalanceWithUnconfirmedCache = new CachedData <CurrencyUnit>(() => new CurrencyUnit(usableBalanceCache.Data.rawAmount - unconfirmedBalanceCache.Data.rawAmount)); unusableBalanceWithUnconformedCache = new CachedData <CurrencyUnit>(() => new CurrencyUnit(unusableBalanceCache.Data.rawAmount + unconfirmedBalanceCache.Data.rawAmount)); blockChain = new BlockChain(bcadb, bmdb, bdb, bfpdb, ufadb, ufpdb, ufptempdb, utxodb); blockChain.LoadTransactionHistories(transactionHistories); //<未改良>暫定? if (blockChain.headBlockIndex == -1) { blockChain.UpdateChain(new GenesisBlock()); this.RaiseNotification("genesis_block_generated", 5); } Dictionary <Account, EventHandler <Tuple <CurrencyUnit, CurrencyUnit> > > changeAmountDict = new Dictionary <Account, EventHandler <Tuple <CurrencyUnit, CurrencyUnit> > >(); Action <bool> _UpdateBalance = (isOnlyUnconfirmed) => { if (!isOnlyUnconfirmed) { usableBalanceCache.IsModified = true; unusableBalanceCache.IsModified = true; } unconfirmedBalanceCache.IsModified = true; usableBalanceWithUnconfirmedCache.IsModified = true; unusableBalanceWithUnconformedCache.IsModified = true; BalanceUpdated(this, EventArgs.Empty); }; Action <Account, bool> _AddAddressEvent = (account, isUpdatebalance) => { EventHandler <Tuple <CurrencyUnit, CurrencyUnit> > eh = (sender, e) => { account.accountStatus.usableAmount = e.Item1; account.accountStatus.unusableAmount = e.Item2; }; changeAmountDict.Add(account, eh); AddressEvent addressEvent = new AddressEvent(account.Address.Hash); addressEvent.BalanceUpdated += eh; blockChain.AddAddressEvent(addressEvent); long rawAmount = 0; foreach (var unconfirmedTh in transactionHistories.unconfirmedTransactionHistories.ToArray()) { foreach (var prevTxOut in unconfirmedTh.senders) { if (prevTxOut.Address.Equals(account.Address)) { rawAmount += prevTxOut.Amount.rawAmount; } } } account.accountStatus.unconfirmedAmount = new CurrencyUnit(rawAmount); if (isUpdatebalance) { _UpdateBalance(false); } }; EventHandler <Account> _AccountAdded = (sender, e) => { utxodb.Open(); _AddAddressEvent(e, true); utxodb.Close(); }; EventHandler <Account> _AccountRemoved = (sender, e) => { EventHandler <Tuple <CurrencyUnit, CurrencyUnit> > eh = changeAmountDict[e]; changeAmountDict.Remove(e); AddressEvent addressEvent = blockChain.RemoveAddressEvent(e.Address.Hash); addressEvent.BalanceUpdated -= eh; _UpdateBalance(false); }; utxodb.Open(); foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { _AddAddressEvent(account, false); } accountHolder.AccountAdded += _AccountAdded; accountHolder.AccountRemoved += _AccountRemoved; } utxodb.Close(); accountHolders.AccountHolderAdded += (sender, e) => { e.AccountAdded += _AccountAdded; e.AccountRemoved += _AccountRemoved; }; accountHolders.AccountHolderRemoved += (semder, e) => { e.AccountAdded -= _AccountAdded; e.AccountRemoved -= _AccountRemoved; }; blockChain.BalanceUpdated += (sender, e) => _UpdateBalance(false); _UpdateBalance(false); unconfirmedTtxs = new Dictionary <TransferTransaction, TransactionOutput[]>(); mining = new Mining(); mining.FoundNonce += (sender, e) => creaNodeTest.DiffuseNewBlock(e); blockChain.Updated += (sender, e) => { foreach (var block in e) { foreach (var tx in block.Transactions) { foreach (var txIn in tx.TxInputs) { TransferTransaction contradiction = null; foreach (var unconfirmedTx in unconfirmedTtxs) { foreach (var unconfirmedTxIn in unconfirmedTx.Key.TxInputs) { if (txIn.PrevTxBlockIndex == unconfirmedTxIn.PrevTxBlockIndex && txIn.PrevTxIndex == unconfirmedTxIn.PrevTxIndex && txIn.PrevTxOutputIndex == unconfirmedTxIn.PrevTxOutputIndex) { contradiction = unconfirmedTx.Key; break; } } if (contradiction != null) { break; } } if (contradiction != null) { unconfirmedTtxs.Remove(contradiction); } } } } Mine(); }; Mine(); //creaNodeTest = new CreaNode(ps.NodePort, creaVersion, appnameWithVersion, new FirstNodeInfosDatabase(p2pDirectory)); creaNodeTest = new CreaNodeTest(blockChain, ps.NodePort, creaVersion, appnameWithVersion); creaNodeTest.ConnectionKeeped += (sender, e) => creaNodeTest.SyncronizeBlockchain(); creaNodeTest.ReceivedNewTransaction += (sender, e) => { TransferTransaction ttx = e as TransferTransaction; if (ttx == null) { return; } TransactionOutput[] prevTxOuts = new TransactionOutput[ttx.TxInputs.Length]; for (int i = 0; i < prevTxOuts.Length; i++) { prevTxOuts[i] = blockChain.GetMainBlock(ttx.TxInputs[i].PrevTxBlockIndex).Transactions[ttx.TxInputs[i].PrevTxIndex].TxOutputs[ttx.TxInputs[i].PrevTxOutputIndex]; } if (!ttx.Verify(prevTxOuts)) { return; } List <TransactionOutput> senders = new List <TransactionOutput>(); List <TransactionOutput> receivers = new List <TransactionOutput>(); long sentAmount = 0; long receivedAmount = 0; for (int i = 0; i < ttx.txInputs.Length; i++) { foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { if (prevTxOuts[i].Address.Equals(account.Address.Hash)) { sentAmount += prevTxOuts[i].Amount.rawAmount; senders.Add(prevTxOuts[i]); } } } } for (int i = 0; i < ttx.TxOutputs.Length; i++) { foreach (var accountHolder in accountHolders.AllAccountHolders) { foreach (var account in accountHolder.Accounts) { if (ttx.TxOutputs[i].Address.Equals(account.Address.Hash)) { receivedAmount += ttx.TxOutputs[i].Amount.rawAmount; receivers.Add(ttx.TxOutputs[i]); } } } } if (senders.Count > 0 || receivers.Count > 0) { TransactionHistoryType type = TransactionHistoryType.transfered; if (receivers.Count < ttx.TxOutputs.Length) { type = TransactionHistoryType.sent; } else if (senders.Count < ttx.TxInputs.Length) { type = TransactionHistoryType.received; } transactionHistories.AddTransactionHistory(new TransactionHistory(true, false, type, DateTime.MinValue, 0, ttx.Id, senders.ToArray(), receivers.ToArray(), ttx, prevTxOuts, new CurrencyUnit(sentAmount), new CurrencyUnit(receivedAmount - sentAmount))); } utxodb.Open(); for (int i = 0; i < ttx.TxInputs.Length; i++) { if (blockChain.FindUtxo(prevTxOuts[i].Address, ttx.TxInputs[i].PrevTxBlockIndex, ttx.TxInputs[i].PrevTxIndex, ttx.TxInputs[i].PrevTxOutputIndex) == null) { return; } } utxodb.Close(); foreach (var txIn in ttx.TxInputs) { foreach (var unconfirmedTtx in unconfirmedTtxs) { foreach (var unconfirmedTxIn in unconfirmedTtx.Key.TxInputs) { if (txIn.PrevTxBlockIndex == unconfirmedTxIn.PrevTxBlockIndex && txIn.PrevTxIndex == unconfirmedTxIn.PrevTxIndex && txIn.PrevTxOutputIndex == unconfirmedTxIn.PrevTxOutputIndex) { return; } } } } unconfirmedTtxs.Add(ttx, prevTxOuts); Mine(); }; creaNodeTest.ReceivedNewBlock += (sender, e) => blockChain.UpdateChain(e).Pipe((ret) => this.RaiseResult("blockchain_update", 5, ret.ToString())); //creaNodeTest.Start(); isSystemStarted = true; }