From 36ca53c3907c141aa7fed85bf1d43774f243d1da Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 27 Aug 2015 15:55:51 +0300 Subject: [PATCH] Implement CKeyPool functionality as a part of CKeyStore, remove CKeyPool. --- Novacoin/CKeyID.cs | 5 + Novacoin/CKeyPool.cs | 48 ------------ Novacoin/CKeyStore.cs | 189 ++++++++++++++++++++++++++++++++++++++------- Novacoin/Novacoin.csproj | 1 - 4 files changed, 164 insertions(+), 79 deletions(-) delete mode 100644 Novacoin/CKeyPool.cs diff --git a/Novacoin/CKeyID.cs b/Novacoin/CKeyID.cs index c1050b9..12b2b97 100644 --- a/Novacoin/CKeyID.cs +++ b/Novacoin/CKeyID.cs @@ -25,6 +25,11 @@ namespace Novacoin _hashBytes = pubKeyHash.hashBytes; } + internal CKeyID(byte[] hashBytes) + { + _hashBytes = hashBytes; + } + public override string ToString() { return (new CNovacoinAddress(this)).ToString(); diff --git a/Novacoin/CKeyPool.cs b/Novacoin/CKeyPool.cs deleted file mode 100644 index a90a1f6..0000000 --- a/Novacoin/CKeyPool.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Novacoin -{ - public class CKeyPool - { - public CKeyPool(int nSize = 100) - { - // TODO - } - - public CKeyID ReserveKey(out int nKeyIndex) - { - // TODO - - nKeyIndex = -1; - - return (new CKeyPair()).KeyID; - } - - public void RemoveKey(int nIndex) - { - // TODO - } - - public void ReturnKey(int nIndex) - { - // TODO - } - - public void ResetPool() - { - // TODO - } - - public long OldestTime - { - get { - // TODO - return 0; - } - } - } -} diff --git a/Novacoin/CKeyStore.cs b/Novacoin/CKeyStore.cs index e9e3603..2736d68 100644 --- a/Novacoin/CKeyStore.cs +++ b/Novacoin/CKeyStore.cs @@ -96,51 +96,43 @@ namespace Novacoin /// /// select count(...) as Count from ... where ... + /// select number from ... where ... /// - class CountQuery + class NumQuery { - public int Count { get; set; } + public int Num { get; set; } } + /// + /// Key storage + /// public class CKeyStore { private object LockObj = new object(); private SQLiteConnection dbConn = null; - public CKeyStore(string strDatabasePath="KeyStore.db") + private int nKeyPoolSize = 100; + + /// + /// Initialize new instance of key store. + /// + /// Path to database file. + /// Number of reserved keys. + public CKeyStore(string strDatabasePath="KeyStore.db", int KeyPoolSize = 100) { - bool firstInit = File.Exists(strDatabasePath); + bool firstInit = !File.Exists(strDatabasePath); dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), strDatabasePath); + nKeyPoolSize = KeyPoolSize; - if (!firstInit) + if (firstInit) { lock(LockObj) { dbConn.CreateTable(CreateFlags.AutoIncPK); dbConn.CreateTable(CreateFlags.AutoIncPK); - dbConn.BeginTransaction(); - - // Generate keys - for (int i = 0; i < 1000; i++) - { - var keyPair = new CKeyPair(); - - var res = dbConn.Insert(new KeyStorageItem() - { - KeyID = keyPair.KeyID.hashBytes, - PublicKey = keyPair.PublicBytes, - PrivateKey = keyPair.SecretBytes, - IsCompressed = keyPair.IsCompressed, - IsUsed = false, - nTime = Interop.GetTime() - }); - - // TODO: Additional initialization - } - - dbConn.Commit(); + GenerateKeys(nKeyPoolSize); } } } @@ -155,6 +147,38 @@ namespace Novacoin } /// + /// Generate keys and insert them to key store. + /// + /// + private void GenerateKeys(int n) + { + lock (LockObj) + { + dbConn.BeginTransaction(); + + // Generate keys + for (int i = 0; i < n; i++) + { + var keyPair = new CKeyPair(); + + var res = dbConn.Insert(new KeyStorageItem() + { + KeyID = keyPair.KeyID.hashBytes, + PublicKey = keyPair.PublicBytes, + PrivateKey = keyPair.SecretBytes, + IsCompressed = keyPair.IsCompressed, + IsUsed = false, + nTime = Interop.GetTime() + }); + + // TODO: Additional initialization + } + + dbConn.Commit(); + } + } + + /// /// Insert key data into table /// /// CKeyPair instance @@ -182,11 +206,16 @@ namespace Novacoin return true; } + /// + /// Check existance of item with provided KeyID + /// + /// Hash160 of public key. + /// Checking result public bool HaveKey(CKeyID keyID) { - var QueryCount = dbConn.Query("select count([ItemID]) as [Count] from [KeyStorage] where [KeyID] = ?", keyID.hashBytes); + var QueryCount = dbConn.Query("select count([ItemID]) from [KeyStorage] where [KeyID] = ?", keyID.hashBytes); - return QueryCount.First().Count == 1; + return QueryCount.First().Num == 1; } /// @@ -209,6 +238,11 @@ namespace Novacoin return false; } + /// + /// Add redeem script to script store. + /// + /// CScript instance + /// Result public bool AddScript(CScript script) { lock (LockObj) @@ -228,13 +262,24 @@ namespace Novacoin return true; } + /// + /// Check existance of item with provided ScriptID + /// + /// Hash160 of script code. + /// Checking result public bool HaveScript(CScriptID scriptID) { - var QueryGet = dbConn.Query("select count([ItemID]) from [ScriptStorage] where [ScriptID] = ?", scriptID.hashBytes); + var QueryGet = dbConn.Query("select count([ItemID]) from [ScriptStorage] where [ScriptID] = ?", scriptID.hashBytes); - return QueryGet.First().Count == 1; + return QueryGet.First().Num == 1; } + /// + /// Get redeem script from database. + /// + /// Script ID, evaluated as Hash160(script code). + /// Instance of CScript + /// Result public bool GetScript(CScriptID scriptID, out CScript script) { var QueryGet = dbConn.Query("select * from [ScriptStorage] where [ScriptID] = ?", scriptID.hashBytes); @@ -249,6 +294,90 @@ namespace Novacoin return false; } + + /// + /// SQLite return type for ReserveKey + /// + class ReservedKey + { + public int ItemId { get; set; } + public byte[] KeyID { get; set; } + } + + /// + /// Reserve key from a list of unused keys. + /// + /// Internal index of key + /// CKeyID instance + public CKeyID SelectKey(out int nKeyIndex) + { + var QueryGet = dbConn.Query("select ItemId, KeyID from [KeyStorage] where not IsUsed order by [nTime] asc limit 1"); + + if (QueryGet.Count() == 1) + { + var res = QueryGet.First(); + + nKeyIndex = res.ItemId; + + return new CKeyID(res.KeyID); + } + else + { + // Generate new keys in case if keypool is exhausted. + + GenerateKeys(nKeyPoolSize); + + return SelectKey(out nKeyIndex); + } + } + + /// + /// Mark key as used. + /// + /// Internal index. + public void MarkUsed(int nIndex) + { + lock (LockObj) + { + dbConn.Execute("update [KeyStorage] set [IsUsed] = true where [ItemId] = ?", nIndex); + } + } + + /// + /// Mark key as unused. + /// + /// Internal index. + public void MarkUnused(int nIndex) + { + lock (LockObj) + { + dbConn.Execute("update [KeyStorage] set [IsUsed] = false where [ItemId] = ?", nIndex); + } + } + + /// + /// Regenerate all unused keys. + /// + public void ResetPool() + { + lock (LockObj) + { + dbConn.Execute("delete from [KeyStorage] where [IsUsed] = false"); + GenerateKeys(nKeyPoolSize); + } + } + + /// + /// Timestamp of oldest item in keystore. + /// + public int OldestTime + { + get + { + var QueryTime = dbConn.Query("select [nTime] from [KeyStorage] where not [IsUsed] order by [ItemId] asc limit 1"); + return QueryTime.First().Num; + } + } } } diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index 141a992..788ff16 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -51,7 +51,6 @@ - -- 1.7.1