Пример #1
0
        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();
        }
Пример #2
0
        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();
        }
Пример #3
0
        public void Load()
        {
            data.Clear();

            string[] lines = File.ReadAllLines(IndexFile);
            foreach (string line in lines)
            {
                data.Add(LedgerIndex.FromString(line));
            }
            isLoaded = true;
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        public int GetNextBlockId()
        {
            LedgerIndex mostrecent = data.OrderByDescending(u => u.BlockId).FirstOrDefault();

            return((mostrecent == null ? 0 : mostrecent.BlockId) + 1);
        }