public void ProcessNextBlock(MiningJobRequestModel miningJobRM) { bool isFound = this.blockCandidates.TryGetValue(miningJobRM.MinerAddress, out BlockCandidate foundBlockCandidate); if (!isFound) { throw new Exception("No miner job associated with this miner address."); } if (foundBlockCandidate.BlockDataHash != miningJobRM.BlockDataHash) { throw new Exception("Mining job block data hash is different than the hash of the prepared block candidate."); } if (this.blocks.Any() && foundBlockCandidate.Index <= this.blocks.Last().Index) { this.SyncNode(foundBlockCandidate.Index); throw new Exception($"Sorry but a block with index {foundBlockCandidate.Index} was already mined."); } if (!this.IsFoundBlockHashValid(miningJobRM)) { throw new Exception("Found block hash is invalid"); } //TODO: During synchronization with other nodes, a check for valid hash for incoming blocks must be done as well. Block newBlock = this.CreateNewBlock(miningJobRM, foundBlockCandidate); this.blocks.Add(newBlock); this.transactionService.ClearAllAddedToBlockPendingTransactions(newBlock.ConfirmedTransactions); this.blockCandidates.Clear(); }
private bool IsFoundBlockHashValid(MiningJobRequestModel miningJobRM) { // Can be added to utils if needed elsewhere string timestampIso8601 = miningJobRM.Timestamp.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); string combinedInput = $"{miningJobRM.BlockDataHash}{timestampIso8601}{miningJobRM.Nonce}"; string calculatedHash = Crypto.CalculateSHA256ToString(combinedInput); return(miningJobRM.MinedBlockHash == calculatedHash); }
public IActionResult SubmitMinedJob([FromBody] MiningJobRequestModel miningJobRM) { try { this.blockService.ProcessNextBlock(miningJobRM); return(Ok("New block sucessfully added to the chain.")); } catch (Exception ex) { return(BadRequest($"Error: {ex}")); } }
private Block CreateNewBlock(MiningJobRequestModel miningJobRM, BlockCandidate blockCandidate) { Block newBlock = new Block() { Index = blockCandidate.Index, ConfirmedTransactions = blockCandidate.ConfirmedTransactions, Difficulty = blockCandidate.Difficulty, PreviousBlockHash = blockCandidate.PreviousBlockHash, MinedBy = blockCandidate.MinedBy, BlockDataHash = blockCandidate.BlockDataHash, Nonce = miningJobRM.Nonce, DateCreated = miningJobRM.Timestamp, BlockHash = miningJobRM.MinedBlockHash }; return(newBlock); }