Example #1
0
File: Core.cs Project: pizyumi/CREA
        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;
        }
Example #2
0
        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;
        }