~ubuntu-branches/debian/jessie/armory/jessie

« back to all changes in this revision

Viewing changes to cppForSwig/old_not_very_good_tests.cpp

  • Committer: Package Import Robot
  • Author(s): Joseph Bisch
  • Date: 2014-10-07 10:22:45 UTC
  • Revision ID: package-import@ubuntu.com-20141007102245-2s3x3rhjxg689hek
Tags: upstream-0.92.3
ImportĀ upstreamĀ versionĀ 0.92.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
//                                                                            //
 
3
//  Copyright (C) 2011-2014, Armory Technologies, Inc.                        //
 
4
//  Distributed under the GNU Affero General Public License (AGPL v3)         //
 
5
//  See LICENSE or http://www.gnu.org/licenses/agpl.html                      //
 
6
//                                                                            //
 
7
////////////////////////////////////////////////////////////////////////////////
 
8
#include <iostream>
 
9
#include <stdio.h>
 
10
#include <fstream>
 
11
#include <string>
 
12
#include <sstream>
 
13
#include "UniversalTimer.h"
 
14
#include "BinaryData.h"
 
15
#include "BtcUtils.h"
 
16
#include "BlockUtils.h"
 
17
#include "EncryptionUtils.h"
 
18
//#include "FileDataPtr.h"
 
19
#include "PartialMerkle.h"
 
20
#include "leveldb_wrapper.h"
 
21
 
 
22
#include "leveldb/db.h"
 
23
 
 
24
 
 
25
using namespace std;
 
26
 
 
27
 
 
28
 
 
29
////////////////////////////////////////////////////////////////////////////////
 
30
void BaseTests(void);
 
31
void TestReadAndOrganizeChain(string blkdir);
 
32
void TestFindNonStdTx(string blkdir);
 
33
void TestReadAndOrganizeChainWithWallet(string blkdir);
 
34
void TestBalanceConstruction(string blkdir);
 
35
void TestReadAndUpdateBlkFile(string blkdir);
 
36
void TestScanForWalletTx(string blkdir);
 
37
void TestReorgBlockchain(string blkdir);
 
38
void TestZeroConf(void);
 
39
void TestCrypto(void);
 
40
void TestMerkle(void);
 
41
void TestECDSA(void);
 
42
void TestPointCompression(void);
 
43
void TestFileCache(void);
 
44
void TestReadBlkFileUpdate(string testblockdir, string blkdir);
 
45
 
 
46
void TestOutOfOrder(string blkdir);
 
47
void TestLevelDB(string testLDBDir, string blkfilepath="");
 
48
void TestLDBScanBlockchain(string testdbpath);
 
49
void TestLdbBlockchainUtils(string blkdir);
 
50
 
 
51
////////////////////////////////////////////////////////////////////////////////
 
52
 
 
53
void printTestHeader(string TestName)
 
54
{
 
55
   cout << endl;
 
56
   for(int i=0; i<80; i++) cout << "*";
 
57
   cout << endl << "Execute test: " << TestName << endl;
 
58
   for(int i=0; i<80; i++) cout << "*";
 
59
   cout << endl;
 
60
}
 
61
 
 
62
bool copyFile(string src, string dst)
 
63
{
 
64
   uint32_t srcsz = BtcUtils::GetFileSize(src);
 
65
   if(srcsz == FILE_DOES_NOT_EXIST)
 
66
      return false;
 
67
 
 
68
   BinaryData temp(srcsz);
 
69
   ifstream is(src.c_str(), ios::in  | ios::binary);
 
70
   is.read((char*)temp.getPtr(), srcsz);
 
71
   is.close();
 
72
 
 
73
   ofstream os(dst.c_str(), ios::out | ios::binary);
 
74
   os.write((char*)temp.getPtr(), srcsz);
 
75
   os.close();
 
76
   return true;
 
77
}
 
78
 
 
79
 
 
80
string pathJoin(string dir, string file)
 
81
{
 
82
   int const TOTALSZ = dir.size() + file.size() + 10;
 
83
   char * path = new char[TOTALSZ];
 
84
   sprintf(path, "%s/%s", dir.c_str(), file.c_str());
 
85
   string ret(path);
 
86
   return ret;
 
87
}
 
88
 
 
89
 
 
90
BinaryData h2b(string s)
 
91
{
 
92
   return BinaryData::CreateFromHex(s);
 
93
}
 
94
 
 
95
 
 
96
int main(void)
 
97
{
 
98
   BaseTests();
 
99
 
 
100
   BlockDataManager_LevelDB::GetInstance().SelectNetwork("Test");
 
101
   
 
102
 
 
103
   //string blkdir("/home/alan/.bitcoin");
 
104
   //string blkdir("/home/alan/.bitcoin/testnet/");
 
105
   //string blkdir("C:/Users/VBox/AppData/Roaming/Bitcoin");
 
106
   string blkdir("C:/Users/Andy/AppData/Roaming/Bitcoin/testnet");
 
107
   //string multitest("./multiblktest");
 
108
   
 
109
 
 
110
   //printTestHeader("Read-and-Organize-Blockchain");
 
111
   TestReadAndOrganizeChain(blkdir);
 
112
 
 
113
   //printTestHeader("Wallet-Relevant-Tx-Scan");
 
114
   TestScanForWalletTx(blkdir);
 
115
 
 
116
   //printTestHeader("Find-Non-Standard-Tx");
 
117
   //TestFindNonStdTx(blkdir);
 
118
 
 
119
   //printTestHeader("Read-and-Organize-Blockchain-With-Wallet");
 
120
   //TestReadAndOrganizeChainWithWallet(blkdir);
 
121
 
 
122
   //printTestHeader("Test-Balance-Construction");
 
123
   //TestBalanceConstruction(blkdir);
 
124
 
 
125
   //printTestHeader("Read-and-Update-Blockchain");
 
126
   //TestReadAndUpdateBlkFile(multitest);
 
127
 
 
128
   //printTestHeader("Blockchain-Reorg-Unit-Test");
 
129
   //TestReorgBlockchain("");
 
130
 
 
131
   //printTestHeader("Test-out-of-order calls");
 
132
   //TestOutOfOrder(blkdir);
 
133
 
 
134
 
 
135
   //printTestHeader("Testing Zero-conf handling");
 
136
   //TestZeroConf();
 
137
 
 
138
   printTestHeader("Testing merkle-root calculation");
 
139
   TestMerkle();
 
140
 
 
141
   //printTestHeader("Crypto-KDF-and-AES-methods");
 
142
   //TestCrypto();
 
143
 
 
144
   //printTestHeader("Crypto-ECDSA-sign-verify");
 
145
   //TestECDSA();
 
146
 
 
147
   //printTestHeader("ECDSA Point Compression");
 
148
   //TestPointCompression();
 
149
 
 
150
   //printTestHeader("Testing file cache");
 
151
   //TestFileCache();
 
152
   
 
153
   //printTestHeader("Testing LevelDB");
 
154
   //TestLevelDB("blk0001db", blkdir + string("/blk0001.dat"));
 
155
   //TestLDBScanBlockchain("blk0001db");
 
156
   
 
157
 
 
158
   //printTestHeader("Testing LDB Blockchain utilities");
 
159
   //TestLdbBlockchainUtils(blkdir);
 
160
 
 
161
 
 
162
   /////////////////////////////////////////////////////////////////////////////
 
163
   // ***** Print out all timings to stdout and a csv file *****
 
164
   //       Any method, anywhere, that called UniversalTimer
 
165
   //       will end up having it's named timers printed out
 
166
   //       This file can be loaded into a spreadsheet,
 
167
   //       but it's not the prettiest thing...
 
168
   UniversalTimer::instance().print();
 
169
   UniversalTimer::instance().printCSV("timings.csv");
 
170
   cout << endl << endl;
 
171
   char pause[256];
 
172
   cout << "enter anything to exit" << endl;
 
173
   cin >> pause;
 
174
}
 
175
 
 
176
 
 
177
 
 
178
 
 
179
void assertError(bool isTrue, string msg)
 
180
{
 
181
   if(isTrue)
 
182
      return;
 
183
 
 
184
   cerr << "***ERROR:  Failed BaseTest.   Msg:" << endl;
 
185
   cerr << msg.c_str() << endl;
 
186
   exit(1);
 
187
}
 
188
 
 
189
 
 
190
void BaseTests(void)
 
