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); } }
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); } }
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}"); }
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"); } }