public void Initialize() { if (false == Directory.Exists(LedgerPath)) { Directory.CreateDirectory(LedgerPath); } Indexes.Initialize(); PhysicalBlock block = new PhysicalBlock(); block.Id = Indexes.GetNextBlockId(); block.LedgerId = Id; block.TransactionData = System.Text.Encoding.ASCII.GetBytes("ledger initialized"); block.SignBlock = new SignBlock(); block.ComputeHash(); LedgerIndex index = Indexes.Add(block.Hash, block.TimeStamp); if (block.Id != index.BlockID) { throw new LedgerException(Name, $"ID mismatch {block.Id}/{index.BlockID}"); } // TODO: these next two steps are technically a transaction, need to determine what happens when // one step fails. System.Console.WriteLine($"saving indexes to {LedgerIndexFileName}"); Indexes.Save(); }
public void Initialize() { if (false == Directory.Exists(LedgerPath)) { Directory.CreateDirectory(LedgerPath); } Indexes.Initialize(); PhysicalBlock block = new PhysicalBlock { Id = Indexes.GetNextBlockId(), LedgerId = Id, TransactionData = System.Text.Encoding.ASCII.GetBytes("ledger initialized"), SignBlock = new SignBlock() }; block.ComputeHash(); LedgerIndex index = Indexes.Add(block.Hash, block.TimeStamp); if (block.Id != index.BlockId) { throw new LedgerException(Name, $"ID mismatch {block.Id}/{index.BlockId}"); } // TODO: these next two steps are technically a transaction, need to determine what happens when // one step fails. _logger.LogInformation($"saving indexes to {LedgerIndexFileName}"); // step 1 save the block // TODO: need rollback if Indexes.Save() fails Writer.SaveBlock(block); // step 2 save the index Indexes.Save(); }
public void Load() { data.Clear(); string[] lines = File.ReadAllLines(IndexFile); foreach (string line in lines) { data.Add(LedgerIndex.FromString(line)); } isLoaded = true; }
public void Validate() { State = LedgerState.StartingUp; if (false == File.Exists(LedgerIndexFileName)) { throw new LedgerNotFoundException(LedgerIndexFileName); } try { Indexes.Load(); // Validation Rule #1: the number of records in the index file should match // the number of blocks saved on disk if (Reader.CountBlocks() != Indexes.Count()) { throw new LedgerNotValidException($"{Reader.CountBlocks()} != {Indexes.Count()}"); } // Validation Rule #2: the boot record (which is the very first record) // should be valid PhysicalBlock rootBlock = Reader.GetLedgerPhysicalBlock(1, (data) => { return(PhysicalBlock.FromString(data)); }) as PhysicalBlock; LedgerIndex rootIndex = Indexes.GetIndex(1); if (rootBlock.ComputeHash() != rootIndex.Hash) { throw new LedgerNotValidException($"block {rootBlock.Id}"); } // Validation Rule #3: the last record should validate // Validation Rule #4: verify a few other blocks // TODO: validate some of the remaining blocks. // TODO: have an option that requires all blocks to be validated State = LedgerState.Available; } catch (Exception e) { State = LedgerState.Nonfunctional; throw new LedgerException(Name, e); } }
public static LedgerIndex FromString(string data) { string[] elements = data.Split(":"); LedgerIndex index = new LedgerIndex(); index.BlockId = Convert.ToInt32(elements[0]); index.Hash = elements[1]; DateTime expectedDate; if (false == DateTime.TryParseExact(elements[2], Constants.DateTimeFormat, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out expectedDate)) { throw new LedgerNotValidException($"index is not valid"); } index.Created = expectedDate; return(index); }
public LedgerIndex Add(string hash, DateTime created) { if (false == isLoaded) { throw new LedgerException(LedgerName, "Attempted to add index before loading"); } LedgerIndex index = new LedgerIndex(); index.BlockId = GetNextBlockId(); index.Created = created; index.Hash = hash; data.Add(index); return(index); }
public int GetNextBlockId() { LedgerIndex mostrecent = data.OrderByDescending(u => u.BlockId).FirstOrDefault(); return((mostrecent == null ? 0 : mostrecent.BlockId) + 1); }