191
{
 
192
 
 
193
   BinaryData pushScript1 = h2b("493046022100c6abd6466c0cca354bebe9e9fb200ebd2924726a390eec8d76643cbb7959a070022100a5e02686e49819644d1f10d39fd59a41eb5c6f7bc28923f65cad72651fc8131401410459fd82189b81772258a3fc723fdda900eb8193057d4a573ee5ad39e26b58b5c12c4a51b0edd01769f96ed1998221daf0df89634a7137a8fa312d5ccc95ed89254930460221008e238f15d45c1d3739a6c65b6ad9689837f01685d0ded7adbff139e479d4a802022100b19ea60db5fdfc228a07b6d6b5115e148b861cd1085c4db1546da913a35a3f64014104ce6242d72ee67e867e6f8ec434b95fcb1889c5b485ec3414df407e11194a7ce012eda021b68f1dd124598a9b677d6e7d7c95b1b7347f5c5a08efa628ef0204e1483045022100cd58f567dba08d9f33c59efd7271e105ab19a2e9e9f7ec423d93b2c5759636ad02206f6512f67a40051c8dd5a3910b371246a409d7589afcf019cc3550bbfcc41416014104ce66c9f5068b715b62cc1622572cd98a08812d8ca01563045263c3e7af6b997e603e8e62041c4eb82dfd386a3412c34c334c34eb3c76fb0e37483fc72323f807");
 
194
   BinaryData pushScript2 = h2b("00493046022100c6abd6466c0cca354bebe9e9fb200ebd2924726a390eec8d76643cbb7959a070022100a5e02686e49819644d1f10d39fd59a41eb5c6f7bc28923f65cad72651fc8131401410459fd82189b81772258a3fc723fdda900eb8193057d4a573ee5ad39e26b58b5c12c4a51b0edd01769f96ed1998221daf0df89634a7137a8fa312d5ccc95ed89254930460221008e238f15d45c1d3739a6c65b6ad9689837f01685d0ded7adbff139e479d4a802022100b19ea60db5fdfc228a07b6d6b5115e148b861cd1085c4db1546da913a35a3f64014104ce6242d72ee67e867e6f8ec434b95fcb1889c5b485ec3414df407e11194a7ce012eda021b68f1dd124598a9b677d6e7d7c95b1b7347f5c5a08efa628ef0204e1483045022100cd58f567dba08d9f33c59efd7271e105ab19a2e9e9f7ec423d93b2c5759636ad02206f6512f67a40051c8dd5a3910b371246a409d7589afcf019cc3550bbfcc41416014104ce66c9f5068b715b62cc1622572cd98a08812d8ca01563045263c3e7af6b997e603e8e62041c4eb82dfd386a3412c34c334c34eb3c76fb0e37483fc72323f807");
 
195
   vector<BinaryData> splitPush = splitPushOnlyScript(pushScript1);
 
196
   cout << "Splitting push-only script" << endl;
 
197
   for(uint32_t i=0; i<splitPush.size(); i++)
 
198
      cout << "   " << splitPush[i].toHexStr() << endl;
 
199
   cout << endl;
 
200
   
 
201
   /////////////////////////////////////////////////////////////////////////////
 
202
   // Test TxOut/TxIn script interpretting
 
203
   vector<BinaryData> txOutScripts;
 
204
   vector<TXOUT_SCRIPT_TYPE> txOutTypes;
 
205
   vector<BinaryData> hash160s;
 
206
   vector<BinaryData> txOutLDBKeys;
 
207
 
 
208
   txOutTypes.push_back( TXOUT_SCRIPT_STDHASH160 )
 
209
   txOutScripts.push_back( h2b("76a914a134408afa258a50ed7a1d9817f26b63cc9002cc88ac"));
 
210
   txOutHash160s.push_back( h2b("a134408afa258a50ed7a1d9817f26b63cc9002cc"));
 
211
   txOutLDBKeys.push_back(h2b("00a134408afa258a50ed7a1d9817f26b63cc9002cc"));
 
212
 
 
213
   txOutTypes.push_back( TXOUT_SCRIPT_STDPUBKEY65 );
 
214
   txOutScripts.push_back( h2b("4104b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7bac"));
 
215
   txOutHash160s.push_back( h2b("6da6f1bd6c6380633bc667ba232611f5bf864be2"));
 
216
   txOutLDBKeys.push_back(h2b("006da6f1bd6c6380633bc667ba232611f5bf864be2"));
 
217
 
 
218
 
 
219
   txOutTypes.push_back( TXOUT_SCRIPT_STDPUBKEY33 );
 
220
   txOutScripts.push_back( h2b("21024005c945d86ac6b01fb04258345abea7a845bd25689edb723d5ad4068ddd3036ac"));
 
221
   txOutHash160s.push_back( h2b("0c1b83d01d0ffb2bccae606963376cca3863a7ce"));
 
222
   txOutLDBKeys.push_back(h2b("000c1b83d01d0ffb2bccae606963376cca3863a7ce"));
 
223
 
 
224
   // This was from block 150951 which was erroneously produced by MagicalTux
 
225
   // This is not only non-standard, it's non-spendable
 
226
   txOutTypes.push_back( TXOUT_SCRIPT_NONSTANDARD );
 
227
   txOutScripts.push_back( h2b("76a90088ac"));
 
228
   txOutHash160s.push_back( BtcUtils::BadAddress_);
 
229
   txOutLDBKeys.push_back(h2b("ff76a90088ac"));
 
230
 
 
231
   // P2SH script from tx: 4ac04b4830d115eb9a08f320ef30159cc107dfb72b29bbc2f370093f962397b4 (TxOut: 1)
 
232
   // Spent in tx:         fd16d6bbf1a3498ca9777b9d31ceae883eb8cb6ede1fafbdd218bae107de66fe (TxIn: 1)
 
233
   // P2SH address:        3Lip6sxQymNr9LD2cAVp6wLrw8xdKBdYFG
 
234
   // Hash160:             d0c15a7d41500976056b3345f542d8c944077c8a
 
235
   txOutTypes.push_back( TXOUT_SCRIPT_P2SH )
 
236
   txOutScripts.push_back( h2b("a914d0c15a7d41500976056b3345f542d8c944077c8a87")); // send to P2SH
 
237
   txOutHash160s.push_back( h2b("d0c15a7d41500976056b3345f542d8c944077c8a"));
 
238
   txOutLDBKeys.push_back( h2b("05d0c15a7d41500976056b3345f542d8c944077c8a"));
 
239
 
 
240
 
 
241
   //realCoinbaseOut = "04b6acd549c083cb0d31ee975eb8c2ad7a41be61f0a47bc5d75e919d42704e5642d72f1804bcbab60dbd33f041d3c9edde57704a061a22c5e3cf93debf5f35daaeac"
 
242
   //spendcb = "47304402201ffc44394e5a3dd9c8b55bdc12147e18574ac945d15dac026793bf3b8ff732af022035fd832549b5176126f735d87089c8c1c1319447a458a09818e173eaf0c2eef101"
 
243
   //has160 = 957efec6af757ccbbcf9a436f0083c5ddaa3bf1d
 
244
   //addrStr 1EdTpNBiPNPbEE4kASow2F4pUpES9jeTJE
 
245
 
 
246
   vector<BinaryData> txInScripts;
 
247
   vector<BinaryData> txInPrevHashes;
 
248
   vector<TXIN_SCRIPT_TYPE> txInTypes;
 
249
   vector<BinaryData> txInHash160s;
 
250
 
 
251
   prevHashCB  = h2b("0000000000000000000000000000000000000000000000000000000000000000");
 
252
   prevHashReg = h2b("894862e362905c6075074d9ec4b4e2dc34720089b1e9ef4738ee1b13f3bdcdb7");
 
253
 
 
254
   txInTypes.push_back(TXIN_SCRIPT_STDUNCOMPR)
 
255
   txInScripts.push_back( h2b("493046022100b9daf2733055be73ae00ee0c5d78ca639d554fe779f163396c1a39b7913e7eac02210091f0deeb2e510c74354afb30cc7d8fbac81b1ca8b3940613379adc41a6ffd226014104b1537fa5bc2242d25ebf54f31e76ebabe0b3de4a4dccd9004f058d6c2caa5d31164252e1e04e5df627fae7adec27fa9d40c271fc4d30ff375ef6b26eba192bac"))
 
256
   txInPrevHashes.push_back(prevHashReg);
 
257
   txInHash160s.push_back(h2b("c42a8290196b2c5bcb35471b45aa0dc096baed5e"));
 
258
 
 
259
   txInTypes.push_back(TXIN_SCRIPT_STDCOMPR);
 
260
   txInScripts.push_back( h2b("47304402205299224886e5e3402b0e9fa3527bcfe1d73c4e2040f18de8dd17f116e3365a1102202590dcc16c4b711daae6c37977ba579ca65bcaa8fba2bd7168a984be727ccf7a01210315122ff4d41d9fe3538a0a8c6c7f813cf12a901069a43d6478917246dc92a782"));
 
261
   txInPrevHashes.push_back(prevHashReg);
 
262
   txInHash160s.push_back("03214fc1433a287e964d6c4242093c34e4ed0001");
 
263
 
 
264
 
 
265
   txInTypes.push_back(TXIN_SCRIPT_COINBASE)
 
266
   txInScripts.push_back( h2b("0310920304000071c3124d696e656420627920425443204775696c640800b75f950e000000"));
 
267
   txInPrevHashes.push_back(prevHashCB);
 
268
   txInHash160s.push_back( BtcUtils::BadAddress_); 
 
269
 
 
270
   // Spending P2SH output as above:  fd16d6bbf1a3498ca9777b9d31ceae883eb8cb6ede1fafbdd218bae107de66fe (TxIn: 1, 219 B)
 
271
   // Leading 0x00 byte is required due to a bug in OP_CHECKMULTISIG
 
272
   txInTypes.push_back(TXIN_SCRIPT_SPENDP2SH)
 
273
   txInScripts.push_back( h2b("004830450221009254113fa46918f299b1d18ec918613e56cffbeba0960db05f66b51496e5bf3802201e229de334bd753a2b08b36cc3f38f5263a23e9714a737520db45494ec095ce80148304502206ee62f539d5cd94f990b7abfda77750f58ff91043c3f002501e5448ef6dba2520221009d29229cdfedda1dd02a1a90bb71b30b77e9c3fc28d1353f054c86371f6c2a8101475221034758cefcb75e16e4dfafb32383b709fa632086ea5ca982712de6add93060b17a2103fe96237629128a0ae8c3825af8a4be8fe3109b16f62af19cec0b1eb93b8717e252ae")); 
 
274
   txInPrevHashes.push_back(prevHashReg);
 
275
   txInHash160s.push_back( BtcUtils::BadAddress_); 
 
276
 
 
277
 
 
278
   txInTypes.push_back(TXIN_SCRIPT_SPENDPUBKEY)
 
279
   txInScripts.push_back( h2b("47304402201ffc44394e5a3dd9c8b55bdc12147e18574ac945d15dac026793bf3b8ff732af022035fd832549b5176126f735d87089c8c1c1319447a458a09818e173eaf0c2eef101"));
 
280
   txInPrevHashes.push_back(prevHashReg);
 
281
   txInHash160s.push_back( BtcUtils::BadAddress_); 
 
282
   //txInHash160s.push_back( h2b("957efec6af757ccbbcf9a436f0083c5ddaa3bf1d")); // this one can't be determined
 
283
  
 
284
 
 
285
   uint32_t nOutTest = txOutScripts.size(); 
 
286
   TXOUT_SCRIPT_TYPE outType;
 
287
   BinaryData a160Out_1, a160Out_2;
 
288
   BinaryData keyOut_1, keyOut_2;
 
289
   for(uint32_t test=0; test<nOutTest; test++)
 
290
   {
 
291
      outType   = getTxOutScriptType(txOutScripts[test].getRef());
 
292
      a160Out_1 = getTxOutRecipientAddr(txOutScripts[test].getRef());
 
293
      a160Out_2 = getTxOutRecipientAddr(txOutScripts[test].getRef(), outType);
 
294
      keyOut_1  = getTxOutScriptLDBKey(txOutScripts[test].getRef());
 
295
      keyOut_2  = getTxOutScriptLDBKey(txOutScripts[test].getRef(), outType);
 
296
 
 
297
      assertError(outType==txOutTypes[test], "TxOut Script Type does not match");    
 
298
      assertError(a160Out_1==txOutHash160s[test], "TxOut Hash160_1 does not match");    
 
299
      assertError(a160Out_1==txOutHash160s[test], "TxOut Hash160_2 does not match");    
 
300
      assertError(keyOut_1==txOutLDBKeys[test], "TxOut LDBKey_1 does not match");    
 
301
      assertError(keyOut_2==txOutLDBKeys[test], "TxOut LDBKey_2 does not match");    
 
302
   }
 
303
 
 
304
   uint32_t nInTest = txInScripts.size();
 
305
   TXIN_SCRIPT_TYPE inType; 
 
306
   BinaryData a160;
 
307
   for(uint32_t test=0; test<nInTest; test++)
 
308
   {
 
309
      inType = getTxInScriptType(txInScripts[test], txInPrevHashes[test]);
 
310
      a160 = 
 
311
   }
 
312
 
 
313
   vector<BinaryData> txInScripts;
 
314
   vector<BinaryData> txInPrevHashes;
 
315
   vector<TXIN_SCRIPT_TYPE> txInTypes;
 
316
   vector<BinaryData> txInHash160s;
 
317
 
 
318
 
 
319
   // Test difficulty-to-double
 
320
   vector<BinaryData> diffBits;
 
321
   vector<double>     diffDbls;
 
322
 
 
323
   diffBits.push_back(h2b("ffff001d"));
 
324
   diffDbls.push_back(1.0);
 
325
 
 
326
   diffBits.push_back(h2b("be2f021a"));
 
327
   diffDbls.push_back(7672999.920164138);
 
328
 
 
329
   diffBits.push_back(h2b("3daa011a"));
 
330
   diffDbls.push_back(10076292.883418716);
 
331
 
 
332
   for(uint32_t test=0; test<diffBits.size(); test++)
 
333
   {
 
334
      double diffdbl = convertDiffBitsToDouble(diffBits[test]);
 
335
      assertError(abs(diffdbl-diffDbls[test])<1e-4, "Double repr of diff !match!");
 
336
   }
 
337
 
 
338
 
 
339
 
 
340
   BinaryData txFull(h2b("01000000020044fbc929d78e4203eed6f1d3d39c0157d8e5c100bbe0886779c0ebf6a69324010000008a47304402206568144ed5e7064d6176c74738b04c08ca19ca54ddeb480084b77f45eebfe57802207927d6975a5ac0e1bb36f5c05356dcda1f521770511ee5e03239c8e1eecf3aed0141045d74feae58c4c36d7c35beac05eddddc78b3ce4b02491a2eea72043978056a8bc439b99ddaad327207b09ef16a8910828e805b0cc8c11fba5caea2ee939346d7ffffffff45c866b219b176952508f8e5aea728f950186554fc4a5807e2186a8e1c4009e5000000008c493046022100bd5d41662f98cfddc46e86ea7e4a3bc8fe9f1dfc5c4836eaf7df582596cfe0e9022100fc459ae4f59b8279d679003b88935896acd10021b6e2e4619377e336b5296c5e014104c00bab76a708ba7064b2315420a1c533ca9945eeff9754cdc574224589e9113469b4e71752146a10028079e04948ecdf70609bf1b9801f6b73ab75947ac339e5ffffffff02ac4c8bd5000000001976a9148dce8946f1c7763bb60ea5cf16ef514cbed0633b88ac002f6859000000001976a9146a59ac0e8f553f292dfe5e9f3aaa1da93499c15e88ac00000000"));
 
341
 
 
342
   BinaryData txFrag(h2b("01000000020044fbc929d78e4203eed6f1d3d39c0157d8e5c100bbe0886779c0ebf6a69324010000008a47304402206568144ed5e7064d6176c74738b04c08ca19ca54ddeb480084b77f45eebfe57802207927d6975a5ac0e1bb36f5c05356dcda1f521770511ee5e03239c8e1eecf3aed0141045d74feae58c4c36d7c35beac05eddddc78b3ce4b02491a2eea72043978056a8bc439b99ddaad327207b09ef16a8910828e805b0cc8c11fba5caea2ee939346d7ffffffff45c866b219b176952508f8e5aea728f950186554fc4a5807e2186a8e1c4009e5000000008c493046022100bd5d41662f98cfddc46e86ea7e4a3bc8fe9f1dfc5c4836eaf7df582596cfe0e9022100fc459ae4f59b8279d679003b88935896acd10021b6e2e4619377e336b5296c5e014104c00bab76a708ba7064b2315420a1c533ca9945eeff9754cdc574224589e9113469b4e71752146a10028079e04948ecdf70609bf1b9801f6b73ab75947ac339e5ffffffff0200000000"));
 
343
   BinaryData txOut0(h2b("ac4c8bd5000000001976a9148dce8946f1c7763bb60ea5cf16ef514cbed0633b88ac"));
 
344
   BinaryData txOut1(h2b("002f6859000000001976a9146a59ac0e8f553f292dfe5e9f3aaa1da93499c15e88ac"));
 
345
 
 
346
   Tx tx;
 
347
   tx.unserialize(txFull);
 
348
 
 
349
   StoredTx stxFull;
 
350
   StoredTx stxFrag;
 
351
   stxFull.unserialize(txFull, false);
 
352
   stxFrag.unserialize(txFrag, true);
 
353
 
 
354
   assertError(txFull.haveAllTxOut(), "Fragged tx reported having all TxOuts");
 
355
   assertError(!txFrag.haveAllTxOut(), "Full tx reported not having all TxOuts");
 
356
 
 
357
   StoredTxOut stxOut0;
 
358
   StoredTxOut stxOut1;
 
359
   stxOut0.unserialize(txOut0);
 
360
   stxOut1.unserialize(txOut1);
 
361
 
 
362
   stxFrag.txOutMap_[0] = stxOut0;
 
363
   assertError(!txFrag.haveAllTxOut(), "Fragged tx reported having all TxOuts");
 
364
 
 
365
   stxFrag.txOutMap_[1] = stxOut1;
 
366
   assertError(txFrag.haveAllTxOut(), "Frag-but-full tx reported not having all TxOuts");
 
367
 
 
368
   assertError(stxFrag.getSerializedTx()==txFrag, "stxFrag.getSerializedTx() does not match raw");
 
369
   assertError(stxFrag.getSerializedTx()==stxFull.serialize(), "stxFrag.getTxCopy() does not match serialized tx");
 
370
 
 
371
   StoredTx stxFrom1;
 
372
   StoredTx stxFrom2;
 
373
   stxFrom1.createFromTx(tx, false);
 
374
   stxFrom2.createFromTx(tx, true);
 
375
 
 
376
   assertError(stxFrom1.getSerializedTx()==stxFrom2.getSerializedTx(), "Creating from tx failed");
 
377
   assertError(stxFrom1.getSerializedTx()==txFull,  "Creating from tx failed");
 
378
 
 
379
}
 
380
 
 
381
 
 
382
 
 
383
void TestReadAndOrganizeChain(string blkdir)
 
384
{
 
385
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
386
   /////////////////////////////////////////////////////////////////////////////
 
387
   cout << "Reading data from blockchain..." << endl;
 
388
   TIMER_START("BDM_Load_and_Scan_BlkChain");
 
389
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
390
   bdm.parseEntireBlockchain();  
 
391
   TIMER_STOP("BDM_Load_and_Scan_BlkChain");
 
392
   cout << endl << endl;
 
393
 
 
394
   /////////////////////////////////////////////////////////////////////////////
 
395
   // Organizing the chain is always really fast (sub-second), and has now been
 
396
   // removed as an OPTION to the "readBlkFile" methods.  It will be done 
 
397
   // automatically
 
398
   //cout << endl << "Organizing blockchain: " ;
 
399
   //TIMER_START("BDM_Organize_Chain");
 
400
   //bool isGenOnMainChain = bdm.organizeChain();
 
401
   //TIMER_STOP("BDM_Organize_Chain");
 
402
   //cout << (isGenOnMainChain ? "No Reorg!" : "Reorg Detected!") << endl;
 
403
   //cout << endl << endl;
 
404
 
 
405
   /////////////////////////////////////////////////////////////////////////////
 
406
   // TESTNET has some 0.125-difficulty blocks which violates the assumption
 
407
   // that it never goes below 1.  So, need to comment this out for testnet
 
408
   /*  For whatever reason, this doesn't work on testnet...
 
409
   cout << "Verify integrity of blockchain file (merkleroots leading zeros on headers)" << endl;
 
410
   TIMER_START("Verify blk0001.dat integrity");
 
411
   bool isVerified = bdm.verifyBlkFileIntegrity();
 
412
   TIMER_STOP("Verify blk0001.dat integrity");
 
413
   cout << "Done!   Your blkfile " << (isVerified ? "is good!" : " HAS ERRORS") << endl;
 
414
   cout << endl << endl;
 
415
   */
 
416
}
 
417
 
 
418
 
 
419
 
 
420
void TestFindNonStdTx(string blkdir)
 
421
{
 
422
   /*
 
423
   // This is mostly just for debugging...
 
424
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
425
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
426
   bdm.parseEntireBlockchain(); 
 
427
   bdm.findAllNonStdTx();
 
428
   // At one point I had code to print out nonstd txinfo... not sure
 
429
   // what happened to it...
 
430
   */
 
431
}
 
432
 
 
433
 
 
434
 
 
435
void TestScanForWalletTx(string blkdir)
 
436
{
 
437
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
438
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
439
   bdm.parseEntireBlockchain();
 
440
   /////////////////////////////////////////////////////////////////////////////
 
441
   BinaryData myAddress;
 
442
   BtcWallet wlt;
 
443
   
 
444
   // Main-network addresses
 
445
   myAddress.createFromHex("604875c897a079f4db88e5d71145be2093cae194"); wlt.addAddress(myAddress);
 
446
   myAddress.createFromHex("8996182392d6f05e732410de4fc3fa273bac7ee6"); wlt.addAddress(myAddress);
 
447
   myAddress.createFromHex("b5e2331304bc6c541ffe81a66ab664159979125b"); wlt.addAddress(myAddress);
 
448
   myAddress.createFromHex("ebbfaaeedd97bc30df0d6887fd62021d768f5cb8"); wlt.addAddress(myAddress);
 
449
   myAddress.createFromHex("11b366edfc0a8b66feebae5c2e25a7b6a5d1cf31"); wlt.addAddress(myAddress);
 
450
 
 
451
   // This address contains a tx with a non-std TxOut, but the other TxOuts are valid
 
452
   myAddress.createFromHex("6c27c8e67b7376f3ab63553fe37a4481c4f951cf"); wlt.addAddress(myAddress);
 
453
 
 
454
   // More testnet addresses, with only a few transactions
 
455
   myAddress.createFromHex("0c6b92101c7025643c346d9c3e23034a8a843e21"); wlt.addAddress(myAddress);
 
456
   myAddress.createFromHex("34c9f8dc91dfe1ae1c59e76cbe1aa39d0b7fc041"); wlt.addAddress(myAddress);
 
457
   myAddress.createFromHex("d77561813ca968270d5f63794ddb6aab3493605e"); wlt.addAddress(myAddress);
 
458
   myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); wlt.addAddress(myAddress);
 
