From 5ca5da3cb81d1d5b7be655cf0d139f9cab7211c4 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Fri, 28 Aug 2015 03:08:54 +0300 Subject: [PATCH] Initial implementation of CBlockStore. --- Novacoin/CBlockStore.cs | 176 ++++++++++++++++++++++++++++++++++++++++++++++ Novacoin/Hash.cs | 1 - Novacoin/Novacoin.csproj | 1 + NovacoinTest/Program.cs | 6 ++ 4 files changed, 183 insertions(+), 1 deletions(-) create mode 100644 Novacoin/CBlockStore.cs diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs new file mode 100644 index 0000000..7f1f9ae --- /dev/null +++ b/Novacoin/CBlockStore.cs @@ -0,0 +1,176 @@ +using System; +using System.IO; +using System.Linq; + +using SQLite.Net; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; +using SQLite.Net.Platform.Generic; + +namespace Novacoin +{ + [Table("BlockStorage")] + class CBlockStoreItem + { + /// + /// Item ID in the database + /// + [PrimaryKey, AutoIncrement] + public int ItemID { get; set; } + + /// + /// PBKDF2+Salsa20 of block hash + /// + [Unique] + public byte[] ScryptHash { get; set; } + + /// + /// Serialized representation of block header + /// + public byte[] BlockHeader { get; set; } + + /// + /// Block position in file + /// + public long nBlockPos { get; set; } + + /// + /// Block size in bytes + /// + public int nBlockSize { get; set; } + } + + public class CBlockStore : IDisposable + { + private bool disposed = false; + private object LockObj = new object(); + private SQLiteConnection dbConn = null; + + /// + /// Init the block storage manager. + /// + /// Path to index database + /// Path to block file + public CBlockStore(string IndexDB = "blockstore.dat", string BlockFile = "blk0001.dat") + { + bool firstInit = !File.Exists(IndexDB); + dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), IndexDB); + + if (firstInit) + { + lock (LockObj) + { + dbConn.CreateTable(CreateFlags.AutoIncPK); + } + } + } + + public bool ParseBlockFile(string BlockFile = "bootstrap.dat") + { + // TODO: Rewrite completely. + + var QueryGet = dbConn.Query("select * from [BlockStorage] order by [ItemId] desc limit 1"); + + var nOffset = 0L; + + if (QueryGet.Count() == 1) + { + var res = QueryGet.First(); + nOffset = res.nBlockPos + res.nBlockSize; + } + + var fileReader = new BinaryReader(File.OpenRead(BlockFile)); + var fileStream = fileReader.BaseStream; + + var buffer = new byte[1000000]; // Max block size is 1Mb + var intBuffer = new byte[4]; + + fileStream.Seek(nOffset, SeekOrigin.Begin); // Seek to previous offset + previous block length + + dbConn.BeginTransaction(); + + while (fileStream.Read(buffer, 0, 4) == 4) // Read magic number + { + var nMagic = BitConverter.ToUInt32(buffer, 0); + if (nMagic != 0xe5e9e8e4) + { + Console.WriteLine("Incorrect magic number."); + break; + } + + var nBytesRead = fileStream.Read(buffer, 0, 4); + if (nBytesRead != 4) + { + Console.WriteLine("BLKSZ EOF"); + break; + } + + var nBlockSize = BitConverter.ToInt32(buffer, 0); + + nOffset = fileStream.Position; + + nBytesRead = fileStream.Read(buffer, 0, nBlockSize); + + if (nBytesRead == 0 || nBytesRead != nBlockSize) + { + Console.WriteLine("BLK EOF"); + break; + } + + var block = new CBlock(buffer); + + if (nOffset % 1000 == 0) // Commit on each 1000th block + { + Console.WriteLine("Offset={0}, Hash: {1}", nOffset, block.header.Hash.ToString()); + dbConn.Commit(); + dbConn.BeginTransaction(); + } + + var result = dbConn.Insert(new CBlockStoreItem() + { + ScryptHash = block.header.Hash, + BlockHeader = block.header, + nBlockPos = nOffset, + nBlockSize = nBlockSize + }); + } + + dbConn.Commit(); + + fileReader.Dispose(); + + return true; + } + + ~CBlockStore() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + // Free other state (managed objects). + } + + if (dbConn != null) + { + dbConn.Close(); + dbConn = null; + } + + disposed = true; + } + } + + } +} diff --git a/Novacoin/Hash.cs b/Novacoin/Hash.cs index 0a988df..05c4567 100644 --- a/Novacoin/Hash.cs +++ b/Novacoin/Hash.cs @@ -17,7 +17,6 @@ */ using System; -using System.Diagnostics.Contracts; using System.Linq; namespace Novacoin diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index ab3512e..38dc701 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -93,6 +93,7 @@ + diff --git a/NovacoinTest/Program.cs b/NovacoinTest/Program.cs index f9b5128..7a2c23f 100644 --- a/NovacoinTest/Program.cs +++ b/NovacoinTest/Program.cs @@ -270,6 +270,12 @@ namespace NovacoinTest keyStore.ResetPool(); Console.WriteLine("Done in {0} ms.", watch.ElapsedMilliseconds); + /* + Console.WriteLine("Reading the block file..."); + var bs = new CBlockStore(); + bs.ParseBlockFile(); + */ + Console.ReadLine(); } } -- 1.7.1