-\feffusing System;
-using System.Collections.Generic;
+\feff/**
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+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
{
+ /// <summary>
+ /// Key storage item and structure
+ /// </summary>
+ [Table("KeyStorage")]
+ class KeyStorageItem
+ {
+ /// <summary>
+ /// Key item number
+ /// </summary>
+ [PrimaryKey, AutoIncrement]
+ public int ItemId { get; set; }
+
+ /// <summary>
+ /// Hash160 of pubkey in base58 form
+ /// </summary>
+ public string KeyID { get; set; }
+
+ /// <summary>
+ /// Public key in base58 form
+ /// </summary>
+ public string PublicKey { get; set; }
+
+ /// <summary>
+ /// Private key in base58 form
+ /// </summary>
+ public string PrivateKey { get; set; }
+
+ /// <summary>
+ /// Compressed key flag
+ /// </summary>
+ public bool IsCompressed { get; set; }
+
+ /// <summary>
+ /// Is this key a part of KeyPool?
+ /// </summary>
+ [Indexed]
+ public bool IsUsed { get; set; }
+ }
+
+ /// <summary>
+ /// Script storage item and structure
+ /// </summary>
+ [Table("ScriptStorage")]
+ class ScriptStorageItem
+ {
+ /// <summary>
+ /// Script item number
+ /// </summary>
+ [PrimaryKey, AutoIncrement]
+ public int ItemId { get; set; }
+
+ /// <summary>
+ /// Hash160 of script in base58 form
+ /// </summary>
+ public string ScriptID { get; set; }
+
+ /// <summary>
+ /// Script code bytes in hex form
+ /// </summary>
+ public string ScriptCode { get; set; }
+
+ }
+
+ /// <summary>
+ /// select count(...) as Count from ... where ...
+ /// </summary>
+ 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<KeyStorageItem>(CreateFlags.AutoIncPK);
+ dbConn.CreateTable<ScriptStorageItem>(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;
+ }
}
+ /// <summary>
+ /// Insert key data into table
+ /// </summary>
+ /// <param name="keyPair">CKeyPair instance</param>
+ /// <returns>Result</returns>
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<CountQuery>("select count([ItemID]) as [Count] from [KeyStorage] where [KeyID] = ?", keyID.ToString());
- return true;
+
+ return QueryCount.First().Count == 1;
}
+ /// <summary>
+ /// Get the key pair object.
+ /// </summary>
+ /// <param name="keyID">Hash of public key.</param>
+ /// <param name="keyPair">Instance of CKeyPair or null.</param>
+ /// <returns>Result</returns>
public bool GetKey(CKeyID keyID, out CKeyPair keyPair)
{
- keyPair = new CKeyPair();
+ var QueryGet = dbConn.Query<KeyStorageItem>("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<CountQuery>("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<ScriptStorageItem>("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;
}
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;
}
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();
}
}