4 using System.Collections.Generic;
7 using SQLite.Net.Attributes;
8 using SQLite.Net.Interop;
9 using SQLite.Net.Platform.Generic;
16 PROOF_OF_WORK_MODIFIER,
18 PROOF_OF_STAKE_MODIFIER
21 [Table("BlockStorage")]
25 /// Item ID in the database
27 [PrimaryKey, AutoIncrement]
28 public int ItemID { get; set; }
31 /// PBKDF2+Salsa20 of block hash
34 public byte[] Hash { get; set; }
39 public byte[] NextHash { get; set; }
42 /// Serialized representation of block header
44 public byte[] BlockHeader { get; set; }
49 public BlockType BlockTypeFlag { get; set; }
52 /// Block position in file
54 public long nBlockPos { get; set; }
57 /// Block size in bytes
59 public int nBlockSize { get; set; }
65 public class CChainNode
75 public CBlockHeader blockHeader;
80 public BlockType blockType;
85 public ScryptHash256 hashNextBlock;
88 public class CBlockStore : IDisposable
90 private bool disposed = false;
91 private object LockObj = new object();
92 private SQLiteConnection dbConn = null;
94 private Dictionary<ScryptHash256, CChainNode> blockIndex = new Dictionary<ScryptHash256, CChainNode>();
97 /// Init the block storage manager.
99 /// <param name="IndexDB">Path to index database</param>
100 /// <param name="BlockFile">Path to block file</param>
101 public CBlockStore(string IndexDB = "blockstore.dat", string BlockFile = "blk0001.dat")
103 bool firstInit = !File.Exists(IndexDB);
104 dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), IndexDB);
110 dbConn.CreateTable<CBlockStoreItem>(CreateFlags.AutoIncPK);
115 public bool ParseBlockFile(string BlockFile = "bootstrap.dat")
117 // TODO: Rewrite completely.
119 var QueryGet = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] order by [ItemId] desc limit 1");
123 if (QueryGet.Count() == 1)
125 var res = QueryGet.First();
126 nOffset = res.nBlockPos + res.nBlockSize;
129 var fileReader = new BinaryReader(File.OpenRead(BlockFile));
130 var fileStream = fileReader.BaseStream;
132 var buffer = new byte[1000000]; // Max block size is 1Mb
133 var intBuffer = new byte[4];
135 fileStream.Seek(nOffset, SeekOrigin.Begin); // Seek to previous offset + previous block length
137 dbConn.BeginTransaction();
139 while (fileStream.Read(buffer, 0, 4) == 4) // Read magic number
141 var nMagic = BitConverter.ToUInt32(buffer, 0);
142 if (nMagic != 0xe5e9e8e4)
144 Console.WriteLine("Incorrect magic number.");
148 var nBytesRead = fileStream.Read(buffer, 0, 4);
151 Console.WriteLine("BLKSZ EOF");
155 var nBlockSize = BitConverter.ToInt32(buffer, 0);
157 nOffset = fileStream.Position;
159 nBytesRead = fileStream.Read(buffer, 0, nBlockSize);
161 if (nBytesRead == 0 || nBytesRead != nBlockSize)
163 Console.WriteLine("BLK EOF");
167 var block = new CBlock(buffer);
169 if (nOffset % 1000 == 0) // Commit on each 1000th block
171 Console.WriteLine("Offset={0}, Hash: {1}", nOffset, block.header.Hash.ToString());
173 dbConn.BeginTransaction();
176 var result = dbConn.Insert(new CBlockStoreItem()
178 Hash = block.header.Hash,
179 BlockHeader = block.header,
180 BlockTypeFlag = block.IsProofOfStake ? BlockType.PROOF_OF_STAKE : BlockType.PROOF_OF_WORK,
182 nBlockSize = nBlockSize
188 fileReader.Dispose();
198 public void Dispose()
201 GC.SuppressFinalize(this);
204 protected virtual void Dispose(bool disposing)
210 // Free other state (managed objects).