459
 
 
460
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
 
461
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
 
462
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
 
463
   
 
464
   cout << "Checking balance of all addresses: " << wlt.getNumAddr() << " addrs" << endl;
 
465
   for(uint32_t i=0; i<wlt.getNumAddr(); i++)
 
466
   {
 
467
      BinaryData addr20 = wlt.getAddrByIndex(i).getAddrStr20();
 
468
      cout << "  Addr: " << wlt.getAddrByIndex(i).getFullBalance() << ","
 
469
                         << wlt.getAddrByHash160(addr20).getFullBalance() << endl;
 
470
      vector<LedgerEntry> const & ledger = wlt.getAddrByIndex(i).getTxLedger();
 
471
      for(uint32_t j=0; j<ledger.size(); j++)
 
472
      {  
 
473
         cout << "    Tx: " 
 
474
           << ledger[j].getAddrStr20().getSliceCopy(0,4).toHexStr() << "  "
 
475
           << ledger[j].getValue()/(float)(CONVERTBTC) << " (" 
 
476
           << ledger[j].getBlockNum()
 
477
           << ")  TxHash: " << ledger[j].getTxHash().getSliceCopy(0,4).toHexStr() << endl;
 
478
      }
 
479
 
 
480
   }
 
481
   cout << endl << endl;
 
482
 
 
483
 
 
484
 
 
485
   cout << "Printing SORTED allAddr ledger..." << endl;
 
486
   wlt.sortLedger();
 
487
   vector<LedgerEntry> const & ledgerAll = wlt.getTxLedger();
 
488
   for(uint32_t j=0; j<ledgerAll.size(); j++)
 
489
   {  
 
490
      cout << "    Tx: " 
 
491
           << ledgerAll[j].getAddrStr20().toHexStr() << "  "
 
492
           << ledgerAll[j].getValue()/1e8 << " (" 
 
493
           << ledgerAll[j].getBlockNum()
 
494
           << ")  TxHash: " << ledgerAll[j].getTxHash().getSliceCopy(0,4).toHexStr() << endl;
 
495
           
 
496
   }
 
497
 
 
498
 
 
499
 
 
500
   /////////////////////////////////////////////////////////////////////////////
 
501
   cout << "Test txout aggregation, with different prioritization schemes" << endl;
 
502
   BtcWallet myWallet;
 
503
 
 
504
#ifndef TEST_NETWORK
 
505
   // TODO:  I somehow borked my list of test addresses.  Make sure I have some
 
506
   //        test addresses in here for each network that usually has lots of 
 
507
   //        unspent TxOuts
 
508
   
 
509
   // Main-network addresses
 
510
   myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); myWallet.addAddress(myAddress);
 
511
#else
 
512
   // Testnet addresses
 
513
   //myAddress.createFromHex("d184cea7e82c775d08edd288344bcd663c3f99a2"); myWallet.addAddress(myAddress);
 
514
   //myAddress.createFromHex("205fa00890e6898b987de6ff8c0912805416cf90"); myWallet.addAddress(myAddress);
 
515
   //myAddress.createFromHex("fc0ef58380e6d4bcb9599c5369ce82d0bc01a5c4"); myWallet.addAddress(myAddress);
 
516
#endif
 
517
 
 
518
   cout << "Rescanning the blockchain for new addresses." << endl;
 
519
   bdm.scanBlockchainForTx(myWallet);
 
520
 
 
521
   //vector<UnspentTxOut> sortedUTOs = bdm.getUnspentTxOutsForWallet(myWallet, 1);
 
522
   vector<UnspentTxOut> sortedUTOs = myWallet.getSpendableTxOutList();
 
523
 
 
524
   int i=1;
 
525
   cout << "   Sorting Method: " << i << endl;
 
526
   cout << "   Value\t#Conf\tTxHash\tTxIdx" << endl;
 
527
   for(int j=0; j<sortedUTOs.size(); j++)
 
528
   {
 
529
      cout << "   "
 
530
           << sortedUTOs[j].getValue()/1e8 << "\t"
 
531
           << sortedUTOs[j].getNumConfirm() << "\t"
 
532
           << sortedUTOs[j].getTxHash().toHexStr() << "\t"
 
533
           << sortedUTOs[j].getTxOutIndex() << endl;
 
534
   }
 
535
   cout << endl;
 
536
 
 
537
 
 
538
   // Test the zero-conf ledger-entry detection
 
539
   //le.pprint();
 
540
 
 
541
   //vector<LedgerEntry> levect = wlt.getAddrLedgerEntriesForTx(txSelf);
 
542
   //for(int i=0; i<levect.size(); i++)
 
543
   //{
 
544
      //levect[i].pprint();
 
545
   //}
 
546
   
 
547
 
 
548
}
 
549
 
 
550
 
 
551
void TestReadAndOrganizeChainWithWallet(string blkdir)
 
552
{
 
553
   cout << endl << "Starting blockchain loading with wallets..." << endl;
 
554
   /////////////////////////////////////////////////////////////////////////////
 
555
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
556
   BinaryData myAddress;
 
557
   BtcWallet wlt1;
 
558
   BtcWallet wlt2;
 
559
   
 
560
   // Main-network addresses
 
561
   myAddress.createFromHex("604875c897a079f4db88e5d71145be2093cae194"); wlt2.addAddress(myAddress);
 
562
   myAddress.createFromHex("8996182392d6f05e732410de4fc3fa273bac7ee6"); wlt2.addAddress(myAddress);
 
563
   myAddress.createFromHex("b5e2331304bc6c541ffe81a66ab664159979125b"); wlt2.addAddress(myAddress);
 
564
   myAddress.createFromHex("ebbfaaeedd97bc30df0d6887fd62021d768f5cb8"); wlt2.addAddress(myAddress);
 
565
   myAddress.createFromHex("11b366edfc0a8b66feebae5c2e25a7b6a5d1cf31"); wlt2.addAddress(myAddress);
 
566
   myAddress.createFromHex("e826f4a4381453dcdcf9bfeedffe95de7c86ccbd"); wlt2.addAddress(myAddress);
 
567
 
 
568
   // P2Pool Address
 
569
   myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt1.addAddress(myAddress);
 
570
   
 
571
   // Add some relevant testnet addresses
 
572
   myAddress.createFromHex("0c6b92101c7025643c346d9c3e23034a8a843e21"); wlt2.addAddress(myAddress);
 
573
   myAddress.createFromHex("34c9f8dc91dfe1ae1c59e76cbe1aa39d0b7fc041"); wlt1.addAddress(myAddress);
 
574
   myAddress.createFromHex("d77561813ca968270d5f63794ddb6aab3493605e"); wlt1.addAddress(myAddress);
 
575
   myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); wlt1.addAddress(myAddress);
 
576
 
 
577
   vector<BtcWallet*> wltList;
 
578
   wltList.push_back(&wlt1);
 
579
   wltList.push_back(&wlt2);
 
580
 
 
581
   bdm.registerWallet(&wlt1);
 
582
   bdm.registerWallet(&wlt2);
 
583
 
 
584
 
 
585
   /////////////////////////////////////////////////////////////////////////////
 
586
   cout << "Reading data from blockchain... (with wallet scan)" << endl;
 
587
   TIMER_START("BDM_Load_Scan_Blockchain_With_Wallet");
 
588
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
589
   bdm.parseEntireBlockchain();  
 
590
   TIMER_STOP("BDM_Load_Scan_Blockchain_With_Wallet");
 
591
   cout << endl << endl;
 
592
 
 
593
   /////////////////////////////////////////////////////////////////////////////
 
594
   cout << endl << "Organizing blockchain: " ;
 
595
   TIMER_START("BDM_Organize_Chain");
 
596
   bool isGenOnMainChain = bdm.organizeChain();
 
597
   TIMER_STOP("BDM_Organize_Chain");
 
598
   cout << (isGenOnMainChain ? "No Reorg!" : "Reorg Detected!") << endl;
 
599
   cout << endl << endl;
 
600
 
 
601
   cout << endl << "Updating wallet (1) based on initial blockchain scan" << endl;
 
602
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt1));
 
603
   cout << "Printing Wallet(1) Ledger" << endl;
 
604
   wlt1.pprintLedger();
 
605
 
 
606
   cout << endl << "Updating wallet (2) based on initial blockchain scan" << endl;
 
607
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt2));
 
608
   cout << "Printing Wallet(2) Ledger" << endl;
 
609
   wlt2.pprintLedger();
 
610
 
 
611
   cout << endl << "Rescanning wlt2 multiple times" << endl;
 
612
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt2));
 
613
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt2));
 
614
   cout << "Printing Wallet(2) Ledger AGAIN" << endl;
 
615
   wlt2.pprintLedger();
 
616
 
 
617
 
 
618
   cout << endl << "ADD a new address to Wlt(1) requiring a blockchain rescan..." << endl;
 
619
   // This address contains a tx with a non-std TxOut, but the other TxOuts are valid
 
620
   myAddress.createFromHex("6c27c8e67b7376f3ab63553fe37a4481c4f951cf"); 
 
621
   wlt1.addAddress(myAddress);
 
622
   bdm.scanBlockchainForTx(wlt1);
 
623
   wlt1.pprintLedger();
 
624
   
 
625
   cout << endl << "ADD new address to wlt(2) but as a just-created addr not requiring rescan" << endl;
 
626
   myAddress.createFromHex("6c27c8e67b7376f3ab63553fe37a4481c4f951cf"); 
 
627
   wlt2.addNewAddress(myAddress);
 
628
   bdm.scanBlockchainForTx(wlt2);
 
629
   wlt2.pprintLedger();
 
630
 
 
631
 
 
632
   cout << endl << "Create new, unregistered wallet, scan it once (should rescan)..." << endl;
 
633
   BtcWallet wlt3;
 
634
   myAddress.createFromHex("72e20a94d6b2ed34a3b4d3757c1fed5152071993"); wlt3.addAddress(myAddress);
 
635
   wlt3.addAddress(myAddress);
 
636
   bdm.scanBlockchainForTx(wlt3);
 
637
   wlt3.pprintLedger();
 
638
 
 
639
   
 
640
   cout << endl << "Rescan unregistered wallet: addr should be registered, so no rescan..." << endl;
 
641
   bdm.scanBlockchainForTx(wlt3);
 
642
   wlt3.pprintLedger();
 
643
 
 
644
 
 
645
   cout << endl << endl;
 
646
   cout << "Getting Sent-To Address List for Wlt1:" << endl;
 
647
   vector<AddressBookEntry> targAddrVect = wlt1.createAddressBook();
 
648
   for(uint32_t i=0; i<targAddrVect.size(); i++)
 
649
   {
 
650
      vector<RegisteredTx> txList = targAddrVect[i].getTxList();
 
651
 
 
652
      cout << targAddrVect[i].getAddr160().toHexStr() << " " 
 
653
           << txList.size() << endl;
 
654
      
 
655
      for(uint32_t j=0; j<txList.size(); j++)
 
656
         cout << "   " << txList[j].txHash_.toHexStr()
 
657
              << "   " << txList[j].blkNum_
 
658
              << "   " << txList[j].txIndex_ << endl;
 
659
   }
 
660
 
 
661
 
 
662
   // Results for the sent-to address list, as of 09 Apr, 2012
 
663
   /*
 
664
   "13Tn1QkAcqnQvGA7kBiCBH7NbijNcr6GMs"
 
665
   "17ZqBkFgR6TWawd8rRKbyJAnpTWDWtok72"
 
666
   "12irKW1XFSnnu6v5FevcC3wZ6hfvPmaEDQ"
 
667
   "12Tg96ZPSYc3P2g5c9c4znFFH2whriN9NQ"
 
668
   "1PymCiNzubeTtJt47dqFdi31Zy9MAM1YZk"
 
669
   "1H3Jbv99F7Ng8oiadCovvda17CGZ9EFkPM"
 
670
   "16jN5NhB4eoUqFrSvuNnvDEc57oz6GRNi4"
 
671
   "17aLXn2XHKH7nhwdCPaWmkY6jgr36zSjyz"
 
672
   "1PjURhoxGr6cdK5YY5SyDDY2pQhEpbZdoK"
 
673
   "1NgBFTvqM6FsooFtkvFgf7VxzRBdXKnxpR"
 
674
   "176msrhhemi6q8DEdpBCoTQJvRCiGV5qEm"
 
675
   "16FSHWWyUv6wzT9qpbi7tCaovf6XX7T9xN"
 
676
   "1JiLbGTrVNmk6BsePVQWmBiD7DFUDmMYXw"
 
677
   "124DJWV7vYS8DUcVan4SXcGNAubopS1BHj"
 
678
   "1PESigPSLwsvaQAQfCDDPZM21i9m8Vqt21"
 
679
   "18i1rVZHMMXQwRxZuSrHZrpqUoejkV2Gh2"
 
680
   "1PZjRprkrM93GVXNdJ5zu7C1p84weTovWj"
 
681
   "14cKqt9e8QvgMaBrwbuykBjha1vXNtaj72"
 
682
   "1QJUzen8xL7EyBTGnkDUX6fnoMX9TL1fU7"
 
683
   "17iRBkToUTzDvVpXsNUT8usT6c6aEDe15R"
 
684
   "1NVJS8DWLdrte45rc5oGvWyjrAe9y1rtFt"
 
685
   "1MzxEf2Ck9XSC7U5y5DHQvMyPhL2UNcjSD"
 
686
   "1F7G4aq9fbAhqGb9jcnsVn6CRm6dqJf3sD"
 
687
   "15dYCgedoR1s4y1t5iiKNrRbgHNDize8VW"
 
688
   "15XopyBFQetJzyhE5BbM6WiuYDPeKPNfVP"
 
689
   "1SAD1wfvNCxz23WjEyQMG6fjKsiQx7FFK"
 
690
   "1TaintGh3cPFVGX9REbRk8FXSKTb1pcFZ"
 
691
   "1SAD2i96iGVQvsfhdhEhpi5GeFQpuP4Ye"
 
692
   "1SAD5qJu5UhhXdAZbW7zpjso4ay364W3B"
 
693
   "1SAD7gSBTkhMz5Qaf92SFjUdAsZiE6fq3"
 
694
   "13Sgmy78mfw7ToMiKQujyad9spmPGUZvCN"
 
695
   "1M7bd7iYNuJoFw8F7fGXvz2Fe9cGnhA3P6"
 
696
   */
 
