예제 #1
0
        public void AttachBroadcastedBlock(BlockSyncApiModel block, string nodeAddress)
        {
            bool isPastBlock = block.Index <= LastBlock.Index;

            if (isPastBlock)
            {
                return;
            }

            Block minedBlock = Block.ReCreateBlock(block);

            ValidateBlockHash(minedBlock, minedBlock.Nonce, minedBlock.BlockHash);

            // replace blockchain if another blockain is longer
            int nodeDifference = minedBlock.Index - BlockChain.Count;

            if (nodeDifference >= 6)
            {
                int          startIndex   = minedBlock.Index - nodeDifference;
                List <Block> forkedBlocks = NodeSynchornizator.GetBlocksForSync(nodeAddress);

                foreach (var bl in forkedBlocks)
                {
                    RevalidateBlock(bl);
                    BlockChain.AddOrUpdate(bl.Index, bl, (index, curBlock) => { return(bl); });
                }

                List <string> blockTxs = forkedBlocks.SelectMany(b => b.Transactions).Select(t => t.TransactionHash).ToList();

                PendingTransactions = new ConcurrentBag <Transaction>(PendingTransactions.
                                                                      Where(t => !blockTxs.Contains(t.TransactionHash)));
            }
            else
            {
                bool isFutureBlock = LastBlock.BlockHash != minedBlock.PreviousBlockHash;
                if (isFutureBlock)
                {
                    return;
                }

                RevalidateBlock(minedBlock);

                // remove mined transactions from pending transactions
                List <string> minedTxIds = minedBlock.Transactions.Select(t => t.TransactionHash).ToList();
                PendingTransactions = new ConcurrentBag <Transaction>(PendingTransactions.Where(t => !minedTxIds.Contains(t.TransactionHash)).ToList());

                BlockChain.TryAdd(minedBlock.Index, minedBlock);
            }
        }
예제 #2
0
        public void NonceFound(string minerAddress, int nonce, string hash)
        {
            lock (_nonceFoundLock)
            {
                Block block = BlocksInProgress[minerAddress];
                if (block == null)
                {
                    return;
                }

                if (!CryptoUtil.IsAddressValid(minerAddress))
                {
                    throw new AddressNotValidException($"Miner address '{minerAddress}' is not valid");
                }

                if (block.Index != BlockChain.Last().Key + 1)
                {
                    throw new NonceUselessException();
                }

                ValidateBlockHash(block, nonce, hash);
                block.BlockMined(nonce, hash, minerAddress);

                int minedTransactionsCount = block.Transactions.Count;

                List <Transaction> notMinedTxs = new List <Transaction>();
                var allTx = PendingTransactions.ToList();

                for (int i = minedTransactionsCount; i < allTx.Count; i++)
                {
                    notMinedTxs.Add(allTx[i]);
                }

                PendingTransactions = new ConcurrentBag <Transaction>(notMinedTxs);

                BlockChain.TryAdd(block.Index, block);
                BlocksInProgress[minerAddress] = null;
                NodeSynchornizator.BroadcastBlock(block);
            }
        }
예제 #3
0
        public void Init()
        {
            Console.WriteLine("Creating genesis block...");

            Block genesisBlock = Block.CreateGenesisBlock(Difficulty);

            BlockChain.TryAdd(0, genesisBlock);

            Started = DateTime.Now;

            Console.WriteLine("Node initializing...");

            var missedBlocks = NodeSynchornizator.SyncBlocks();

            foreach (var b in missedBlocks)
            {
                RevalidateBlock(b);
                BlockChain.TryAdd(b.Index, b);
            }

            Console.WriteLine($"Node initialized. Synced finished.Blocks count {BlockChain.Count}");
        }
예제 #4
0
        public void AddTransaction(Transaction transaction, bool broadcast = true)
        {
            ValidateTransaction(transaction);

            ulong senderBalance = CalculateBalance(transaction.FromAddress, true, true);

            if (senderBalance >= transaction.Fee)
            {
                transaction.TranserSuccessfull = senderBalance >= transaction.Amount + transaction.Fee;
                PendingTransactions.Add(transaction);
                if (broadcast)
                {
                    NodeSynchornizator.BroadcastTransaction(transaction);
                }
                if (!transaction.TranserSuccessfull)
                {
                    throw new BalanceNotEnoughException($"Address '{transaction.FromAddress}' trying to send {transaction.Amount.GetFormattedTokens()}, but balance is {senderBalance.GetFormattedTokens()}. Transaction fee will be deducted !!!");
                }
            }
            else
            {
                throw new BalanceNotEnoughException($"Address '{transaction.FromAddress}' does not have enough money even for paying the fee");
            }
        }