private static HeadCandidate SelectHead(Database db, BlocksTemp blocks, HeadSelector selector) { var heads = blocks.Blocks.Where(block => !block.HasChildren).ToList(); if (heads.Count == 0) { throw new Exception("Invalid blockchain. Circular topologies are invalid."); } if (heads.Count == 1) { return(heads[0]); } var hash = db.BlockchainHead; if (hash == null) { if (selector == null) { throw new Exception("Can't read blockchain head from DB."); } hash = selector(heads).Hash; } HeadCandidate ret; if (!blocks.BlockMap.TryGetValue(hash, out ret)) { throw new Exception( $"DB states that the blockchain head is {hash}, but no such block exists in the DB."); } return(ret); }
private static BlocksTemp BuildBlocks(Database db) { var ret = new BlocksTemp(); foreach (var block in db.GetAllBlocks()) { var candidate = new HeadCandidate { DbId = block.Id, Hash = block.Hash, PreviousHash = block.PreviousHash }; ret.Blocks.Add(candidate); ret.BlockMap[block.Hash] = candidate; } foreach (var block in ret.Blocks) { HeadCandidate previous; if (!ret.BlockMap.TryGetValue(block.PreviousHash, out previous)) { continue; } block.Previous = previous; block.Previous.HasChildren = true; } return(ret); }