697
 
 
698
   /* Here's the hash160 version of the above list
 
699
   "1b00a2f6899335366f04b277e19d777559c35bc8"
 
700
   "480649dc5fd4448f8c4bf75b3c84bb98ec40b45a"
 
701
   "12e259809932ee8fdab278946911dbd6c6e9e977"
 
702
   "10039ce4fdb5d4ee56148fe3935b9bfbbe4ecc89"
 
703
   "fc0ef58380e6d4bcb9599c5369ce82d0bc01a5c4"
 
704
   "aff189b24a36a1b93de2ea4d157c13d18251270a"
 
705
   "3edbb132f2cd894bc45fee76cfbf13d79fa87bbb"
 
706
   "481ec8e7d30c484ea664824fb7f52b5ae0a99d1d"
 
707
   "f95b21b39dbd7cfe9dd5ef81fe19777707b57f00"
 
708
   "edc36b7309fe440fea79e59c3b50d3969e7fa97d"
 
709
   "42e84bba78b26c2a8917f5cb48493316c3766f88"
 
710
   "39938f166521cbbef621f7c016308fbb428fd9e0"
 
711
   "c24b8bdcba3cb15a7fe95aa99b7ab6ceba5a4c2c"
 
712
   "0b93a48b5ebf29c0e6c7ce53d6701cb4495fc623"
 
713
   "f3dda4c01f89186a012c68607899a5cfd172e408"
 
714
   "548aa5b107b7a5d787c3b21db4fa07ec1cd7b1ec"
 
715
   "f7837ec1fccdbcb1c9848c271468aa9ddf12bf7a"
 
716
   "2796aa497bf2e3d8989319ceff88d1f30300ae36"
 
717
   "ff9955241d540b35fcd429b04e4f59fcfa34580d"
 
718
   "49a5ff7f45c3e2c256adf0615f45f2bbba7a33d3"
 
719
   "ebb4d74391893c08716988c5b9f684275be5966b"
 
720
   "e658556ebd5104f49ea88c27212e8fba71f38e3d"
 
721
   "9ac0d4663bae84fbccfb3f3d887551c075283d7b"
 
722
   "32c985fe4602556cef24b9fd1a35459a0d39e806"
 
723
   "31b4123c92a4aed2d7cfd08edced603dedefcfb7"
 
724
   "04c215b608229b1e71f6314d6973d235fe448c2e"
 
725
   "0506f6a7742b6b4c554ada6c780f7242c85bfdc2"
 
726
   "04c215c2800a1fb2a50f79865bd87a51ae9505c5"
 
727
   "04c215f54c237440e91ebc0e7ed01ecec18d09c0"
 
728
   "04c21613557ce112d0b95a37e08fabf3f8ec96b2"
 
729
   "1acbda75c997d00e2cef09389750708e75433357"
 
730
   "dca1e9baf8d970229f5efa269a15dd420ea7cfab"
 
731
   */
 
732
 
 
733
   BinaryData txHash1 = BinaryData::CreateFromHex("2ec3a745e032c8bcc1061ebf270afcee47318a43462ba57215174084775c794d");
 
734
   BinaryData txHash2 = BinaryData::CreateFromHex("b754fa89f7eb7f7c564611d9297dbcb471cf8d3cb0d235686323b6a5b263b094");
 
735
 
 
736
   if( bdm.getTxRefPtrByHash(txHash1) != NULL &&
 
737
       bdm.getTxRefPtrByHash(txHash2) != NULL)
 
738
   {
 
739
      cout << "Testing soft-scanning..." << endl;
 
740
      LedgerEntry le;
 
741
      le = wlt1.calcLedgerEntryForTx( *bdm.getTxRefPtrByHash(txHash1) ); le.pprintOneLine(); cout << endl;
 
742
      le = wlt2.calcLedgerEntryForTx( *bdm.getTxRefPtrByHash(txHash1) ); le.pprintOneLine(); cout << endl;
 
743
      le = wlt1.calcLedgerEntryForTx( *bdm.getTxRefPtrByHash(txHash2) ); le.pprintOneLine(); cout << endl;
 
744
      le = wlt2.calcLedgerEntryForTx( *bdm.getTxRefPtrByHash(txHash2) ); le.pprintOneLine(); cout << endl;
 
745
   }
 
746
 
 
747
   //cout << "Num Headers: " << bdm.getNumHeaders() << endl;
 
748
   //cout << "Num Tx:      " << bdm.getNumTx() << endl;
 
749
  
 
750
}
 
751
 
 
752
void TestBalanceConstruction(string blkdir)
 
753
{
 
754
   cout << endl << "Starting blockchain loading with wallets..." << endl;
 
755
   /////////////////////////////////////////////////////////////////////////////
 
756
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
757
   BinaryData myAddress;
 
758
   BtcWallet wlt;
 
759
   
 
760
   // Main-network addresses
 
761
   // I do not remember anymore what any of these addresses were for ...
 
762
   // All I know is they probably have some tx history..
 
763
   //myAddress.createFromHex("604875c897a079f4db88e5d71145be2093cae194"); wlt.addAddress(myAddress);
 
764
   //myAddress.createFromHex("8996182392d6f05e732410de4fc3fa273bac7ee6"); wlt.addAddress(myAddress);
 
765
   //myAddress.createFromHex("b5e2331304bc6c541ffe81a66ab664159979125b"); wlt.addAddress(myAddress);
 
766
   //myAddress.createFromHex("ebbfaaeedd97bc30df0d6887fd62021d768f5cb8"); wlt.addAddress(myAddress);
 
767
   //myAddress.createFromHex("11b366edfc0a8b66feebae5c2e25a7b6a5d1cf31"); wlt.addAddress(myAddress);
 
768
   //myAddress.createFromHex("e826f4a4381453dcdcf9bfeedffe95de7c86ccbd"); wlt.addAddress(myAddress);
 
769
 
 
770
   // P2Pool Address
 
771
   myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt.addAddress(myAddress);
 
772
 
 
773
   // Add some relevant testnet addresses
 
774
   //myAddress.createFromHex("0c6b92101c7025643c346d9c3e23034a8a843e21"); wlt.addAddress(myAddress);
 
775
   //myAddress.createFromHex("34c9f8dc91dfe1ae1c59e76cbe1aa39d0b7fc041"); wlt.addAddress(myAddress);
 
776
   //myAddress.createFromHex("d77561813ca968270d5f63794ddb6aab3493605e"); wlt.addAddress(myAddress);
 
777
   //myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); wlt.addAddress(myAddress);
 
778
 
 
779
   // These two addresses were used at one point for testing unconfirmed balances
 
780
   myAddress.createFromHex("8c61f6a7558af399e404d82beddcc4692db7b30f"); wlt.addAddress(myAddress);
 
781
   myAddress.createFromHex("14445409283ef413f5fb004338377bf042064922"); wlt.addAddress(myAddress);
 
782
 
 
783
   bdm.registerWallet(&wlt);
 
784
 
 
785
 
 
786
   /////////////////////////////////////////////////////////////////////////////
 
787
   cout << "Reading data from blockchain... (with wallet scan)" << endl;
 
788
   TIMER_START("BDM_Load_Scan_Blockchain_With_Wallet");
 
789
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
790
   bdm.parseEntireBlockchain();  
 
791
   TIMER_STOP("BDM_Load_Scan_Blockchain_With_Wallet");
 
792
   cout << endl << endl;
 
793
 
 
794
 
 
795
   cout << endl << "Scanning wallet tx based on initial blockchain scan" << endl;
 
796
   TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
 
797
   cout << "Printing Wallet Ledger" << endl;
 
798
   wlt.pprintLedger();
 
799
 
 
800
 
 
801
   // We want to check the memory pool transactions...
 
802
   string mempool("C:/Users/VBox/AppData/Roaming/Armory/mempool.bin");
 
803
   bdm.enableZeroConf(mempool);
 
804
   bdm.scanBlockchainForTx(wlt);
 
805
 
 
806
   uint32_t topBlk = bdm.getTopBlockHeight();
 
807
   uint64_t balFul = wlt.getFullBalance();
 
808
   uint64_t balSpd = wlt.getSpendableBalance(topBlk);
 
809
   uint64_t balUnc = wlt.getUnconfirmedBalance(topBlk);
 
810
 
 
811
   vector<UnspentTxOut> utxoF = wlt.getFullTxOutList(topBlk);
 
812
   vector<UnspentTxOut> utxoS = wlt.getSpendableTxOutList(topBlk);
 
813
   cout << "FULL:" << endl;
 
814
   for(uint32_t i=0; i<utxoF.size(); i++)
 
815
      utxoF[i].pprintOneLine(topBlk);
 
816
 
 
817
   cout << "SPENDABLE:" << endl;
 
818
   for(uint32_t i=0; i<utxoS.size(); i++)
 
819
      utxoS[i].pprintOneLine(topBlk);
 
820
}
 
821
 
 
822
void TestReadAndUpdateBlkFile(string tempBlkDir)
 
823
{
 
824
 
 
825
   string blk3  = pathJoin(tempBlkDir, "blk0003.dat");
 
826
   string blk3s = pathJoin(tempBlkDir, "blk0003sm.dat");
 
827
   string blk3b = pathJoin(tempBlkDir, "blk0003big.dat");
 
828
   string blk3g = pathJoin(tempBlkDir, "blk0003bigger.dat");
 
829
   string blk4  = pathJoin(tempBlkDir, "blk0004.dat");
 
830
   string blk4s = pathJoin(tempBlkDir, "blk0004sm.dat");
 
831
   string blk5  = pathJoin(tempBlkDir, "blk0005.dat");
 
832
   string blk5s = pathJoin(tempBlkDir, "blk0005sm.dat");
 
833
   uint32_t nblk;
 
834
 
 
835
   // Clean up from the previous run
 
836
   copyFile(blk3s,  blk3);
 
837
   if( BtcUtils::GetFileSize(blk4) != FILE_DOES_NOT_EXIST ) 
 
838
      remove(blk4.c_str());
 
839
   if( BtcUtils::GetFileSize(blk5) != FILE_DOES_NOT_EXIST ) 
 
840
      remove(blk5.c_str());
 
841
 
 
842
 
 
843
   // The newblk directory has a blk0003.dat file with one more block
 
844
   // and blk0004.dat file with 4 more blocks
 
845
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
846
   bdm.SetBlkFileLocation(tempBlkDir, 4, 1);
 
847
   bdm.parseEntireBlockchain();  
 
848
 
 
849
   // Test standard blkfile expansion
 
850
   copyFile(blk3b, blk3);
 
851
   nblk = bdm.readBlkFileUpdate();
 
852
   cout << "New Blocks Read: " << nblk << endl;
 
853
 
 
854
   // Test both blkfile expansion and splitting
 
855
   copyFile(blk3g, blk3);
 
856
   copyFile(blk4s, blk4);
 
857
   nblk = bdm.readBlkFileUpdate();
 
858
   cout << "New Blocks Read: " << nblk << endl;
 
859
 
 
860
 
 
861
   // Test just blockfile splitting
 
862
   copyFile(blk5s, blk5);
 
863
   nblk = bdm.readBlkFileUpdate();
 
864
   cout << "New Blocks Read: " << nblk << endl;
 
865
 
 
866
}
 
867
 
 
868
void TestReorgBlockchain(string blkdir)
 
869
{
 
870
   // June, 2012:  The reorg test compiled&worked up until I changed everything
 
871
   //              to FileDataPtrs, and now I don't have a good way to force 
 
872
   //              different blk files (because I auto-detect blkfiles...)
 
873
   //              Will revive this when I figure it out...
 
874
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
875
   /////////////////////////////////////////////////////////////////////////////
 
876
   //
 
877
   // BLOCKCHAIN REORGANIZATION UNIT-TEST
 
878
   //
 
879
   /////////////////////////////////////////////////////////////////////////////
 
880
   //
 
881
   // NOTE:  The unit-test files (blk_0_to_4, blk_3A, etc) are located in 
 
882
   //        cppForSwig/reorgTest.  These files represent a very small 
 
883
   //        blockchain with a double-spend and a couple invalidated 
 
884
   //        coinbase tx's.  All tx-hashes & OutPoints are consistent,
 
885
   //        all transactions have real ECDSA signatures, and blockheaders
 
886
   //        have four leading zero-bytes to be valid at difficulty=1
 
887
   //        
 
888
   //        If you were to set COINBASE_MATURITY=1 (not applicable here)
 
889
   //        this would be a *completely valid* blockchain--just a very 
 
890
   //        short blockchain.
 
891
   //
 
892
   //        FYI: The first block is the *actual* main-network genesis block
 
893
   //
 
894
   string blk04("reorgTest/blk_0_to_4.dat");
 
895
   string blk3A("reorgTest/blk_3A.dat");
 
896
   string blk4A("reorgTest/blk_4A.dat");
 
897
   string blk5A("reorgTest/blk_5A.dat");
 
898
 
 
899
   BtcWallet wlt;
 
900
   wlt.addAddress(BinaryData::CreateFromHex("62e907b15cbf27d5425399ebf6f0fb50ebb88f18"));
 
901
   wlt.addAddress(BinaryData::CreateFromHex("ee26c56fc1d942be8d7a24b2a1001dd894693980"));
 
902
   wlt.addAddress(BinaryData::CreateFromHex("cb2abde8bccacc32e893df3a054b9ef7f227a4ce"));
 
903
   wlt.addAddress(BinaryData::CreateFromHex("c522664fb0e55cdc5c0cea73b4aad97ec8343232"));
 
904
 
 
905
                   
 
906
   cout << endl << endl;
 
907
   cout << "Preparing blockchain-reorganization test!" << endl;
 
908
   cout << "Resetting block-data mgr...";
 
909
   bdm.Reset();
 
910
   cout << "Done!" << endl;
 
911
   cout << "Reading in initial block chain (Blocks 0 through 4)..." ;
 
912
 
 
913
   copyFile(blk04, "reorgTest/blk00000.dat");
 
914
   bdm.SetBlkFileLocation("reorgTest", 5, 0);
 
915
   bdm.parseEntireBlockchain();
 
916
   bdm.organizeChain();
 
917
   cout << "Done" << endl;
 
918
 
 
919
   // TODO: Let's look at the address ledger after the first chain
 
920
   //       Then look at it again after the reorg.  What we want
 
921
   //       to see is the presence of an invalidated tx, not just
 
922
   //       a disappearing tx -- the user must be informed that a 
 
923
   //       tx they previously thought they owned is now invalid.
 
924
   //       If the user is not informed, they could go crazy trying
 
925
   //       to figure out what happened to this money they thought
 
926
   //       they had.
 
927
   cout << "Constructing address ledger for the to-be-invalidated chain:" << endl;
 
928
   bdm.scanBlockchainForTx(wlt);
 
929
   vector<LedgerEntry> const & ledgerAll2 = wlt.getTxLedger();
 
930
   for(uint32_t j=0; j<ledgerAll2.size(); j++)
 
931
   {  
 
932
      cout << "    Tx: " 
 
933
           << ledgerAll2[j].getValue()/1e8
 
934
           << " (" << ledgerAll2[j].getBlockNum() << ")"
 
935
           << "  TxHash: " << ledgerAll2[j].getTxHash().getSliceCopy(0,4).toHexStr();
 
936
      if(!ledgerAll2[j].isValid())      cout << " (INVALID) ";
 
937
      if( ledgerAll2[j].isSentToSelf()) cout << " (SENT_TO_SELF) ";
 
938
      if( ledgerAll2[j].isChangeBack()) cout << " (RETURNED CHANGE) ";
 
939
      cout << endl;
 
940
   }
 
941
   cout << "Checking balance of all addresses: " << wlt.getNumAddr() << "addrs" << endl;
 
942
   cout << "                          Balance: " << wlt.getFullBalance()/1e8 << endl;
 
943
   for(uint32_t i=0; i<wlt.getNumAddr(); i++)
 
944
   {
 
945
      BinaryData addr20 = wlt.getAddrByIndex(i).getAddrStr20();
 
946
      cout << "  Addr: " << wlt.getAddrByIndex(i).getFullBalance()/1e8 << ","
 
947
                         << wlt.getAddrByHash160(addr20).getFullBalance() << endl;
 
948
      vector<LedgerEntry> const & ledger = wlt.getAddrByIndex(i).getTxLedger();
 
949
      for(uint32_t j=0; j<ledger.size(); j++)
 
950
      {  
 
951
         cout << "    Tx: " 
 
952
              << ledger[j].getAddrStr20().getSliceCopy(0,4).toHexStr() << "  "
 
953
              << ledger[j].getValue()/(float)(CONVERTBTC) << " (" 
 
954
              << ledger[j].getBlockNum()
 
955
              << ")  TxHash: " << ledger[j].getTxHash().getSliceCopy(0,4).toHexStr();
 
956
         if( ! ledger[j].isValid())  cout << " (INVALID) ";
 
957
         cout << endl;
 
958
      }
 
959
 
 
960
   }
 
961
 
 
962
   // prepare the other block to be read in
 
963
   vector<bool> result;
 
964
 
 
965
   /////
 
966
   cout << "Pushing Block 3A into the BDM:" << endl;
 
967
   copyFile(blk3A, "reorgTest/blk00000.dat");
 
968
   bdm.readBlkFileUpdate();
 
969
   cout << "Is last block reorg? " << (bdm.isLastBlockReorg() ? 1 : 0) << endl;
 
970
 
 
971
   /////
 
972
   cout << "Pushing Block 4A into the BDM:" << endl;
 
973
   copyFile(blk4A, "reorgTest/blk00000.dat");
 
974
   bdm.readBlkFileUpdate();
 
975
   cout << "Is last block reorg? " << (bdm.isLastBlockReorg() ? 1 : 0) << endl;
 
976
 
 
977
   /////
 
978
   cout << "Pushing Block 5A into the BDM:" << endl;
 
979
   copyFile(blk5A, "reorgTest/blk00000.dat");
 
980
   bdm.readBlkFileUpdate();
 
981
   cout << "Is last block reorg? " << (bdm.isLastBlockReorg() ? 1 : 0) << endl;
 
982
   if(bdm.isLastBlockReorg())
 
983
   {
 
984
      cout << "Reorg happened after pushing block 5A" << endl;
 
985
      bdm.scanBlockchainForTx(wlt);
 
986
      bdm.updateWalletAfterReorg(wlt);
 
987
   }
 
988
 
 
989
   cout << "Checking balance of entire wallet: " << wlt.getFullBalance()/1e8 << endl;
 
990
   vector<LedgerEntry> const & ledgerAll3 = wlt.getTxLedger();
 
991
   for(uint32_t j=0; j<ledgerAll3.size(); j++)
 
992
   {  
 
993
      cout << "    Tx: " 
 
994
           << ledgerAll3[j].getValue()/1e8
 
995
           << " (" << ledgerAll3[j].getBlockNum() << ")"
 
996
           << "  TxHash: " << ledgerAll3[j].getTxHash().getSliceCopy(0,4).toHexStr();
 
997
      if(!ledgerAll3[j].isValid())      cout << " (INVALID) ";
 
998
      if( ledgerAll3[j].isSentToSelf()) cout << " (SENT_TO_SELF) ";
 
999
      if( ledgerAll3[j].isChangeBack()) cout << " (RETURNED CHANGE) ";
 
1000
      cout << endl;
 
1001
   }
 
1002
 
 
1003
   cout << "Checking balance of all addresses: " << wlt.getNumAddr() << "addrs" << endl;
 
1004
   for(uint32_t i=0; i<wlt.getNumAddr(); i++)
 
1005
   {
 
1006
      BinaryData addr20 = wlt.getAddrByIndex(i).getAddrStr20();
 
1007
      cout << "  Addr: " << wlt.getAddrByIndex(i).getFullBalance()/1e8 << ","
 
1008
                         << wlt.getAddrByHash160(addr20).getFullBalance()/1e8 << endl;
 
1009
      vector<LedgerEntry> const & ledger = wlt.getAddrByIndex(i).getTxLedger();
 
1010
      for(uint32_t j=0; j<ledger.size(); j++)
 
1011
      {  
 
1012
         cout << "    Tx: " 
 
1013
              << ledger[j].getAddrStr20().getSliceCopy(0,4).toHexStr() << "  "
 
1014
              << ledger[j].getValue()/(float)(CONVERTBTC) << " (" 
 
1015
              << ledger[j].getBlockNum()
 
1016
              << ")  TxHash: " << ledger[j].getTxHash().getSliceCopy(0,4).toHexStr();
 
1017
         if( ! ledger[j].isValid())
 
1018
            cout << " (INVALID) ";
 
1019
         cout << endl;
 
1020
      }
 
1021
 
 
1022
   }
 
1023
   /////////////////////////////////////////////////////////////////////////////
 
1024
   //
 
1025
   // END BLOCKCHAIN REORG UNIT-TEST
 
1026
   //
 
1027
   /////////////////////////////////////////////////////////////////////////////
 
1028
  
 
1029
 
 
1030
}
 
