KeyStore: key timestamp
[NovacoinLibrary.git] / Novacoin / CKeyStore.cs
1 \feff/**
2  *  Novacoin classes library
3  *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
4
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 using SQLite.Net;
21 using SQLite.Net.Attributes;
22 using SQLite.Net.Interop;
23 using SQLite.Net.Platform.Generic;
24 using System.IO;
25 using System.Linq;
26
27 namespace Novacoin
28 {
29     /// <summary>
30     /// Key storage item and structure
31     /// </summary>
32     [Table("KeyStorage")]
33     class KeyStorageItem
34     {
35         /// <summary>
36         /// Key item number
37         /// </summary>
38         [PrimaryKey, AutoIncrement]
39         public int ItemId { get; set; }
40
41         /// <summary>
42         /// Hash160 of pubkey
43         /// </summary>
44         public byte[] KeyID { get; set; }
45
46         /// <summary>
47         /// Public key 
48         /// </summary>
49         public byte[] PublicKey { get; set; }
50
51         /// <summary>
52         /// Private key 
53         /// </summary>
54         public byte[] PrivateKey { get; set; }
55
56         /// <summary>
57         /// Compressed key flag
58         /// </summary>
59         public bool IsCompressed { get; set; }
60
61         /// <summary>
62         /// Is this key a part of KeyPool?
63         /// </summary>
64         [Indexed]
65         public bool IsUsed { get; set; }
66
67         /// <summary>
68         /// Item creation time
69         /// </summary>
70         [Indexed]
71         public int nTime { get; set; }
72     }
73
74     /// <summary>
75     /// Script storage item and structure
76     /// </summary>
77     [Table("ScriptStorage")]
78     class ScriptStorageItem
79     {
80         /// <summary>
81         /// Script item number
82         /// </summary>
83         [PrimaryKey, AutoIncrement]
84         public int ItemId { get; set; }
85
86         /// <summary>
87         /// Hash160 of script 
88         /// </summary>
89         public byte[] ScriptID { get; set; }
90
91         /// <summary>
92         /// Script code bytes 
93         /// </summary>
94         public byte[] ScriptCode { get; set; }
95     }
96
97     /// <summary>
98     /// select count(...) as Count from ... where ...
99     /// </summary>
100     class CountQuery
101     {
102         public int Count { get; set; }
103     }
104
105     public class CKeyStore
106     {
107         private object LockObj = new object();
108         private SQLiteConnection dbConn = null;
109
110         public CKeyStore(string strDatabasePath="KeyStore.db")
111         {
112             bool firstInit = File.Exists(strDatabasePath);
113
114             dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), strDatabasePath);
115
116             if (!firstInit)
117             {
118                 lock(LockObj)
119                 {
120                     dbConn.CreateTable<KeyStorageItem>(CreateFlags.AutoIncPK);
121                     dbConn.CreateTable<ScriptStorageItem>(CreateFlags.AutoIncPK);
122
123                     dbConn.BeginTransaction();
124
125                     // Generate keys
126                     for (int i = 0; i < 1000; i++)
127                     {
128                         var keyPair = new CKeyPair();
129
130                         var res = dbConn.Insert(new KeyStorageItem()
131                         {
132                             KeyID = keyPair.KeyID.hashBytes,
133                             PublicKey = keyPair.PublicBytes,
134                             PrivateKey = keyPair.SecretBytes,
135                             IsCompressed = keyPair.IsCompressed,
136                             IsUsed = false,
137                             nTime = Interop.GetTime()
138                         });
139
140                         // TODO: Additional initialization
141                     }
142
143                     dbConn.Commit();
144                 }
145             }
146         }
147
148         ~CKeyStore()
149         {
150             if (dbConn != null)
151             {
152                 dbConn.Close();
153                 dbConn = null;
154             }
155         }
156
157         /// <summary>
158         /// Insert key data into table
159         /// </summary>
160         /// <param name="keyPair">CKeyPair instance</param>
161         /// <returns>Result</returns>
162         public bool AddKey(CKeyPair keyPair)
163         {
164             lock(LockObj)
165             {
166                 var res = dbConn.Insert(new KeyStorageItem()
167                 {
168                     KeyID = keyPair.KeyID.hashBytes,
169                     PublicKey = keyPair.PublicBytes,
170                     PrivateKey = keyPair.SecretBytes,
171                     IsCompressed = keyPair.IsCompressed,
172                     IsUsed = true,
173                     nTime = Interop.GetTime()
174                 });
175
176                 if (res == 0)
177                 {
178                     return false;
179                 }
180             }
181
182             return true;
183         }
184
185         public bool HaveKey(CKeyID keyID)
186         {
187             var QueryCount = dbConn.Query<CountQuery>("select count([ItemID]) as [Count] from [KeyStorage] where [KeyID] = ?", keyID.hashBytes);
188
189             return QueryCount.First().Count == 1;
190         }
191
192         /// <summary>
193         /// Get the key pair object.
194         /// </summary>
195         /// <param name="keyID">Hash of public key.</param>
196         /// <param name="keyPair">Instance of CKeyPair or null.</param>
197         /// <returns>Result</returns>
198         public bool GetKey(CKeyID keyID, out CKeyPair keyPair)
199         {
200             var QueryGet = dbConn.Query<KeyStorageItem>("select * from [KeyStorage] where [KeyID] = ?", keyID.hashBytes);
201
202             if (QueryGet.Count() == 1)
203             {
204                 keyPair = new CKeyPair(QueryGet.First().PrivateKey);
205                 return true;
206             }
207
208             keyPair = null;
209             return false;
210         }
211
212         public bool AddScript(CScript script)
213         {
214             lock (LockObj)
215             {
216                 var res = dbConn.Insert(new ScriptStorageItem()
217                 {
218                     ScriptID = script.ScriptID.hashBytes,
219                     ScriptCode = script.Bytes
220                 });
221
222                 if (res == 0)
223                 {
224                     return false;
225                 }
226             }
227
228             return true;
229         }
230
231         public bool HaveScript(CScriptID scriptID)
232         {
233             var QueryGet = dbConn.Query<CountQuery>("select count([ItemID]) from [ScriptStorage] where [ScriptID] = ?", scriptID.hashBytes);
234
235             return QueryGet.First().Count == 1;
236         }
237
238         public bool GetScript(CScriptID scriptID, out CScript script)
239         {
240             var QueryGet = dbConn.Query<ScriptStorageItem>("select * from [ScriptStorage] where [ScriptID] = ?", scriptID.hashBytes);
241
242             if (QueryGet.Count() == 1)
243             {
244                 script = new CScript(QueryGet.First().ScriptCode);
245                 return true;
246             }
247
248             script = null;
249             return false;
250         }
251
252
253     }
254 }