From 76cb31496b0a6c10854071195c9312366acb56f3 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Wed, 26 Aug 2015 02:47:29 +0300 Subject: [PATCH] Simplest implementation of CKeyStore --- Novacoin/CKeyStore.cs | 209 +++++++++++++++++++++++++++++++++++++++--- Novacoin/CNovacoinAddress.cs | 5 + Novacoin/Novacoin.csproj | 12 +++ NovacoinTest/Program.cs | 23 ++++- 4 files changed, 232 insertions(+), 17 deletions(-) diff --git a/Novacoin/CKeyStore.cs b/Novacoin/CKeyStore.cs index 59c3fbd..e90b103 100644 --- a/Novacoin/CKeyStore.cs +++ b/Novacoin/CKeyStore.cs @@ -1,63 +1,242 @@ -using System; -using System.Collections.Generic; +/** + * Novacoin classes library + * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +using SQLite.Net; +using SQLite.Net.Attributes; +using SQLite.Net.Interop; +using SQLite.Net.Platform.Generic; +using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Novacoin { + /// + /// Key storage item and structure + /// + [Table("KeyStorage")] + class KeyStorageItem + { + /// + /// Key item number + /// + [PrimaryKey, AutoIncrement] + public int ItemId { get; set; } + + /// + /// Hash160 of pubkey in base58 form + /// + public string KeyID { get; set; } + + /// + /// Public key in base58 form + /// + public string PublicKey { get; set; } + + /// + /// Private key in base58 form + /// + public string PrivateKey { get; set; } + + /// + /// Compressed key flag + /// + public bool IsCompressed { get; set; } + + /// + /// Is this key a part of KeyPool? + /// + [Indexed] + public bool IsUsed { get; set; } + } + + /// + /// Script storage item and structure + /// + [Table("ScriptStorage")] + class ScriptStorageItem + { + /// + /// Script item number + /// + [PrimaryKey, AutoIncrement] + public int ItemId { get; set; } + + /// + /// Hash160 of script in base58 form + /// + public string ScriptID { get; set; } + + /// + /// Script code bytes in hex form + /// + public string ScriptCode { get; set; } + + } + + /// + /// select count(...) as Count from ... where ... + /// + class CountQuery + { + public int Count { get; set; } + } + public class CKeyStore { - public CKeyStore(string strDatabasePath="Wallet.db") + private object LockObj = new object(); + private SQLiteConnection dbConn = null; + + public CKeyStore(string strDatabasePath="KeyStore.db") { + bool firstInit = File.Exists(strDatabasePath); + + dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), strDatabasePath); + + if (!firstInit) + { + lock(LockObj) + { + dbConn.CreateTable(CreateFlags.AutoIncPK); + dbConn.CreateTable(CreateFlags.AutoIncPK); + + // Generate keys + for (int i = 0; i < 100; i++) + { + var keyPair = new CKeyPair(); + + var res = dbConn.Insert(new KeyStorageItem() + { + KeyID = keyPair.KeyID.ToString(), // Use string serializarion of binary values, + PublicKey = keyPair.PubKey.ToString(), // otherwise sqlite corrupts them. + PrivateKey = keyPair.ToString(), + IsCompressed = keyPair.IsCompressed, + IsUsed = false + }); + + // TODO: Additional initialization + } + } + } } ~CKeyStore() { + if (dbConn != null) + { + dbConn.Close(); + dbConn = null; + } } + /// + /// Insert key data into table + /// + /// CKeyPair instance + /// Result public bool AddKey(CKeyPair keyPair) { - // TODO + lock(LockObj) + { + var res = dbConn.Insert(new KeyStorageItem() + { + KeyID = keyPair.KeyID.ToString(), + PublicKey = keyPair.PubKey.ToString(), + PrivateKey = keyPair.ToString(), + IsCompressed = keyPair.IsCompressed, + IsUsed = true + }); + + if (res == 0) + { + return false; + } + } return true; } public bool HaveKey(CKeyID keyID) { - // TODO + var QueryCount = dbConn.Query("select count([ItemID]) as [Count] from [KeyStorage] where [KeyID] = ?", keyID.ToString()); - return true; + + return QueryCount.First().Count == 1; } + /// + /// Get the key pair object. + /// + /// Hash of public key. + /// Instance of CKeyPair or null. + /// Result public bool GetKey(CKeyID keyID, out CKeyPair keyPair) { - keyPair = new CKeyPair(); + var QueryGet = dbConn.Query("select * from [KeyStorage] where [KeyID] = ?", keyID.ToString()); + if (QueryGet.Count() == 1) + { + keyPair = new CKeyPair(QueryGet.First().PrivateKey); + return true; + } + + keyPair = null; return false; } public bool AddScript(CScript script) { - // TODO + lock (LockObj) + { + var res = dbConn.Insert(new ScriptStorageItem() + { + ScriptID = script.ScriptID.ToString(), + ScriptCode = Interop.ToHex(script.Bytes) + }); + + if (res == 0) + { + return false; + } + } return true; } public bool HaveScript(CScriptID scriptID) { - // TODO + var QueryGet = dbConn.Query("select count([ItemID]) from [ScriptStorage] where [ScriptID] = ?", scriptID.ToString()); - return true; + return QueryGet.First().Count == 1; } public bool GetScript(CScriptID scriptID, out CScript script) { - // TODO + var QueryGet = dbConn.Query("select * from [ScriptStorage] where [ScriptID] = ?", scriptID.ToString()); - script = new CScript(); + if (QueryGet.Count() == 1) + { + script = new CScript(Interop.HexToArray(QueryGet.First().ScriptCode)); + return true; + } - return true; + script = null; + return false; } diff --git a/Novacoin/CNovacoinAddress.cs b/Novacoin/CNovacoinAddress.cs index 22e94ae..e443b88 100644 --- a/Novacoin/CNovacoinAddress.cs +++ b/Novacoin/CNovacoinAddress.cs @@ -79,6 +79,11 @@ namespace Novacoin addrData = new List(scriptID.hashBytes); } + public Hash160 Hash + { + get { return new Hash160(addrData.ToArray()); } + } + /// /// Basic sanity checking /// diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index fc561f8..141a992 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -28,6 +28,18 @@ false + + ..\packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.dll + True + + + ..\packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.Platform.Generic.dll + True + + + ..\packages\SQLite.Net-PCL.3.0.5\lib\net4\SQLite.Net.Platform.Win32.dll + True + diff --git a/NovacoinTest/Program.cs b/NovacoinTest/Program.cs index 0fc0176..708747d 100644 --- a/NovacoinTest/Program.cs +++ b/NovacoinTest/Program.cs @@ -231,12 +231,12 @@ namespace NovacoinTest Hash256 merkleroot = null; - Console.WriteLine("\nRinning 1000 iterations of merkle tree computation for very big block..."); + Console.WriteLine("\nRinning 100 iterations of merkle tree computation for very big block..."); watch = Stopwatch.StartNew(); // the code that you want to measure comes here - for (int i = 0; i < 1000; i++) + for (int i = 0; i < 100; i++) { merkleroot = veryBigBlock.hashMerkleRoot; } @@ -246,6 +246,25 @@ namespace NovacoinTest Console.WriteLine("Calculation time: {0} ms\n", elapsedMs); Console.WriteLine("Merkle tree is OK: {0}", merkleroot.hashBytes.SequenceEqual(veryBigBlock.header.merkleRoot.hashBytes)); + // Initialization of key store + + Console.Write("Initialization of key store..."); + var keyStore = new CKeyStore(); + + Console.WriteLine("Adding and querying new key pair"); + var kp1 = new CKeyPair(); + keyStore.AddKey(kp1); + + + CKeyPair kp2; + var queryRes = keyStore.GetKey(kp1.KeyID, out kp2); + Console.WriteLine("KeyID={0} exists in database: {1}", kp1.KeyID.ToString(), queryRes); + + if (queryRes) + { + Console.WriteLine("KeyID={0} is identical to inserted one: {1}", kp2.KeyID.ToString(), kp2.KeyID.ToString() == kp1.KeyID.ToString()); + } + Console.ReadLine(); } } -- 1.7.1