1031
 
 
1032
 
 
1033
void TestZeroConf(void)
 
1034
{
 
1035
 
 
1036
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
1037
   BinaryData myAddress;
 
1038
   BtcWallet wlt;
 
1039
   /*
 
1040
   bdm.Reset();
 
1041
   bdm.SetBlkFileLocation("zctest/blk0001.dat", 4, 1);
 
1042
   bdm.parseEntireBlockchain();
 
1043
 
 
1044
   // More testnet addresses, with only a few transactions
 
1045
   myAddress.createFromHex("4c98e1fb7aadce864b310b2e52b685c09bdfd5e7"); wlt.addAddress(myAddress);
 
1046
   myAddress.createFromHex("08ccdf1ef9269b95f6ce93899ece9f68cd5afb22"); wlt.addAddress(myAddress);
 
1047
   myAddress.createFromHex("edf6bbd7ba7aad222c2b28e6d8d5001178e3680c"); wlt.addAddress(myAddress);
 
1048
   myAddress.createFromHex("18d9cae7ee0be5c6d58f02a992442d2cdb9914fa"); wlt.addAddress(myAddress);
 
1049
 
 
1050
   bdm.scanBlockchainForTx(wlt);
 
1051
 
 
1052
   bdm.enableZeroConf("zctest/mempool_new.bin");
 
1053
   uint32_t currBlk = bdm.getTopBlockHeader().getBlockHeight();
 
1054
 
 
1055
   ifstream zcIn("zctest/mempool.bin", ios::in | ios::binary);
 
1056
   zcIn.seekg(0, ios::end);
 
1057
   uint64_t filesize = (size_t)zcIn.tellg();
 
1058
   zcIn.seekg(0, ios::beg);
 
1059
 
 
1060
   BinaryData memPool(filesize);
 
1061
   zcIn.read((char*)memPool.getPtr(), filesize);
 
1062
 
 
1063
   BinaryRefReader brr(memPool);
 
1064
   cout << "Starting Wallet:" << endl;
 
1065
   bdm.rescanWalletZeroConf(wlt);
 
1066
   wlt.pprintLedger();
 
1067
   while(brr.getSizeRemaining() > 8)
 
1068
   {
 
1069
      cout << endl << endl;
 
1070
      cout << "Inserting another 0-conf tx..." << endl;
 
1071
      uint64_t txtime = brr.get_uint64_t();
 
1072
      TxRef zcTx(brr);
 
1073
      bool wasAdded = bdm.addNewZeroConfTx(zcTx.serialize(), txtime, true);
 
1074
 
 
1075
      if(wasAdded)
 
1076
         bdm.rescanWalletZeroConf(wlt);
 
1077
 
 
1078
      cout << "UltBal: " << wlt.getFullBalance() << endl;
 
1079
      cout << "SpdBal: " << wlt.getSpendableBalance() << endl;
 
1080
      cout << "UncBal: " << wlt.getUnconfirmedBalance(currBlk) << endl;
 
1081
      wlt.pprintLedger();
 
1082
 
 
1083
      cout << "Unspent TxOuts:" << endl;
 
1084
      vector<UnspentTxOut> utxoList = wlt.getSpendableTxOutList(currBlk);
 
1085
      uint64_t bal = 0;
 
1086
      for(uint32_t i=0; i<utxoList.size(); i++)
 
1087
      {
 
1088
         bal += utxoList[i].getValue();
 
1089
         utxoList[i].pprintOneLine(currBlk);
 
1090
      }
 
1091
      cout << "Sum of TxOuts: " << bal/1e8 << endl;
 
1092
   }
 
1093
   */
 
1094
 
 
1095
   /*  Not only does this test not work anymore (due to FileDataPtr updates),
 
1096
    *  I appear to have lost my carefully-constructed zctest directory since
 
1097
    *  I ran this last... :(
 
1098
   ifstream is("zctest/mempool_new.bin", ios::in  | ios::binary);
 
1099
   ofstream os("zctest/mempool.bin",     ios::out | ios::binary);
 
1100
   is.seekg(0, ios::end);
 
1101
   uint64_t filesize = (size_t)is.tellg();
 
1102
   is.seekg(0, ios::beg);
 
1103
   BinaryData mempool(filesize);
 
1104
   is.read ((char*)mempool.getPtr(), filesize);
 
1105
   os.write((char*)mempool.getPtr(), filesize);
 
1106
   is.close();
 
1107
   os.close();
 
1108
 
 
1109
   ////////////////////////////////////////////////////////////////////////////
 
1110
   ////////////////////////////////////////////////////////////////////////////
 
1111
   // Start testing balance/wlt update after a new block comes in
 
1112
 
 
1113
   bdm.Reset();
 
1114
   bdm.SetBlkFileLocation("zctest/blk0001.dat", 4, 1);
 
1115
   bdm.parseEntireBlockchain();
 
1116
   // More testnet addresses, with only a few transactions
 
1117
   wlt = BtcWallet();
 
1118
   myAddress.createFromHex("4c98e1fb7aadce864b310b2e52b685c09bdfd5e7"); wlt.addAddress(myAddress);
 
1119
   myAddress.createFromHex("08ccdf1ef9269b95f6ce93899ece9f68cd5afb22"); wlt.addAddress(myAddress);
 
1120
   myAddress.createFromHex("edf6bbd7ba7aad222c2b28e6d8d5001178e3680c"); wlt.addAddress(myAddress);
 
1121
   myAddress.createFromHex("18d9cae7ee0be5c6d58f02a992442d2cdb9914fa"); wlt.addAddress(myAddress);
 
1122
   uint32_t topBlk = bdm.getTopBlockHeader().getBlockHeight();
 
1123
 
 
1124
   // This will load the memory pool into the zeroConfPool_ in BDM
 
1125
   bdm.enableZeroConf("zctest/mempool.bin");
 
1126
 
 
1127
   // Now scan all transactions, which ends with scanning zero-conf
 
1128
   bdm.scanBlockchainForTx(wlt);
 
1129
 
 
1130
   wlt.pprintAlot(topBlk, true);
 
1131
 
 
1132
   // The new blkfile has about 10 new blocks, one of which has these tx
 
1133
   bdm.readBlkFileUpdate("zctest/blk0001_updated.dat");
 
1134
   bdm.scanBlockchainForTx(wlt, topBlk);
 
1135
   topBlk = bdm.getTopBlockHeader().getBlockHeight();
 
1136
   wlt.pprintAlot(topBlk, true);
 
1137
   */
 
1138
 
 
1139
}
 
1140
 
 
1141
   
 
1142
void TestMerkle(void)
 
