//2014/12/17追加 BlockChainの試験(口座残高) public static void Test25() { 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]; 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; } } if (blockchain.registeredAddresses.Count != 0) throw new Exception("test25_1"); AddressEvent ae = new AddressEvent(new Sha256Ripemd160Hash()); blockchain.AddAddressEvent(ae); if (blockchain.registeredAddresses.Count != 1) throw new Exception("test25_2"); if (!blockchain.registeredAddresses.Keys.Contains(ae)) throw new Exception("test25_3"); if (blockchain.registeredAddresses[ae].Count != 0) throw new Exception("test25_4"); AddressEvent aeret = blockchain.RemoveAddressEvent(new Sha256Ripemd160Hash()); if (ae != aeret) throw new Exception("test25_5"); if (blockchain.registeredAddresses.Count != 0) throw new Exception("test25_6"); blockchain.AddAddressEvent(ae); Dictionary<Sha256Ripemd160Hash, Tuple<CurrencyUnit, CurrencyUnit>> balances = new Dictionary<Sha256Ripemd160Hash, Tuple<CurrencyUnit, CurrencyUnit>>(); foreach (var address in bg.addresses) { AddressEvent addressEvent = new AddressEvent(address); addressEvent.BalanceUpdated += (sender, e) => { balances[addressEvent.address] = e; }; blockchain.AddAddressEvent(addressEvent); } int counter = 0; blockchain.BalanceUpdated += (sender, e) => { counter++; }; for (int i = 0; i < blks.Length; i++) { blockchain.UpdateChain(blks2[i]); if (counter != i) throw new Exception("test25_7"); foreach (var address in bg.addresses) { long usable = 0; long unusable = 0; foreach (var txoutcon in blkCons[i].unspentTxOuts[address]) if (txoutcon.bIndex + 6 > i) unusable += txoutcon.amount.rawAmount; else usable += txoutcon.amount.rawAmount; if (balances[address].Item1.rawAmount != usable) throw new Exception("test25_2"); if (balances[address].Item2.rawAmount != unusable) throw new Exception("test25_2"); } } Console.WriteLine("test25_succeeded"); }
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; }
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; }