1143
{
 
1144
   vector<BinaryData> txList(7);
 
1145
   // The "abcd" quartets are to trigger endianness errors -- without them,
 
1146
   // these hashes are palindromes that work regardless of your endian-handling
 
1147
   txList[0].createFromHex("00000000000000000000000000000000000000000000000000000000abcd0000");
 
1148
   txList[1].createFromHex("11111111111111111111111111111111111111111111111111111111abcd1111");
 
1149
   txList[2].createFromHex("22222222222222222222222222222222222222222222222222222222abcd2222");
 
1150
   txList[3].createFromHex("33333333333333333333333333333333333333333333333333333333abcd3333");
 
1151
   txList[4].createFromHex("44444444444444444444444444444444444444444444444444444444abcd4444");
 
1152
   txList[5].createFromHex("55555555555555555555555555555555555555555555555555555555abcd5555");
 
1153
   txList[6].createFromHex("66666666666666666666666666666666666666666666666666666666abcd6666");
 
1154
 
 
1155
   cout << "Merkle Tree looks like the following (7 tx): " << endl;
 
1156
   cout << "The ** indicates the nodes we care about for partial tree test" << endl;
 
1157
   cout << "                                                    \n";
 
1158
   cout << "                   _____0a10_____                   \n";
 
1159
   cout << "                  /              \\                  \n";
 
1160
   cout << "                _/                \\_                \n";
 
1161
   cout << "            65df                    b4d6            \n";
 
1162
   cout << "          /      \\                /      \\          \n";
 
1163
   cout << "      6971        22dc        5675        d0b6      \n";
 
1164
   cout << "     /    \\      /    \\      /    \\      /          \n";
 
1165
   cout << "   0000  1111  2222  3333  4444  5555  6666         \n";
 
1166
   cout << "    **                            **                \n";
 
1167
   cout << "    " << endl;
 
1168
   cout << endl;
 
1169
 
 
1170
   vector<BinaryData> merkleTree = BtcUtils::calculateMerkleTree(txList); 
 
1171
 
 
1172
   cout << "Full Merkle Tree (this one has been unit tested before):" << endl;
 
1173
   for(uint32_t i=0; i<merkleTree.size(); i++)
 
1174
      cout << "    " << i << " " << merkleTree[i].toHexStr() << endl;
 
1175
 
 
1176
   /////////////////////////////////////////////////////////////////////////////
 
1177
   vector<bool> isOurs(7);
 
1178
   isOurs[0] = true;
 
1179
   isOurs[1] = true;
 
1180
   isOurs[2] = true;
 
1181
   isOurs[3] = true;
 
1182
   isOurs[4] = true;
 
1183
   isOurs[5] = true;
 
1184
   isOurs[6] = true;
 
1185
 
 
1186
   cout << "Start serializing a full tree" << endl;
 
1187
   PartialMerkleTree pmtFull(7, &isOurs, &txList);
 
1188
   BinaryData pmtSerFull = pmtFull.serialize();
 
1189
 
 
1190
   cout << "Finished serializing (full)" << endl;
 
1191
   cout << "Merkle Root: " << pmtFull.getMerkleRoot().toHexStr() << endl;
 
1192
 
 
1193
   cout << "Starting unserialize (full):" << endl;
 
1194
   cout << "Serialized: " << pmtSerFull.toHexStr() << endl;
 
1195
   PartialMerkleTree pmtFull2(7);
 
1196
   pmtFull2.unserialize(pmtSerFull);
 
1197
   BinaryData pmtSerFull2 = pmtFull2.serialize();
 
1198
   cout << "Reserializ: " << pmtSerFull2.toHexStr() << endl;
 
1199
   cout << "Equal? " << (pmtSerFull==pmtSerFull2 ? "True" : "False") << endl;
 
1200
 
 
1201
   cout << "Print Tree:" << endl;
 
1202
   pmtFull2.pprintTree();
 
1203
 
 
1204
 
 
1205
   /////////////////////////////////////////////////////////////////////////////
 
1206
   cout << "Starting Partial Merkle tree" << endl;
 
1207
   isOurs[0] = true;
 
1208
   isOurs[1] = false;
 
1209
   isOurs[2] = false;
 
1210
   isOurs[3] = false;
 
1211
   isOurs[4] = false;
 
1212
   isOurs[5] = true;
 
1213
   isOurs[6] = false;
 
1214
 
 
1215
   PartialMerkleTree pmt(7, &isOurs, &txList);
 
1216
   cout << "Serializing (partial)" << endl;
 
1217
   BinaryData pmtSer = pmt.serialize();
 
1218
   PartialMerkleTree pmt2(7);
 
1219
   cout << "Unserializing (partial)" << endl;
 
1220
   pmt2.unserialize(pmtSer);
 
1221
   cout << "Reserializing (partial)" << endl;
 
1222
   BinaryData pmtSer2 = pmt2.serialize();
 
1223
   cout << "Serialized (Partial): " << pmtSer.toHexStr() << endl;
 
1224
   cout << "Reserializ (Partial): " << pmtSer.toHexStr() << endl;
 
1225
   cout << "Equal? " << (pmtSer==pmtSer2 ? "True" : "False") << endl;
 
1226
 
 
1227
   cout << "Print Tree:" << endl;
 
1228
   pmt2.pprintTree();
 
1229
 
 
1230
   /////////////////////////////////////////////////////////////////////////////
 
1231
   cout << "Empty tree" << endl;
 
1232
   isOurs[0] = false;
 
1233
   isOurs[1] = false;
 
1234
   isOurs[2] = false;
 
1235
   isOurs[3] = false;
 
1236
   isOurs[4] = false;
 
1237
   isOurs[5] = false;
 
1238
   isOurs[6] = false;
 
1239
 
 
1240
   PartialMerkleTree pmt3(7, &isOurs, &txList);
 
1241
   cout << "Serializing (partial)" << endl;
 
1242
   BinaryData pmtSer3 = pmt3.serialize();
 
1243
   PartialMerkleTree pmt4(7);
 
1244
   cout << "Unserializing (partial)" << endl;
 
1245
   pmt4.unserialize(pmtSer3);
 
1246
   cout << "Reserializing (partial)" << endl;
 
1247
   BinaryData pmtSer4 = pmt4.serialize();
 
1248
   cout << "Equal? " << (pmtSer3==pmtSer4 ? "True" : "False") << endl;
 
1249
   cout << "Empty Serialized: " << pmtSer3.toHexStr() << endl;
 
1250
   cout << "Print Tree:" << endl;
 
1251
   pmt4.pprintTree();
 
1252
 
 
1253
 
 
1254
   /////////////////////////////////////////////////////////////////////////////
 
1255
   cout << "Single Node on edge" << endl;
 
1256
   isOurs[0] = false;
 
1257
   isOurs[1] = false;
 
1258
   isOurs[2] = false;
 
1259
   isOurs[3] = false;
 
1260
   isOurs[4] = false;
 
1261
   isOurs[5] = false;
 
1262
   isOurs[6] = true;
 
1263
   PartialMerkleTree pmt5(7, &isOurs, &txList);
 
1264
   cout << "Serializing (partial)" << endl;
 
1265
   BinaryData pmtSer5 = pmt5.serialize();
 
1266
   PartialMerkleTree pmt6(7);
 
1267
   cout << "Unserializing (partial)" << endl;
 
1268
   pmt6.unserialize(pmtSer5);
 
1269
   cout << "Reserializing (partial)" << endl;
 
1270
   BinaryData pmtSer6 = pmt6.serialize();
 
1271
   cout << "Equal? " << (pmtSer5==pmtSer6 ? "True" : "False") << endl;
 
1272
   cout << "Single Serialized: " << pmtSer5.toHexStr() << endl;
 
1273
   cout << "Print Tree:" << endl;
 
1274
   pmt6.pprintTree();
 
1275
 
 
1276
   cout << "Four Tests: " << endl;
 
1277
   cout << "   " << (pmtSerFull==pmtSerFull2 ? "PASS" : "FAIL") << endl;
 
1278
   cout << "   " << (pmtSer==pmtSer2 ? "PASS" : "FAIL") << endl;
 
1279
   cout << "   " << (pmtSer3==pmtSer4 ? "PASS" : "FAIL") << endl;
 
1280
   cout << "   " << (pmtSer5==pmtSer6 ? "PASS" : "FAIL") << endl;
 
1281
 
 
1282
 
 
1283
   cout << "Super large merkle tree!" << endl;
 
1284
   uint32_t testSize = 100000;
 
1285
   vector<HashString> longHash(testSize);
 
1286
   vector<bool>       longBits(testSize);
 
1287
   for(uint32_t i=0; i<testSize; i++)
 
1288
   {
 
1289
      // Create 100,000 simple hashes
 
1290
      longHash[i] = BinaryData(32);
 
1291
      *(uint32_t*)(longHash[i].getPtr()+28) = i;
 
1292
   
 
1293
      longBits[i] = ((i%(testSize/13-1))==0);
 
1294
   }
 
1295
 
 
1296
   TIMER_START("Create 100000 Merkle Tree");
 
1297
   PartialMerkleTree pmtLong(testSize, &longBits, &longHash);
 
1298
   TIMER_STOP("Create 100000 Merkle Tree");
 
1299
 
 
1300
   TIMER_START("Serialize 100000 Merkle Tree");
 
1301
   BinaryData longSer = pmtLong.serialize();
 
1302
   TIMER_STOP("Serialize 100000 Merkle Tree");
 
1303
 
 
1304
   PartialMerkleTree pmtLong2(testSize);
 
1305
 
 
1306
   TIMER_START("Unserialize 100000 Merkle Tree");
 
1307
   pmtLong2.unserialize(longSer);
 
1308
   TIMER_STOP("Unserialize 100000 Merkle Tree");
 
1309
 
 
1310
   
 
1311
   cout << endl;
 
1312
   cout << "Size of original transaction list: " 
 
1313
        << BtcUtils::numToStrWCommas(testSize*32) << endl;
 
1314
   cout << "Size of partial merkle tree list:  " 
 
1315
        << BtcUtils::numToStrWCommas(longSer.getSize()) << endl;
 
1316
   
 
1317
 
 
1318
}
 
1319
 
 
1320
 
 
1321
void TestCrypto(void)
 
1322
{
 
1323
 
 
1324
   SecureBinaryData a("aaaaaaaaaa");
 
1325
   SecureBinaryData b; b.resize(5);
 
1326
   SecureBinaryData c; c.resize(0);
 
1327
 
 
1328
   a.copyFrom(b);
 
1329
   b.copyFrom(c);
 
1330
   c.copyFrom(a);
 
1331
 
 
1332
   a.resize(0);
 
1333
   b = a;
 
1334
   SecureBinaryData d(a); 
 
1335
 
 
1336
   cout << "a=" << a.toHexStr() << endl;
 
1337
   cout << "b=" << b.toHexStr() << endl;
 
1338
   cout << "c=" << c.toHexStr() << endl;
 
1339
   cout << "d=" << d.toHexStr() << endl;
 
1340
 
 
1341
   SecureBinaryData e("eeeeeeeeeeeeeeee");
 
1342
   SecureBinaryData f("ffffffff");
 
1343
   SecureBinaryData g(0);
 
1344
 
 
1345
   e = g.copy();
 
1346
   e = f.copy();
 
1347
 
 
1348
   cout << "e=" << e.toHexStr() << endl;
 
1349
   cout << "f=" << f.toHexStr() << endl;
 
1350
   cout << "g=" << g.toHexStr() << endl;
 
1351
   
 
1352
   
 
1353
 
 
1354
   /////////////////////////////////////////////////////////////////////////////
 
1355
   // Start Key-Derivation-Function (KDF) Tests.  
 
1356
   // ROMIX is the provably memory-hard (GPU-resistent) algorithm proposed by 
 
1357
   // Colin Percival, who is the creator of Scrypt.  
 
1358
   cout << endl << endl;
 
1359
   cout << "Executing Key-Derivation-Function (KDF) tests" << endl;
 
1360
   KdfRomix kdf;  
 
1361
   kdf.computeKdfParams();
 
1362
   kdf.printKdfParams();
 
1363
 
 
1364
   SecureBinaryData passwd1("This is my first password");
 
1365
   SecureBinaryData passwd2("This is my first password.");
 
1366
   SecureBinaryData passwd3("This is my first password");
 
1367
   SecureBinaryData key;
 
1368
 
 
1369
   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
 
1370
   key = kdf.DeriveKey(passwd1);
 
1371
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1372
 
 
1373
   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
 
1374
   key = kdf.DeriveKey(passwd2);
 
1375
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1376
 
 
1377
   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
 
1378
   key = kdf.DeriveKey(passwd3);
 
1379
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1380
 
 
1381
   /////////////////////////////////////////////////////////////////////////////
 
1382
   cout << "Executing KDF tests with longer compute time" << endl;
 
1383
   kdf.computeKdfParams(1.0);
 
1384
   kdf.printKdfParams();
 
1385
 
 
1386
   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
 
1387
   key = kdf.DeriveKey(passwd1);
 
1388
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1389
 
 
1390
   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
 
1391
   key = kdf.DeriveKey(passwd2);
 
1392
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1393
 
 
1394
   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
 
1395
   key = kdf.DeriveKey(passwd3);
 
1396
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1397
 
 
1398
   /////////////////////////////////////////////////////////////////////////////
 
1399
   cout << "Executing KDF tests with limited memory target" << endl;
 
1400
   kdf.computeKdfParams(1.0, 256*1024);
 
1401
   kdf.printKdfParams();
 
1402
 
 
1403
   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
 
1404
   key = kdf.DeriveKey(passwd1);
 
1405
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1406
 
 
1407
   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
 
1408
   key = kdf.DeriveKey(passwd2);
 
1409
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1410
 
 
1411
   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
 
1412
   key = kdf.DeriveKey(passwd3);
 
1413
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1414
 
 
1415
   /////////////////////////////////////////////////////////////////////////////
 
1416
   cout << "KDF with min memory requirement (1 kB)" << endl;
 
1417
   kdf.computeKdfParams(1.0, 0);
 
1418
   kdf.printKdfParams();
 
1419
 
 
1420
   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
 
1421
   key = kdf.DeriveKey(passwd1);
 
1422
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1423
 
 
1424
   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
 
1425
   key = kdf.DeriveKey(passwd2);
 
1426
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1427
 
 
1428
   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
 
1429
   key = kdf.DeriveKey(passwd3);
 
1430
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1431
 
 
1432
   /////////////////////////////////////////////////////////////////////////////
 
1433
   cout << "KDF with 0 compute time" << endl;
 
1434
   kdf.computeKdfParams(0, 0);
 
1435
   kdf.printKdfParams();
 
1436
 
 
1437
   cout << "   Password1: '" << passwd1.toBinStr() << "'" << endl;
 
1438
   key = kdf.DeriveKey(passwd1);
 
1439
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1440
 
 
1441
   cout << "   Password2: '" << passwd2.toBinStr() << "'" << endl;
 
1442
   key = kdf.DeriveKey(passwd2);
 
1443
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1444
 
 
1445
   cout << "   Password1: '" << passwd3.toBinStr() << "'" << endl;
 
1446
   key = kdf.DeriveKey(passwd3);
 
1447
   cout << "   MasterKey: '" << key.toHexStr() << endl << endl;
 
1448
 
 
1449
   // Test AES code using NIST test vectors
 
1450
   /// *** Test 1 *** ///
 
1451
   cout << endl << endl;
 
1452
   SecureBinaryData testIV, plaintext, cipherTarg, cipherComp, testKey, rtPlain;
 
1453
   testKey.createFromHex   ("0000000000000000000000000000000000000000000000000000000000000000");
 
1454
   testIV.createFromHex    ("80000000000000000000000000000000");
 
1455
   plaintext.createFromHex ("00000000000000000000000000000000");
 
1456
   cipherTarg.createFromHex("ddc6bf790c15760d8d9aeb6f9a75fd4e");
 
1457
 
 
1458
   cout << "   Plain        : " << plaintext.toHexStr() << endl;
 
1459
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
 
1460
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
 
1461
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
 
1462
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
 
1463
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;
 
1464
 
 
1465
 
 
1466
   /// *** Test 2 *** ///
 
1467
   cout << endl << endl;
 
1468
   testKey.createFromHex   ("0000000000000000000000000000000000000000000000000000000000000000");
 
1469
   testIV.createFromHex    ("014730f80ac625fe84f026c60bfd547d");
 
1470
   plaintext.createFromHex ("00000000000000000000000000000000");
 
1471
   cipherTarg.createFromHex("5c9d844ed46f9885085e5d6a4f94c7d7");
 
1472
 
 
1473
   cout << "   Plain        : " << plaintext.toHexStr() << endl;
 
1474
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
 
1475
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
 
1476
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
 
1477
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
 
1478
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;
 
1479
 
 
1480
   /// *** Test 3 *** ///
 
1481
   cout << endl << endl;
 
1482
   testKey.createFromHex   ("ffffffffffff0000000000000000000000000000000000000000000000000000");
 
1483
   testIV.createFromHex    ("00000000000000000000000000000000");
 
1484
   plaintext.createFromHex ("00000000000000000000000000000000");
 
1485
   cipherTarg.createFromHex("225f068c28476605735ad671bb8f39f3");
 
1486
 
 
1487
   cout << "   Plain        : " << plaintext.toHexStr() << endl;
 
1488
   cipherComp = CryptoAES().EncryptCFB(plaintext, testKey, testIV);
 
1489
   cout << "   CipherTarget : " << cipherComp.toHexStr() << endl;
 
1490
   cout << "   CipherCompute: " << cipherComp.toHexStr() << endl;
 
1491
   rtPlain = CryptoAES().DecryptCFB(cipherComp, testKey, testIV);
 
1492
   cout << "   Plain        : " << rtPlain.toHexStr() << endl;
 
1493
 
 
1494
 
 
1495
   /// My own test, for sanity (can only check the roundtrip values)
 
1496
   // This test is a lot more exciting with the couts uncommented in Encrypt/Decrypt
 
1497
   cout << endl << endl;
 
1498
   cout << "Starting some kdf-aes-combined tests..." << endl;
 
1499
   kdf.printKdfParams();
 
1500
   testKey = kdf.DeriveKey(SecureBinaryData("This passphrase is tough to guess"));
 
1501
   SecureBinaryData secret, cipher;
 
1502
   secret.createFromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
 
1503
   SecureBinaryData randIV(0);  // tell the crypto to generate a random IV for me.
 
1504
 
 
1505
   cout << "Encrypting:" << endl;
 
1506
   cipher = CryptoAES().EncryptCFB(secret, testKey, randIV);
 
1507
   cout << endl << endl;
 
1508
   cout << "Decrypting:" << endl;
 
1509
   secret = CryptoAES().DecryptCFB(cipher, testKey, randIV);
 
1510
   cout << endl << endl;
 
1511
 
 
1512
   // Now encrypting so I can store the encrypted data in file
 
1513
   cout << "Encrypting again:" << endl;
 
1514
   cipher = CryptoAES().EncryptCFB(secret, testKey, randIV);
 
1515
 
 
1516
   ofstream testfile("safefile.txt", ios::out);
 
1517
   testfile << "KdfParams " << endl;
 
1518
   testfile << "   MemReqts " << kdf.getMemoryReqtBytes() << endl;
 
1519
   testfile << "   NumIters " << kdf.getNumIterations() << endl;
 
1520
   testfile << "   HexSalt  " << kdf.getSalt().toHexStr() << endl;
 
1521
   testfile << "EncryptedData" << endl;
 
1522
   testfile << "   HexIV    " << randIV.toHexStr() << endl;
 
1523
   testfile << "   Cipher   " << cipher.toHexStr() << endl;
 
1524
   testfile.close();
 
1525
   
 
1526
   ifstream infile("safefile.txt", ios::in);
 
1527
   uint32_t mem, nIters;
 
1528
   SecureBinaryData salt, iv;
 
1529
   char deadstr[256];
 
1530
   char hexstr[256];
 
1531
 
 
1532
   infile >> deadstr;
 
1533
   infile >> deadstr >> mem;
 
1534
   infile >> deadstr >> nIters;
 
1535
   infile >> deadstr >> hexstr;
 
1536
   salt.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
 
1537
   infile >> deadstr;
 
1538
   infile >> deadstr >> hexstr;
 
1539
   iv.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
 
1540
   infile >> deadstr >> hexstr;
 
1541
   cipher.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
 
1542
   infile.close();
 
1543
   cout << endl << endl;
 
1544
 
 
1545
   // Will try this twice, once with correct passphrase, once without
 
1546
   SecureBinaryData cipherTry1 = cipher;
 
1547
   SecureBinaryData cipherTry2 = cipher;
 
1548
   SecureBinaryData newKey;
 
1549
 
 
1550
   KdfRomix newKdf(mem, nIters, salt);
 
1551
   newKdf.printKdfParams();
 
1552
 
 
1553
   // First test with the wrong passphrase
 
1554
   cout << "Attempting to decrypt with wrong passphrase" << endl;
 
1555
   SecureBinaryData passphrase = SecureBinaryData("This is the wrong passphrase");
 
1556
   newKey = newKdf.DeriveKey( passphrase );
 
1557
   CryptoAES().DecryptCFB(cipherTry1, newKey, iv);
 
1558
 
 
1559
 
 
1560
   // Now try correct passphrase
 
1561
   cout << "Attempting to decrypt with CORRECT passphrase" << endl;
 
1562
   passphrase = SecureBinaryData("This passphrase is tough to guess");
 
1563
   newKey = newKdf.DeriveKey( passphrase );
 
1564
   CryptoAES().DecryptCFB(cipherTry2, newKey, iv);
 
1565
}
 
1566
 
 
1567
 
 
1568
 
 
1569
 
 
1570
 
 
1571
 
 
1572
void TestECDSA(void)
 
1573
{
 
1574
 
 
1575
   SecureBinaryData msgToSign("This message came from me!");
 
1576
   SecureBinaryData privData = SecureBinaryData().GenerateRandom(32);
 
1577
   BTC_PRIVKEY privKey = CryptoECDSA().ParsePrivateKey(privData);
 
1578
   BTC_PUBKEY  pubKey  = CryptoECDSA().ComputePublicKey(privKey);
 
1579
 
 
1580
   // Test key-match check
 
1581
   cout << "Do the pub-priv keypair we just created match? ";
 
1582
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(privKey, pubKey) ? 1 : 0) << endl;
 
1583
   cout << endl;
 
1584
   
 
1585
   SecureBinaryData signature = CryptoECDSA().SignData(msgToSign, privKey);
 
1586
   cout << "Signature = " << signature.toHexStr() << endl;
 
1587
   cout << endl;
 
1588
 
 
1589
   bool isValid = CryptoECDSA().VerifyData(msgToSign, signature, pubKey);
 
1590
   cout << "SigValid? = " << (isValid ? 1 : 0) << endl;
 
1591
   cout << endl;
 
1592
 
 
1593
   // Test signature from blockchain:
 
1594
   SecureBinaryData msg = SecureBinaryData::CreateFromHex("0100000001bb664ff716b9dfc831bcc666c1767f362ad467fcfbaf4961de92e45547daab870100000062537a7652a269537a829178a91480677c5392220db736455533477d0bc2fba65502879b69537a829178a91402d7aa2e76d9066fb2b3c41ff8839a5c81bdca19879b69537a829178a91410039ce4fdb5d4ee56148fe3935b9bfbbe4ecc89879b6953aeffffffff0280969800000000001976a9140817482d2e97e4be877efe59f4bae108564549f188ac7015a7000000000062537a7652a269537a829178a91480677c5392220db736455533477d0bc2fba65502879b69537a829178a91402d7aa2e76d9066fb2b3c41ff8839a5c81bdca19879b69537a829178a91410039ce4fdb5d4ee56148fe3935b9bfbbe4ecc89879b6953ae0000000001000000");
 
1595
   SecureBinaryData px  = SecureBinaryData::CreateFromHex("8c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38");
 
1596
   SecureBinaryData py  = SecureBinaryData::CreateFromHex("e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
 
1597
   SecureBinaryData pub65  = SecureBinaryData::CreateFromHex("048c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
 
1598
   //SecureBinaryData sig = SecureBinaryData::CreateFromHex("3046022100d73f633f114e0e0b324d87d38d34f22966a03b072803afa99c9408201f6d6dc6022100900e85be52ad2278d24e7edbb7269367f5f2d6f1bd338d017ca4600087766144");
 
1599
   SecureBinaryData sig = SecureBinaryData::CreateFromHex("d73f633f114e0e0b324d87d38d34f22966a03b072803afa99c9408201f6d6dc6900e85be52ad2278d24e7edbb7269367f5f2d6f1bd338d017ca4600087766144");
 
1600
   pubKey = CryptoECDSA().ParsePublicKey(px,py);
 
1601
   isValid = CryptoECDSA().VerifyData(msg, sig, pubKey);
 
1602
   cout << "SigValid? = " << (isValid ? 1 : 0) << endl;
 
1603
 
 
1604
 
 
1605
   // Test speed on signature:
 
1606
   uint32_t nTest = 50;
 
1607
   cout << "Test signature and verification speeds"  << endl;
 
1608
   cout << "\nTiming Signing";
 
1609
   TIMER_START("SigningTime");
 
1610
   for(uint32_t i=0; i<nTest; i++)
 
1611
   {
 
1612
      // This timing includes key parsing
 
1613
      CryptoECDSA().SignData(msgToSign, privData);
 
1614
   }
 
1615
   TIMER_STOP("SigningTime");
 
1616
 
 
1617
   // Test speed of verification
 
1618
   TIMER_START("VerifyTime");
 
1619
   cout << "\nTiming Verify";
 
1620
   for(uint32_t i=0; i<nTest; i++)
 
1621
   {
 
1622
      // This timing includes key parsing
 
1623
      CryptoECDSA().VerifyData(msg, sig, pub65);
 
1624
   }
 
1625
   TIMER_STOP("VerifyTime");
 
1626
 
 
1627
   cout << endl;
 
1628
   cout << "Timing (Signing): " << 1/(TIMER_READ_SEC("SigningTime")/nTest)
 
1629
        << " signatures/sec" << endl;
 
1630
   cout << "Timing (Verify):  " << 1/(TIMER_READ_SEC("VerifyTime")/nTest)
 
1631
        << " verifies/sec" << endl;
 
1632
 
 
1633
 
 
1634
   // Test deterministic key generation
 
1635
   SecureBinaryData privDataOrig = SecureBinaryData().GenerateRandom(32);
 
1636
   BTC_PRIVKEY privOrig = CryptoECDSA().ParsePrivateKey(privDataOrig);
 
1637
   BTC_PUBKEY  pubOrig  = CryptoECDSA().ComputePublicKey(privOrig);
 
1638
   cout << "Testing deterministic key generation" << endl;
 
1639
   cout << "   Verify again that pub/priv objects pair match : ";
 
1640
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(privOrig, pubOrig) ? 1 : 0) << endl;
 
1641
 
 
1642
   SecureBinaryData binPriv = CryptoECDSA().SerializePrivateKey(privOrig);
 
1643
   SecureBinaryData binPub  = CryptoECDSA().SerializePublicKey(pubOrig);
 
1644
   cout << "   Verify again that binary pub/priv pair match  : ";
 
1645
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(binPriv, binPub) ? 1 : 0) << endl;
 
1646
   cout << endl;
 
1647
 
 
1648
   SecureBinaryData chaincode = SecureBinaryData().GenerateRandom(32);
 
1649
   cout << "   Starting privKey:" << binPriv.toHexStr() << endl;
 
1650
   cout << "   Starting pubKey :" << binPub.toHexStr() << endl;
 
1651
   cout << "   Chaincode       :" << chaincode.toHexStr() << endl;
 
1652
   cout << endl;
 
1653
   
 
1654
   SecureBinaryData newBinPriv = CryptoECDSA().ComputeChainedPrivateKey(binPriv, chaincode);
 
1655
   SecureBinaryData newBinPubA = CryptoECDSA().ComputePublicKey(newBinPriv);
 
1656
   SecureBinaryData newBinPubB = CryptoECDSA().ComputeChainedPublicKey(binPub, chaincode);
 
1657
   cout << "   Verify new binary pub/priv pair match: ";
 
1658
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(newBinPriv, newBinPubA) ? 1 : 0) << endl;
 
1659
   cout << "   Verify new binary pub/priv pair match: ";
 
1660
   cout << (CryptoECDSA().CheckPubPrivKeyMatch(newBinPriv, newBinPubB) ? 1 : 0) << endl;
 
1661
   cout << "   New privKey:" << newBinPriv.toHexStr() << endl;
 
1662
   cout << "   New pubKeyA:" << newBinPubA.getSliceCopy(0,30).toHexStr() << "..." << endl;
 
1663
   cout << "   New pubKeyB:" << newBinPubB.getSliceCopy(0,30).toHexStr() << "..." << endl;
 
1664
   cout << endl;
 
1665
 
 
1666
 
 
1667
   // Test arbitrary scalar/point operations
 
1668
   BinaryData a = BinaryData::CreateFromHex("8c006ff0d2cfde86455086af5a25b88c2b81858aab67f6a3132c885a2cb9ec38");
 
1669
   BinaryData b = BinaryData::CreateFromHex("e700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
 
1670
   BinaryData c = BinaryData::CreateFromHex("f700576fd46c7d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
 
1671
   BinaryData d = BinaryData::CreateFromHex("8130904787384d72d7d22555eee3a14e2876c643cd70b1b0a77fbf46e62331ac");
 
1672
   BinaryData e = CryptoECDSA().ECMultiplyScalars(a,b);
 
1673
   BinaryData f = CryptoECDSA().ECMultiplyPoint(a, b, c);
 
1674
   BinaryData g = CryptoECDSA().ECAddPoints(a, b, c, d);
 
1675
}
 
1676
 
 
1677
 
 
1678
 
 
1679
 
 
1680
void TestPointCompression(void)
 
1681
{
 
1682
   vector<BinaryData> testPubKey(3);
 
1683
   testPubKey[0].createFromHex("044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1");
 
1684
   testPubKey[1].createFromHex("04ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bdedc416f5cefc1db0625cd0c75de8192d2b592d7e3b00bcfb4a0e860d880fd1fc");
 
1685
   testPubKey[2].createFromHex("042596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3ed0a9004acf927666eee18b7f5e8ad72ff100a3bb710a577256fd7ec81eb1cb3");
 
1686
 
 
1687
   CryptoPP::ECP & ecp = CryptoECDSA::Get_secp256k1_ECP();
 
1688
   for(uint32_t i=0; i<3; i++)
 
1689
   {
 
1690
      CryptoPP::Integer pubX, pubY;
 
1691
      pubX.Decode(testPubKey[i].getPtr()+1,  32, UNSIGNED);
 
1692
      pubY.Decode(testPubKey[i].getPtr()+33, 32, UNSIGNED);
 
1693
      BTC_ECPOINT ptPub(pubX, pubY);
 
1694
 
 
1695
      BinaryData ptFlat(65);
 
1696
      BinaryData ptComp(33);
 
1697
 
 
1698
      ecp.EncodePoint((byte*)ptFlat.getPtr(), ptPub, false);
 
1699
      ecp.EncodePoint((byte*)ptComp.getPtr(), ptPub, true);
 
1700
 
 
1701
      cout << "Point (" << i << "): " << ptFlat.toHexStr() << endl;
 
1702
      cout << "Point (" << i << "): " << ptComp.toHexStr() << endl;
 
1703
      cout << "Point (" << i << "): " << CryptoECDSA().UncompressPoint(SecureBinaryData(ptComp)).toHexStr() << endl;
 
1704
      cout << "Point (" << i << "): " << CryptoECDSA().CompressPoint(SecureBinaryData(testPubKey[i])).toHexStr() << endl;
 
1705
   }
 
1706
 
 
1707
 
 
1708
 
 
1709
}
 
1710
 
 
1711
 
 
1712
 
 
1713
 
 
1714
 
 
1715
 
 
1716
 
 
1717
void TestReadBlkFileUpdate(string testblockdir, string blkdir)
 
1718
{
 
1719
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
1720
    
 
1721
   // Setup the files that will be copied -- sources and destinations
 
1722
   vector<string> srcs(7);
 
1723
   srcs[0] = testblockdir + string("/blk00000.dat");
 
1724
   srcs[1] = testblockdir + string("/blk00000_test1.dat");
 
1725
   srcs[2] = testblockdir + string("/blk00000_test2.dat");
 
1726
   srcs[3] = testblockdir + string("/blk00001_test3.dat");
 
1727
   srcs[4] = testblockdir + string("/blk00002_test4.dat");
 
1728
   srcs[5] = testblockdir + string("/blk00002_test5.dat");
 
1729
   srcs[6] = testblockdir + string("/blk00003_test5.dat");
 
1730
   
 
1731
   vector<string> dsts(7);
 
1732
   dsts[0] = blkdir + string("/blk00000.dat");
 
1733
   dsts[1] = blkdir + string("/blk00000.dat");
 
1734
   dsts[2] = blkdir + string("/blk00000.dat");
 
1735
   dsts[3] = blkdir + string("/blk00001.dat");
 
1736
   dsts[4] = blkdir + string("/blk00002.dat");
 
1737
   dsts[5] = blkdir + string("/blk00002.dat");
 
1738
   dsts[6] = blkdir + string("/blk00003.dat");
 
1739
 
 
1740
   for(uint32_t i=0; i<7; i++)
 
1741
      if( BtcUtils::GetFileSize(dsts[i]) != FILE_DOES_NOT_EXIST )
 
1742
         remove(dsts[i].c_str()); 
 
1743
 
 
1744
 
 
1745
   copyFile(srcs[0], dsts[0]);
 
1746
   bdm.SetBlkFileLocation(blkdir, 5, 0);
 
1747
   bdm.parseEntireBlockchain();  
 
1748
   cout << "Top Block: " << bdm.getTopBlockHeight() << endl;
 
1749
   
 
1750
   uint32_t t = 1;
 
1751
 
 
1752
   // TEST 1 -- Add one block
 
1753
   copyFile(srcs[1], dsts[1]);
 
1754
   bdm.readBlkFileUpdate();
 
1755
   cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
 
1756
 
 
1757
   // TEST 2 -- Add 3 blocks
 
1758
   copyFile(srcs[2], dsts[2]);
 
1759
   bdm.readBlkFileUpdate();
 
1760
   cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
 
1761
 
 
1762
   // TEST 3 -- Blkfile split with 1 block
 
1763
   copyFile(srcs[3], dsts[3]);
 
1764
   bdm.readBlkFileUpdate();
 
1765
   cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
 
1766
 
 
1767
   // TEST 4 -- Blkfile split with 3 blocks
 
1768
   copyFile(srcs[4], dsts[4]);
 
1769
   bdm.readBlkFileUpdate();
 
1770
   cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
 
1771
 
 
1772
   // TEST 5 -- Add blocks and split
 
1773
   copyFile(srcs[5], dsts[5]);
 
1774
   copyFile(srcs[6], dsts[6]);
 
1775
   bdm.readBlkFileUpdate();
 
1776
   cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
 
1777
 
 
1778
}
 
1779
 
 
1780
void TestOutOfOrder(string blkdir)
 
1781
{
 
1782
   /////////////////////////////////////////////////////////////////////////////
 
1783
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
1784
   BinaryData myAddress;
 
1785
   BtcWallet wlt;
 
1786
   
 
1787
   // Main-network addresses
 
1788
   // I do not remember anymore what any of these addresses were for ...
 
1789
   // All I know is they probably have some tx history..
 
1790
   myAddress.createFromHex("604875c897a079f4db88e5d71145be2093cae194"); wlt.addAddress(myAddress);
 
1791
   myAddress.createFromHex("8996182392d6f05e732410de4fc3fa273bac7ee6"); wlt.addAddress(myAddress);
 
1792
   myAddress.createFromHex("b5e2331304bc6c541ffe81a66ab664159979125b"); wlt.addAddress(myAddress);
 
1793
   myAddress.createFromHex("ebbfaaeedd97bc30df0d6887fd62021d768f5cb8"); wlt.addAddress(myAddress);
 
1794
 
 
1795
   // P2Pool Address
 
1796
   //myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt.addAddress(myAddress);
 
1797
 
 
1798
   // Add some relevant testnet addresses
 
1799
   //myAddress.createFromHex("0c6b92101c7025643c346d9c3e23034a8a843e21"); wlt.addAddress(myAddress);
 
1800
   //myAddress.createFromHex("34c9f8dc91dfe1ae1c59e76cbe1aa39d0b7fc041"); wlt.addAddress(myAddress);
 
1801
   //myAddress.createFromHex("d77561813ca968270d5f63794ddb6aab3493605e"); wlt.addAddress(myAddress);
 
1802
   //myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); wlt.addAddress(myAddress);
 
1803
 
 
1804
   // These two addresses were used at one point for testing unconfirmed balances
 
1805
   myAddress.createFromHex("8c61f6a7558af399e404d82beddcc4692db7b30f"); wlt.addAddress(myAddress);
 
1806
   myAddress.createFromHex("14445409283ef413f5fb004338377bf042064922"); wlt.addAddress(myAddress);
 
1807
 
 
1808
   bdm.registerWallet(&wlt);
 
1809
 
 
1810
 
 
1811
   /////////////////////////////////////////////////////////////////////////////
 
1812
   cout << "Reading data from blockchain... (with wallet scan)" << endl;
 
1813
   TIMER_START("BDM_Load_Scan_Blockchain_With_Wallet");
 
1814
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
1815
   bdm.parseEntireBlockchain();  
 
1816
   TIMER_STOP("BDM_Load_Scan_Blockchain_With_Wallet");
 
1817
   cout << endl << endl;
 
1818
 
 
1819
   myAddress.createFromHex("11b366edfc0a8b66feebae5c2e25a7b6a5d1cf31"); wlt.addAddress(myAddress);
 
1820
   myAddress.createFromHex("e826f4a4381453dcdcf9bfeedffe95de7c86ccbd"); wlt.addAddress(myAddress);
 
1821
 
 
1822
   bdm.scanBlockchainForTx(wlt);
 
1823
}
 
1824
 
 
1825
 
 
1826
 
 
1827
 
 
1828
void TestLevelDB(string testLDBDir, string blkfilepath)
 
1829
{
 
1830
   leveldb::DB* ldb;
 
1831
   leveldb::Options opts;   
 
1832
   
 
1833
   // Setup the optoins for this particular database
 
1834
   opts.create_if_missing = true;
 
1835
   //opts.filter_policy     = NewBloomFilter(10);
 
1836
   
 
1837
   /*
 
1838
   leveldb::Status stat = leveldb::DB::Open(opts, testLDBDir.c_str(), &ldb);
 
1839
   assert(leveldb::ldbCheckStatus(stat));
 
1840
 
 
1841
   for(uint32_t i=0; i<10; i++)
 
1842
   {
 
1843
      uint32_t ncharKey = 2*(i%6)+1;
 
1844
      uint32_t ncharVal = 3*(i%8)+1;
 
1845
      BinaryData insertKey(ncharKey);
 
1846
      BinaryData insertVal(ncharVal);
 
1847
      insertKey.fill( (uint8_t)i%255 );
 
1848
      insertVal.fill( (uint8_t)i%256 );
 
1849
      
 
1850
      cout << "Inserting: (" << insertKey.toHexStr() << "," 
 
1851
                             << insertVal.toHexStr() << ")" << endl;
 
1852
 
 
1853
      stat = ldb->Put(leveldb::WriteOptions(), 
 
1854
                      insertKey.toBinStr(), 
 
1855
                      insertVal.toBinStr()); 
 
1856
      assert(leveldb::ldbCheckStatus(stat));
 
1857
   }
 
1858
 
 
1859
   leveldb::Iterator* it = ldb->NewIterator(leveldb::ReadOptions());
 
1860
   uint32_t idx = 1;
 
1861
   for(it->SeekToFirst(); it->Valid(); it->Next())
 
1862
   {
 
1863
      BinaryData key(it->key().ToString());
 
1864
      BinaryData val(it->value().ToString());
 
1865
      cout << idx++ << ": " << key.toHexStr() << ": " << val.toHexStr() << endl;
 
1866
   }
 
1867
 
 
1868
   cout << "Keys in DB: " << idx-1 << endl;
 
1869
 
 
1870
   string val2;
 
1871
   stat = ldb->Get(leveldb::ReadOptions(), "MyKey", &val2);
 
1872
   leveldb::ldbCheckStatus(stat);
 
1873
   cout << "Plowed through the error..." << endl;
 
1874
 
 
1875
   delete ldb;
 
1876
   //delete opts.filter_policy;
 
1877
   */
 
1878
   
 
1879
   // Start new blockchain read/write test....
 
1880
   opts.create_if_missing = true;
 
1881
   opts.compression       = leveldb::kNoCompression;
 
1882
   leveldb::Status stat = leveldb::DB::Open(opts, testLDBDir.c_str(), &ldb);
 
1883
   assert(leveldb::ldbCheckStatus(stat));
 
1884
 
 
1885
   ifstream is(blkfilepath.c_str(), ios::in | ios::binary);
 
1886
   assert(is.is_open());
 
1887
 
 
1888
   uint64_t filesize = BtcUtils::GetFileSize(blkfilepath);
 
1889
   BinaryStreamBuffer bsb;
 
1890
   bsb.attachAsStreamBuffer(is, filesize);
 
1891
 
 
1892
   bool alreadyRead8B = false;
 
1893
   uint32_t nextBlkSize;
 
1894
   uint64_t nBytesRead = 0;
 
1895
   uint32_t nBlkRead = 0;
 
1896
   TIMER_START("NaiveScan");
 
1897
   while(bsb.streamPull())
 
1898
   {
 
1899
      while(bsb.reader().getSizeRemaining() > 8)
 
1900
      {
 
1901
         if(!alreadyRead8B)
 
1902
         {
 
1903
            bsb.reader().advance(4);
 
1904
            nextBlkSize = bsb.reader().get_uint32_t();
 
1905
            nBytesRead += 8;
 
1906
         }
 
1907
 
 
1908
         if(bsb.reader().getSizeRemaining() < nextBlkSize)
 
1909
         {
 
1910
            alreadyRead8B = true;
 
1911
            break;
 
1912
         }
 
1913
         alreadyRead8B = false;
 
1914
 
 
1915
         BinaryRefReader brr(bsb.reader().getCurrPtr(), nextBlkSize);
 
1916
 
 
1917
         // Do something with the block just read
 
1918
         BinaryData headerHash(32);
 
1919
         BinaryData headerRaw(HEADER_SIZE);
 
1920
         brr.get_BinaryData(headerRaw, HEADER_SIZE);
 
1921
         BtcUtils::getHash256_NoSafetyCheck(headerRaw.getPtr(), HEADER_SIZE, headerHash);
 
1922
         
 
1923
         stat = ldb->Put(leveldb::WriteOptions(), 
 
1924
                         headerHash.toBinStr(),
 
1925
                         headerRaw.toBinStr()); 
 
1926
         assert(leveldb::ldbCheckStatus(stat));
 
1927
         
 
1928
 
 
1929
         uint32_t nTx = brr.get_var_int();
 
1930
         for(uint32_t itx=0; itx<nTx; itx++)
 
1931
         {
 
1932
            uint32_t txLen = BtcUtils::TxCalcLength(brr.getCurrPtr());
 
1933
            BinaryData txRaw(txLen);
 
1934
            brr.get_BinaryData(txRaw, txLen);
 
1935
            BinaryData txHash(32);
 
1936
            BtcUtils::getHash256_NoSafetyCheck(txRaw.getPtr(), txLen, txHash); 
 
1937
 
 
1938
            stat = ldb->Put(leveldb::WriteOptions(), 
 
1939
                        txHash.toBinStr(),
 
1940
                        txRaw.toBinStr()); 
 
1941
            assert(leveldb::ldbCheckStatus(stat));
 
1942
         }
 
1943
 
 
1944
         nBlkRead++;
 
1945
         nBytesRead += nextBlkSize;
 
1946
         bsb.reader().advance(nextBlkSize);
 
1947
 
 
1948
         if(nBlkRead % 5000 == 0)
 
1949
            cout << nBlkRead << " blocks read..." << endl;
 
1950
      }
 
1951
   }
 
1952
   TIMER_STOP("NaiveScan");
 
1953
      
 
1954
 
 
1955
}
 
1956
 
 
1957
 
 
1958
void TestLDBScanBlockchain(string testdbpath)
 
1959
{
 
1960
   leveldb::Options opts;   
 
1961
   opts.create_if_missing = true;
 
1962
   opts.compression       = leveldb::kNoCompression;
 
1963
 
 
1964
   leveldb::DB* ldb;
 
1965
   leveldb::Status stat = leveldb::DB::Open(opts, testdbpath.c_str(), &ldb);
 
1966
   assert(leveldb::ldbCheckStatus(stat));
 
1967
 
 
1968
 
 
1969
   map<BinaryData, int> addrMap;
 
1970
   BinaryData addr;
 
1971
   // Main-network addresses
 
1972
   addr.createFromHex("47b8ad0b1d6803260ce428d9e09e2cd99fd3b359"); addrMap[addr] = 1;
 
1973
   addr.createFromHex("59b3d39fd92c9ee0d928e40c2603681d0badb847"); addrMap[addr] = 1;
 
1974
   addr.createFromHex("fe3959db250f247ad724f2af5439ca32e8be3db1"); addrMap[addr] = 1;
 
1975
   addr.createFromHex("b13dbee832ca3954aff224d77a240f25db5939fe"); addrMap[addr] = 1;
 
1976
 
 
1977
   map<OutPoint, uint64_t> unspentOutPoints;
 
1978
 
 
1979
   leveldb::Iterator* it = ldb->NewIterator(leveldb::ReadOptions());
 
1980
   uint32_t idx = 1;
 
1981
   vector<uint32_t> offsetsIn;
 
1982
   vector<uint32_t> offsetsOut;
 
1983
 
 
1984
   TIMER_START("Rescan_from_LevelDB");
 
1985
   uint32_t nObj=0;
 
1986
   uint64_t allbtc=0;
 
1987
   cout << "Entry Lengths: ";
 
1988
   for(it->SeekToFirst(); it->Valid(); it->Next())
 
1989
   {
 
1990
      BinaryData val(it->value().ToString());
 
1991
      if(val.getSize()==80)  // need to add another condition
 
1992
         continue;
 
1993
 
 
1994
      uint32_t txLen = BtcUtils::TxCalcLength(val.getPtr(), &offsetsIn, &offsetsOut);
 
1995
      
 
1996
      OutPoint op;
 
1997
 
 
1998
      for(uint32_t iout=0; iout<offsetsOut.size()-1; iout++)
 
1999
      {
 
2000
         static uint8_t scriptLenFirstByte;
 
2001
         static HashString addr20(20);
 
2002
   
 
2003
         uint8_t const * ptr = (val.getPtr() + offsetsOut[iout] + 8);
 
2004
         scriptLenFirstByte = *(uint8_t*)ptr;
 
2005
         if(scriptLenFirstByte == 25)
 
2006
         {
 
2007
            // Std TxOut with 25-byte script
 
2008
            addr20.copyFrom(ptr+4, 20);
 
2009
            if( addrMap.find(addr20) != addrMap.end() )
 
2010
            {
 
2011
               uint64_t val = *(uint64_t*)(ptr-8);
 
2012
               cout << "   Received a TxOut! " << val/1e8 << endl;
 
2013
               allbtc += val;
 
2014
               op.setTxHash(it->key().ToString());
 
2015
               op.setTxOutIndex(iout);
 
2016
               unspentOutPoints[op] = val;
 
2017
            }
 
2018
         }
 
2019
         else if(scriptLenFirstByte==67)
 
2020
         {
 
2021
            // Std spend-coinbase TxOut script
 
2022
            static HashString addr20(20);
 
2023
            BtcUtils::getHash160_NoSafetyCheck(ptr+2, 65, addr20);
 
2024
            if( addrMap.find(addr20) != addrMap.end() )
 
2025
            {
 
2026
               uint64_t val = *(uint64_t*)(ptr-8);
 
2027
               cout << "   Received a TxOut!" << val/1e8 << endl;
 
2028
               allbtc += val;
 
2029
               op.setTxHash(it->key().ToString());
 
2030
               op.setTxOutIndex(iout);
 
2031
               unspentOutPoints[op] = val;
 
2032
            }
 
2033
         }
 
2034
         else
 
2035
         {
 
2036
            // Do nothing
 
2037
         }
 
2038
      }
 
2039
 
 
2040
      if(++nObj % 50000 == 0)
 
2041
         cout << "Processed " << nObj << " tx " << endl;
 
2042
   }
 
2043
 
 
2044
   for(it->SeekToFirst(); it->Valid(); it->Next())
 
2045
   {
 
2046
      BinaryData val(it->value().ToString());
 
2047
      if(val.getSize()==80)  // need to add another condition
 
2048
         continue;
 
2049
 
 
2050
      uint32_t txLen = BtcUtils::TxCalcLength(val.getPtr(), &offsetsIn, &offsetsOut);
 
2051
      
 
2052
      OutPoint op;
 
2053
      map<OutPoint, uint64_t>::iterator iter;
 
2054
      for(uint32_t iin=0; iin<offsetsIn.size()-1; iin++)
 
2055
      {
 
2056
         op.unserialize(val.getPtr() + offsetsIn[iin]);
 
2057
         iter = unspentOutPoints.find(op); 
 
2058
         if(iter != unspentOutPoints.end())
 
2059
         {
 
2060
            cout << "   Spent a TxOut! " << endl;
 
2061
            allbtc -= iter->second;
 
2062
            unspentOutPoints.erase(iter);
 
2063
         }
 
2064
      }
 
2065
   }
 
2066
 
 
2067
   TIMER_STOP("Rescan_from_LevelDB");
 
2068
   cout << "Total TxOuts: " << allbtc/1e8 << endl;
 
2069
 
 
2070
}
 
2071
 
 
2072
 
 
2073
 
 
2074
void TestLdbBlockchainUtils(string blkdir)
 
2075
{
 
2076
   BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance(); 
 
2077
   bdm.SetBlkFileLocation(blkdir, 4, 1);
 
2078
 
 
2079
   string pathH("testldb/ldbtestHeaders");
 
2080
   string pathT("testldb/ldbtestTx");
 
2081
   string pathR("testldb/ldbtestTransient");
 
2082
 
 
2083
   //bdm.setLevelDBPaths(pathH, pathT, pathR);
 
2084
 
 
2085
   
 
2086
}
 
2087
 
 
2088
 
 
2089
 
 
2090
 
 
2091
 
 
2092
 
 
2093
 
 
2094
 
 
2095