1
////////////////////////////////////////////////////////////////////////////////
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 //
7
////////////////////////////////////////////////////////////////////////////////
13
#include "UniversalTimer.h"
14
#include "BinaryData.h"
16
#include "BlockUtils.h"
17
#include "EncryptionUtils.h"
18
//#include "FileDataPtr.h"
19
#include "PartialMerkle.h"
20
#include "leveldb_wrapper.h"
22
#include "leveldb/db.h"
29
////////////////////////////////////////////////////////////////////////////////
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);
42
void TestPointCompression(void);
43
void TestFileCache(void);
44
void TestReadBlkFileUpdate(string testblockdir, string blkdir);
46
void TestOutOfOrder(string blkdir);
47
void TestLevelDB(string testLDBDir, string blkfilepath="");
48
void TestLDBScanBlockchain(string testdbpath);
49
void TestLdbBlockchainUtils(string blkdir);
51
////////////////////////////////////////////////////////////////////////////////
53
void printTestHeader(string TestName)
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 << "*";
62
bool copyFile(string src, string dst)
64
uint32_t srcsz = BtcUtils::GetFileSize(src);
65
if(srcsz == FILE_DOES_NOT_EXIST)
68
BinaryData temp(srcsz);
69
ifstream is(src.c_str(), ios::in | ios::binary);
70
is.read((char*)temp.getPtr(), srcsz);
73
ofstream os(dst.c_str(), ios::out | ios::binary);
74
os.write((char*)temp.getPtr(), srcsz);
80
string pathJoin(string dir, string file)
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());
90
BinaryData h2b(string s)
92
return BinaryData::CreateFromHex(s);
100
BlockDataManager_LevelDB::GetInstance().SelectNetwork("Test");
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");
110
//printTestHeader("Read-and-Organize-Blockchain");
111
TestReadAndOrganizeChain(blkdir);
113
//printTestHeader("Wallet-Relevant-Tx-Scan");
114
TestScanForWalletTx(blkdir);
116
//printTestHeader("Find-Non-Standard-Tx");
117
//TestFindNonStdTx(blkdir);
119
//printTestHeader("Read-and-Organize-Blockchain-With-Wallet");
120
//TestReadAndOrganizeChainWithWallet(blkdir);
122
//printTestHeader("Test-Balance-Construction");
123
//TestBalanceConstruction(blkdir);
125
//printTestHeader("Read-and-Update-Blockchain");
126
//TestReadAndUpdateBlkFile(multitest);
128
//printTestHeader("Blockchain-Reorg-Unit-Test");
129
//TestReorgBlockchain("");
131
//printTestHeader("Test-out-of-order calls");
132
//TestOutOfOrder(blkdir);
135
//printTestHeader("Testing Zero-conf handling");
138
printTestHeader("Testing merkle-root calculation");
141
//printTestHeader("Crypto-KDF-and-AES-methods");
144
//printTestHeader("Crypto-ECDSA-sign-verify");
147
//printTestHeader("ECDSA Point Compression");
148
//TestPointCompression();
150
//printTestHeader("Testing file cache");
153
//printTestHeader("Testing LevelDB");
154
//TestLevelDB("blk0001db", blkdir + string("/blk0001.dat"));
155
//TestLDBScanBlockchain("blk0001db");
158
//printTestHeader("Testing LDB Blockchain utilities");
159
//TestLdbBlockchainUtils(blkdir);
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;
172
cout << "enter anything to exit" << endl;
179
void assertError(bool isTrue, string msg)
184
cerr << "***ERROR: Failed BaseTest. Msg:" << endl;
185
cerr << msg.c_str() << endl;
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;
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;
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"));
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"));
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"));
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"));
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"));
241
//realCoinbaseOut = "04b6acd549c083cb0d31ee975eb8c2ad7a41be61f0a47bc5d75e919d42704e5642d72f1804bcbab60dbd33f041d3c9edde57704a061a22c5e3cf93debf5f35daaeac"
242
//spendcb = "47304402201ffc44394e5a3dd9c8b55bdc12147e18574ac945d15dac026793bf3b8ff732af022035fd832549b5176126f735d87089c8c1c1319447a458a09818e173eaf0c2eef101"
243
//has160 = 957efec6af757ccbbcf9a436f0083c5ddaa3bf1d
244
//addrStr 1EdTpNBiPNPbEE4kASow2F4pUpES9jeTJE
246
vector<BinaryData> txInScripts;
247
vector<BinaryData> txInPrevHashes;
248
vector<TXIN_SCRIPT_TYPE> txInTypes;
249
vector<BinaryData> txInHash160s;
251
prevHashCB = h2b("0000000000000000000000000000000000000000000000000000000000000000");
252
prevHashReg = h2b("894862e362905c6075074d9ec4b4e2dc34720089b1e9ef4738ee1b13f3bdcdb7");
254
txInTypes.push_back(TXIN_SCRIPT_STDUNCOMPR)
255
txInScripts.push_back( h2b("493046022100b9daf2733055be73ae00ee0c5d78ca639d554fe779f163396c1a39b7913e7eac02210091f0deeb2e510c74354afb30cc7d8fbac81b1ca8b3940613379adc41a6ffd226014104b1537fa5bc2242d25ebf54f31e76ebabe0b3de4a4dccd9004f058d6c2caa5d31164252e1e04e5df627fae7adec27fa9d40c271fc4d30ff375ef6b26eba192bac"))
256
txInPrevHashes.push_back(prevHashReg);
257
txInHash160s.push_back(h2b("c42a8290196b2c5bcb35471b45aa0dc096baed5e"));
259
txInTypes.push_back(TXIN_SCRIPT_STDCOMPR);
260
txInScripts.push_back( h2b("47304402205299224886e5e3402b0e9fa3527bcfe1d73c4e2040f18de8dd17f116e3365a1102202590dcc16c4b711daae6c37977ba579ca65bcaa8fba2bd7168a984be727ccf7a01210315122ff4d41d9fe3538a0a8c6c7f813cf12a901069a43d6478917246dc92a782"));
261
txInPrevHashes.push_back(prevHashReg);
262
txInHash160s.push_back("03214fc1433a287e964d6c4242093c34e4ed0001");
265
txInTypes.push_back(TXIN_SCRIPT_COINBASE)
266
txInScripts.push_back( h2b("0310920304000071c3124d696e656420627920425443204775696c640800b75f950e000000"));
267
txInPrevHashes.push_back(prevHashCB);
268
txInHash160s.push_back( BtcUtils::BadAddress_);
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_);
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
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++)
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);
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");
304
uint32_t nInTest = txInScripts.size();
305
TXIN_SCRIPT_TYPE inType;
307
for(uint32_t test=0; test<nInTest; test++)
309
inType = getTxInScriptType(txInScripts[test], txInPrevHashes[test]);
313
vector<BinaryData> txInScripts;
314
vector<BinaryData> txInPrevHashes;
315
vector<TXIN_SCRIPT_TYPE> txInTypes;
316
vector<BinaryData> txInHash160s;
319
// Test difficulty-to-double
320
vector<BinaryData> diffBits;
321
vector<double> diffDbls;
323
diffBits.push_back(h2b("ffff001d"));
324
diffDbls.push_back(1.0);
326
diffBits.push_back(h2b("be2f021a"));
327
diffDbls.push_back(7672999.920164138);
329
diffBits.push_back(h2b("3daa011a"));
330
diffDbls.push_back(10076292.883418716);
332
for(uint32_t test=0; test<diffBits.size(); test++)
334
double diffdbl = convertDiffBitsToDouble(diffBits[test]);
335
assertError(abs(diffdbl-diffDbls[test])<1e-4, "Double repr of diff !match!");
340
BinaryData txFull(h2b("01000000020044fbc929d78e4203eed6f1d3d39c0157d8e5c100bbe0886779c0ebf6a69324010000008a47304402206568144ed5e7064d6176c74738b04c08ca19ca54ddeb480084b77f45eebfe57802207927d6975a5ac0e1bb36f5c05356dcda1f521770511ee5e03239c8e1eecf3aed0141045d74feae58c4c36d7c35beac05eddddc78b3ce4b02491a2eea72043978056a8bc439b99ddaad327207b09ef16a8910828e805b0cc8c11fba5caea2ee939346d7ffffffff45c866b219b176952508f8e5aea728f950186554fc4a5807e2186a8e1c4009e5000000008c493046022100bd5d41662f98cfddc46e86ea7e4a3bc8fe9f1dfc5c4836eaf7df582596cfe0e9022100fc459ae4f59b8279d679003b88935896acd10021b6e2e4619377e336b5296c5e014104c00bab76a708ba7064b2315420a1c533ca9945eeff9754cdc574224589e9113469b4e71752146a10028079e04948ecdf70609bf1b9801f6b73ab75947ac339e5ffffffff02ac4c8bd5000000001976a9148dce8946f1c7763bb60ea5cf16ef514cbed0633b88ac002f6859000000001976a9146a59ac0e8f553f292dfe5e9f3aaa1da93499c15e88ac00000000"));
342
BinaryData txFrag(h2b("01000000020044fbc929d78e4203eed6f1d3d39c0157d8e5c100bbe0886779c0ebf6a69324010000008a47304402206568144ed5e7064d6176c74738b04c08ca19ca54ddeb480084b77f45eebfe57802207927d6975a5ac0e1bb36f5c05356dcda1f521770511ee5e03239c8e1eecf3aed0141045d74feae58c4c36d7c35beac05eddddc78b3ce4b02491a2eea72043978056a8bc439b99ddaad327207b09ef16a8910828e805b0cc8c11fba5caea2ee939346d7ffffffff45c866b219b176952508f8e5aea728f950186554fc4a5807e2186a8e1c4009e5000000008c493046022100bd5d41662f98cfddc46e86ea7e4a3bc8fe9f1dfc5c4836eaf7df582596cfe0e9022100fc459ae4f59b8279d679003b88935896acd10021b6e2e4619377e336b5296c5e014104c00bab76a708ba7064b2315420a1c533ca9945eeff9754cdc574224589e9113469b4e71752146a10028079e04948ecdf70609bf1b9801f6b73ab75947ac339e5ffffffff0200000000"));
343
BinaryData txOut0(h2b("ac4c8bd5000000001976a9148dce8946f1c7763bb60ea5cf16ef514cbed0633b88ac"));
344
BinaryData txOut1(h2b("002f6859000000001976a9146a59ac0e8f553f292dfe5e9f3aaa1da93499c15e88ac"));
347
tx.unserialize(txFull);
351
stxFull.unserialize(txFull, false);
352
stxFrag.unserialize(txFrag, true);
354
assertError(txFull.haveAllTxOut(), "Fragged tx reported having all TxOuts");
355
assertError(!txFrag.haveAllTxOut(), "Full tx reported not having all TxOuts");
359
stxOut0.unserialize(txOut0);
360
stxOut1.unserialize(txOut1);
362
stxFrag.txOutMap_[0] = stxOut0;
363
assertError(!txFrag.haveAllTxOut(), "Fragged tx reported having all TxOuts");
365
stxFrag.txOutMap_[1] = stxOut1;
366
assertError(txFrag.haveAllTxOut(), "Frag-but-full tx reported not having all TxOuts");
368
assertError(stxFrag.getSerializedTx()==txFrag, "stxFrag.getSerializedTx() does not match raw");
369
assertError(stxFrag.getSerializedTx()==stxFull.serialize(), "stxFrag.getTxCopy() does not match serialized tx");
373
stxFrom1.createFromTx(tx, false);
374
stxFrom2.createFromTx(tx, true);
376
assertError(stxFrom1.getSerializedTx()==stxFrom2.getSerializedTx(), "Creating from tx failed");
377
assertError(stxFrom1.getSerializedTx()==txFull, "Creating from tx failed");
383
void TestReadAndOrganizeChain(string blkdir)
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;
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
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;
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;
420
void TestFindNonStdTx(string blkdir)
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...
435
void TestScanForWalletTx(string blkdir)
437
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
438
bdm.SetBlkFileLocation(blkdir, 4, 1);
439
bdm.parseEntireBlockchain();
440
/////////////////////////////////////////////////////////////////////////////
441
BinaryData myAddress;
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);
451
// This address contains a tx with a non-std TxOut, but the other TxOuts are valid
452
myAddress.createFromHex("6c27c8e67b7376f3ab63553fe37a4481c4f951cf"); wlt.addAddress(myAddress);
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);
460
TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
461
TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
462
TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
464
cout << "Checking balance of all addresses: " << wlt.getNumAddr() << " addrs" << endl;
465
for(uint32_t i=0; i<wlt.getNumAddr(); i++)
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++)
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;
481
cout << endl << endl;
485
cout << "Printing SORTED allAddr ledger..." << endl;
487
vector<LedgerEntry> const & ledgerAll = wlt.getTxLedger();
488
for(uint32_t j=0; j<ledgerAll.size(); j++)
491
<< ledgerAll[j].getAddrStr20().toHexStr() << " "
492
<< ledgerAll[j].getValue()/1e8 << " ("
493
<< ledgerAll[j].getBlockNum()
494
<< ") TxHash: " << ledgerAll[j].getTxHash().getSliceCopy(0,4).toHexStr() << endl;
500
/////////////////////////////////////////////////////////////////////////////
501
cout << "Test txout aggregation, with different prioritization schemes" << endl;
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
509
// Main-network addresses
510
myAddress.createFromHex("0e0aec36fe2545fb31a41164fb6954adcd96b342"); myWallet.addAddress(myAddress);
513
//myAddress.createFromHex("d184cea7e82c775d08edd288344bcd663c3f99a2"); myWallet.addAddress(myAddress);
514
//myAddress.createFromHex("205fa00890e6898b987de6ff8c0912805416cf90"); myWallet.addAddress(myAddress);
515
//myAddress.createFromHex("fc0ef58380e6d4bcb9599c5369ce82d0bc01a5c4"); myWallet.addAddress(myAddress);
518
cout << "Rescanning the blockchain for new addresses." << endl;
519
bdm.scanBlockchainForTx(myWallet);
521
//vector<UnspentTxOut> sortedUTOs = bdm.getUnspentTxOutsForWallet(myWallet, 1);
522
vector<UnspentTxOut> sortedUTOs = myWallet.getSpendableTxOutList();
525
cout << " Sorting Method: " << i << endl;
526
cout << " Value\t#Conf\tTxHash\tTxIdx" << endl;
527
for(int j=0; j<sortedUTOs.size(); j++)
530
<< sortedUTOs[j].getValue()/1e8 << "\t"
531
<< sortedUTOs[j].getNumConfirm() << "\t"
532
<< sortedUTOs[j].getTxHash().toHexStr() << "\t"
533
<< sortedUTOs[j].getTxOutIndex() << endl;
538
// Test the zero-conf ledger-entry detection
541
//vector<LedgerEntry> levect = wlt.getAddrLedgerEntriesForTx(txSelf);
542
//for(int i=0; i<levect.size(); i++)
544
//levect[i].pprint();
551
void TestReadAndOrganizeChainWithWallet(string blkdir)
553
cout << endl << "Starting blockchain loading with wallets..." << endl;
554
/////////////////////////////////////////////////////////////////////////////
555
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
556
BinaryData myAddress;
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);
569
myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt1.addAddress(myAddress);
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);
577
vector<BtcWallet*> wltList;
578
wltList.push_back(&wlt1);
579
wltList.push_back(&wlt2);
581
bdm.registerWallet(&wlt1);
582
bdm.registerWallet(&wlt2);
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;
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;
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;
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;
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;
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);
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);
632
cout << endl << "Create new, unregistered wallet, scan it once (should rescan)..." << endl;
634
myAddress.createFromHex("72e20a94d6b2ed34a3b4d3757c1fed5152071993"); wlt3.addAddress(myAddress);
635
wlt3.addAddress(myAddress);
636
bdm.scanBlockchainForTx(wlt3);
640
cout << endl << "Rescan unregistered wallet: addr should be registered, so no rescan..." << endl;
641
bdm.scanBlockchainForTx(wlt3);
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++)
650
vector<RegisteredTx> txList = targAddrVect[i].getTxList();
652
cout << targAddrVect[i].getAddr160().toHexStr() << " "
653
<< txList.size() << endl;
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;
662
// Results for the sent-to address list, as of 09 Apr, 2012
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"
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"
733
BinaryData txHash1 = BinaryData::CreateFromHex("2ec3a745e032c8bcc1061ebf270afcee47318a43462ba57215174084775c794d");
734
BinaryData txHash2 = BinaryData::CreateFromHex("b754fa89f7eb7f7c564611d9297dbcb471cf8d3cb0d235686323b6a5b263b094");
736
if( bdm.getTxRefPtrByHash(txHash1) != NULL &&
737
bdm.getTxRefPtrByHash(txHash2) != NULL)
739
cout << "Testing soft-scanning..." << endl;
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;
747
//cout << "Num Headers: " << bdm.getNumHeaders() << endl;
748
//cout << "Num Tx: " << bdm.getNumTx() << endl;
752
void TestBalanceConstruction(string blkdir)
754
cout << endl << "Starting blockchain loading with wallets..." << endl;
755
/////////////////////////////////////////////////////////////////////////////
756
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
757
BinaryData myAddress;
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);
771
myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt.addAddress(myAddress);
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);
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);
783
bdm.registerWallet(&wlt);
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;
795
cout << endl << "Scanning wallet tx based on initial blockchain scan" << endl;
796
TIMER_WRAP(bdm.scanBlockchainForTx(wlt));
797
cout << "Printing Wallet Ledger" << endl;
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);
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);
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);
817
cout << "SPENDABLE:" << endl;
818
for(uint32_t i=0; i<utxoS.size(); i++)
819
utxoS[i].pprintOneLine(topBlk);
822
void TestReadAndUpdateBlkFile(string tempBlkDir)
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");
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());
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();
849
// Test standard blkfile expansion
850
copyFile(blk3b, blk3);
851
nblk = bdm.readBlkFileUpdate();
852
cout << "New Blocks Read: " << nblk << endl;
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;
861
// Test just blockfile splitting
862
copyFile(blk5s, blk5);
863
nblk = bdm.readBlkFileUpdate();
864
cout << "New Blocks Read: " << nblk << endl;
868
void TestReorgBlockchain(string blkdir)
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
/////////////////////////////////////////////////////////////////////////////
877
// BLOCKCHAIN REORGANIZATION UNIT-TEST
879
/////////////////////////////////////////////////////////////////////////////
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
888
// If you were to set COINBASE_MATURITY=1 (not applicable here)
889
// this would be a *completely valid* blockchain--just a very
892
// FYI: The first block is the *actual* main-network genesis block
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");
900
wlt.addAddress(BinaryData::CreateFromHex("62e907b15cbf27d5425399ebf6f0fb50ebb88f18"));
901
wlt.addAddress(BinaryData::CreateFromHex("ee26c56fc1d942be8d7a24b2a1001dd894693980"));
902
wlt.addAddress(BinaryData::CreateFromHex("cb2abde8bccacc32e893df3a054b9ef7f227a4ce"));
903
wlt.addAddress(BinaryData::CreateFromHex("c522664fb0e55cdc5c0cea73b4aad97ec8343232"));
906
cout << endl << endl;
907
cout << "Preparing blockchain-reorganization test!" << endl;
908
cout << "Resetting block-data mgr...";
910
cout << "Done!" << endl;
911
cout << "Reading in initial block chain (Blocks 0 through 4)..." ;
913
copyFile(blk04, "reorgTest/blk00000.dat");
914
bdm.SetBlkFileLocation("reorgTest", 5, 0);
915
bdm.parseEntireBlockchain();
917
cout << "Done" << endl;
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
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++)
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) ";
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++)
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++)
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) ";
962
// prepare the other block to be read in
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;
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;
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())
984
cout << "Reorg happened after pushing block 5A" << endl;
985
bdm.scanBlockchainForTx(wlt);
986
bdm.updateWalletAfterReorg(wlt);
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++)
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) ";
1003
cout << "Checking balance of all addresses: " << wlt.getNumAddr() << "addrs" << endl;
1004
for(uint32_t i=0; i<wlt.getNumAddr(); i++)
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++)
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) ";
1023
/////////////////////////////////////////////////////////////////////////////
1025
// END BLOCKCHAIN REORG UNIT-TEST
1027
/////////////////////////////////////////////////////////////////////////////
1033
void TestZeroConf(void)
1036
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
1037
BinaryData myAddress;
1041
bdm.SetBlkFileLocation("zctest/blk0001.dat", 4, 1);
1042
bdm.parseEntireBlockchain();
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);
1050
bdm.scanBlockchainForTx(wlt);
1052
bdm.enableZeroConf("zctest/mempool_new.bin");
1053
uint32_t currBlk = bdm.getTopBlockHeader().getBlockHeight();
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);
1060
BinaryData memPool(filesize);
1061
zcIn.read((char*)memPool.getPtr(), filesize);
1063
BinaryRefReader brr(memPool);
1064
cout << "Starting Wallet:" << endl;
1065
bdm.rescanWalletZeroConf(wlt);
1067
while(brr.getSizeRemaining() > 8)
1069
cout << endl << endl;
1070
cout << "Inserting another 0-conf tx..." << endl;
1071
uint64_t txtime = brr.get_uint64_t();
1073
bool wasAdded = bdm.addNewZeroConfTx(zcTx.serialize(), txtime, true);
1076
bdm.rescanWalletZeroConf(wlt);
1078
cout << "UltBal: " << wlt.getFullBalance() << endl;
1079
cout << "SpdBal: " << wlt.getSpendableBalance() << endl;
1080
cout << "UncBal: " << wlt.getUnconfirmedBalance(currBlk) << endl;
1083
cout << "Unspent TxOuts:" << endl;
1084
vector<UnspentTxOut> utxoList = wlt.getSpendableTxOutList(currBlk);
1086
for(uint32_t i=0; i<utxoList.size(); i++)
1088
bal += utxoList[i].getValue();
1089
utxoList[i].pprintOneLine(currBlk);
1091
cout << "Sum of TxOuts: " << bal/1e8 << endl;
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);
1109
////////////////////////////////////////////////////////////////////////////
1110
////////////////////////////////////////////////////////////////////////////
1111
// Start testing balance/wlt update after a new block comes in
1114
bdm.SetBlkFileLocation("zctest/blk0001.dat", 4, 1);
1115
bdm.parseEntireBlockchain();
1116
// More testnet addresses, with only a few transactions
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();
1124
// This will load the memory pool into the zeroConfPool_ in BDM
1125
bdm.enableZeroConf("zctest/mempool.bin");
1127
// Now scan all transactions, which ends with scanning zero-conf
1128
bdm.scanBlockchainForTx(wlt);
1130
wlt.pprintAlot(topBlk, true);
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);
1142
void TestMerkle(void)
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");
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;
1158
cout << " _____0a10_____ \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;
1170
vector<BinaryData> merkleTree = BtcUtils::calculateMerkleTree(txList);
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;
1176
/////////////////////////////////////////////////////////////////////////////
1177
vector<bool> isOurs(7);
1186
cout << "Start serializing a full tree" << endl;
1187
PartialMerkleTree pmtFull(7, &isOurs, &txList);
1188
BinaryData pmtSerFull = pmtFull.serialize();
1190
cout << "Finished serializing (full)" << endl;
1191
cout << "Merkle Root: " << pmtFull.getMerkleRoot().toHexStr() << endl;
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;
1201
cout << "Print Tree:" << endl;
1202
pmtFull2.pprintTree();
1205
/////////////////////////////////////////////////////////////////////////////
1206
cout << "Starting Partial Merkle tree" << endl;
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;
1227
cout << "Print Tree:" << endl;
1230
/////////////////////////////////////////////////////////////////////////////
1231
cout << "Empty tree" << endl;
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;
1254
/////////////////////////////////////////////////////////////////////////////
1255
cout << "Single Node on edge" << endl;
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;
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;
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++)
1289
// Create 100,000 simple hashes
1290
longHash[i] = BinaryData(32);
1291
*(uint32_t*)(longHash[i].getPtr()+28) = i;
1293
longBits[i] = ((i%(testSize/13-1))==0);
1296
TIMER_START("Create 100000 Merkle Tree");
1297
PartialMerkleTree pmtLong(testSize, &longBits, &longHash);
1298
TIMER_STOP("Create 100000 Merkle Tree");
1300
TIMER_START("Serialize 100000 Merkle Tree");
1301
BinaryData longSer = pmtLong.serialize();
1302
TIMER_STOP("Serialize 100000 Merkle Tree");
1304
PartialMerkleTree pmtLong2(testSize);
1306
TIMER_START("Unserialize 100000 Merkle Tree");
1307
pmtLong2.unserialize(longSer);
1308
TIMER_STOP("Unserialize 100000 Merkle Tree");
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;
1321
void TestCrypto(void)
1324
SecureBinaryData a("aaaaaaaaaa");
1325
SecureBinaryData b; b.resize(5);
1326
SecureBinaryData c; c.resize(0);
1334
SecureBinaryData d(a);
1336
cout << "a=" << a.toHexStr() << endl;
1337
cout << "b=" << b.toHexStr() << endl;
1338
cout << "c=" << c.toHexStr() << endl;
1339
cout << "d=" << d.toHexStr() << endl;
1341
SecureBinaryData e("eeeeeeeeeeeeeeee");
1342
SecureBinaryData f("ffffffff");
1343
SecureBinaryData g(0);
1348
cout << "e=" << e.toHexStr() << endl;
1349
cout << "f=" << f.toHexStr() << endl;
1350
cout << "g=" << g.toHexStr() << endl;
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;
1361
kdf.computeKdfParams();
1362
kdf.printKdfParams();
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;
1369
cout << " Password1: '" << passwd1.toBinStr() << "'" << endl;
1370
key = kdf.DeriveKey(passwd1);
1371
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1373
cout << " Password2: '" << passwd2.toBinStr() << "'" << endl;
1374
key = kdf.DeriveKey(passwd2);
1375
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1377
cout << " Password1: '" << passwd3.toBinStr() << "'" << endl;
1378
key = kdf.DeriveKey(passwd3);
1379
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1381
/////////////////////////////////////////////////////////////////////////////
1382
cout << "Executing KDF tests with longer compute time" << endl;
1383
kdf.computeKdfParams(1.0);
1384
kdf.printKdfParams();
1386
cout << " Password1: '" << passwd1.toBinStr() << "'" << endl;
1387
key = kdf.DeriveKey(passwd1);
1388
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1390
cout << " Password2: '" << passwd2.toBinStr() << "'" << endl;
1391
key = kdf.DeriveKey(passwd2);
1392
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1394
cout << " Password1: '" << passwd3.toBinStr() << "'" << endl;
1395
key = kdf.DeriveKey(passwd3);
1396
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1398
/////////////////////////////////////////////////////////////////////////////
1399
cout << "Executing KDF tests with limited memory target" << endl;
1400
kdf.computeKdfParams(1.0, 256*1024);
1401
kdf.printKdfParams();
1403
cout << " Password1: '" << passwd1.toBinStr() << "'" << endl;
1404
key = kdf.DeriveKey(passwd1);
1405
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1407
cout << " Password2: '" << passwd2.toBinStr() << "'" << endl;
1408
key = kdf.DeriveKey(passwd2);
1409
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1411
cout << " Password1: '" << passwd3.toBinStr() << "'" << endl;
1412
key = kdf.DeriveKey(passwd3);
1413
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1415
/////////////////////////////////////////////////////////////////////////////
1416
cout << "KDF with min memory requirement (1 kB)" << endl;
1417
kdf.computeKdfParams(1.0, 0);
1418
kdf.printKdfParams();
1420
cout << " Password1: '" << passwd1.toBinStr() << "'" << endl;
1421
key = kdf.DeriveKey(passwd1);
1422
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1424
cout << " Password2: '" << passwd2.toBinStr() << "'" << endl;
1425
key = kdf.DeriveKey(passwd2);
1426
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1428
cout << " Password1: '" << passwd3.toBinStr() << "'" << endl;
1429
key = kdf.DeriveKey(passwd3);
1430
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1432
/////////////////////////////////////////////////////////////////////////////
1433
cout << "KDF with 0 compute time" << endl;
1434
kdf.computeKdfParams(0, 0);
1435
kdf.printKdfParams();
1437
cout << " Password1: '" << passwd1.toBinStr() << "'" << endl;
1438
key = kdf.DeriveKey(passwd1);
1439
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1441
cout << " Password2: '" << passwd2.toBinStr() << "'" << endl;
1442
key = kdf.DeriveKey(passwd2);
1443
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
1445
cout << " Password1: '" << passwd3.toBinStr() << "'" << endl;
1446
key = kdf.DeriveKey(passwd3);
1447
cout << " MasterKey: '" << key.toHexStr() << endl << endl;
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");
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;
1466
/// *** Test 2 *** ///
1467
cout << endl << endl;
1468
testKey.createFromHex ("0000000000000000000000000000000000000000000000000000000000000000");
1469
testIV.createFromHex ("014730f80ac625fe84f026c60bfd547d");
1470
plaintext.createFromHex ("00000000000000000000000000000000");
1471
cipherTarg.createFromHex("5c9d844ed46f9885085e5d6a4f94c7d7");
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;
1480
/// *** Test 3 *** ///
1481
cout << endl << endl;
1482
testKey.createFromHex ("ffffffffffff0000000000000000000000000000000000000000000000000000");
1483
testIV.createFromHex ("00000000000000000000000000000000");
1484
plaintext.createFromHex ("00000000000000000000000000000000");
1485
cipherTarg.createFromHex("225f068c28476605735ad671bb8f39f3");
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;
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.
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;
1512
// Now encrypting so I can store the encrypted data in file
1513
cout << "Encrypting again:" << endl;
1514
cipher = CryptoAES().EncryptCFB(secret, testKey, randIV);
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;
1526
ifstream infile("safefile.txt", ios::in);
1527
uint32_t mem, nIters;
1528
SecureBinaryData salt, iv;
1533
infile >> deadstr >> mem;
1534
infile >> deadstr >> nIters;
1535
infile >> deadstr >> hexstr;
1536
salt.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
1538
infile >> deadstr >> hexstr;
1539
iv.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
1540
infile >> deadstr >> hexstr;
1541
cipher.copyFrom( SecureBinaryData::CreateFromHex(string(hexstr, 64)));
1543
cout << endl << endl;
1545
// Will try this twice, once with correct passphrase, once without
1546
SecureBinaryData cipherTry1 = cipher;
1547
SecureBinaryData cipherTry2 = cipher;
1548
SecureBinaryData newKey;
1550
KdfRomix newKdf(mem, nIters, salt);
1551
newKdf.printKdfParams();
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);
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);
1572
void TestECDSA(void)
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);
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;
1585
SecureBinaryData signature = CryptoECDSA().SignData(msgToSign, privKey);
1586
cout << "Signature = " << signature.toHexStr() << endl;
1589
bool isValid = CryptoECDSA().VerifyData(msgToSign, signature, pubKey);
1590
cout << "SigValid? = " << (isValid ? 1 : 0) << endl;
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;
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++)
1612
// This timing includes key parsing
1613
CryptoECDSA().SignData(msgToSign, privData);
1615
TIMER_STOP("SigningTime");
1617
// Test speed of verification
1618
TIMER_START("VerifyTime");
1619
cout << "\nTiming Verify";
1620
for(uint32_t i=0; i<nTest; i++)
1622
// This timing includes key parsing
1623
CryptoECDSA().VerifyData(msg, sig, pub65);
1625
TIMER_STOP("VerifyTime");
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;
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;
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;
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;
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;
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);
1680
void TestPointCompression(void)
1682
vector<BinaryData> testPubKey(3);
1683
testPubKey[0].createFromHex("044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1");
1684
testPubKey[1].createFromHex("04ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bdedc416f5cefc1db0625cd0c75de8192d2b592d7e3b00bcfb4a0e860d880fd1fc");
1685
testPubKey[2].createFromHex("042596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3ed0a9004acf927666eee18b7f5e8ad72ff100a3bb710a577256fd7ec81eb1cb3");
1687
CryptoPP::ECP & ecp = CryptoECDSA::Get_secp256k1_ECP();
1688
for(uint32_t i=0; i<3; i++)
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);
1695
BinaryData ptFlat(65);
1696
BinaryData ptComp(33);
1698
ecp.EncodePoint((byte*)ptFlat.getPtr(), ptPub, false);
1699
ecp.EncodePoint((byte*)ptComp.getPtr(), ptPub, true);
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;
1717
void TestReadBlkFileUpdate(string testblockdir, string blkdir)
1719
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
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");
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");
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());
1745
copyFile(srcs[0], dsts[0]);
1746
bdm.SetBlkFileLocation(blkdir, 5, 0);
1747
bdm.parseEntireBlockchain();
1748
cout << "Top Block: " << bdm.getTopBlockHeight() << endl;
1752
// TEST 1 -- Add one block
1753
copyFile(srcs[1], dsts[1]);
1754
bdm.readBlkFileUpdate();
1755
cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
1757
// TEST 2 -- Add 3 blocks
1758
copyFile(srcs[2], dsts[2]);
1759
bdm.readBlkFileUpdate();
1760
cout << "Read block update " << t++ << ": " << bdm.getTopBlockHeight() << endl;
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;
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;
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;
1780
void TestOutOfOrder(string blkdir)
1782
/////////////////////////////////////////////////////////////////////////////
1783
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
1784
BinaryData myAddress;
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);
1796
//myAddress.createFromHex("4975703dc910107e2cc1321e632d136803e218e8"); wlt.addAddress(myAddress);
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);
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);
1808
bdm.registerWallet(&wlt);
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;
1819
myAddress.createFromHex("11b366edfc0a8b66feebae5c2e25a7b6a5d1cf31"); wlt.addAddress(myAddress);
1820
myAddress.createFromHex("e826f4a4381453dcdcf9bfeedffe95de7c86ccbd"); wlt.addAddress(myAddress);
1822
bdm.scanBlockchainForTx(wlt);
1828
void TestLevelDB(string testLDBDir, string blkfilepath)
1831
leveldb::Options opts;
1833
// Setup the optoins for this particular database
1834
opts.create_if_missing = true;
1835
//opts.filter_policy = NewBloomFilter(10);
1838
leveldb::Status stat = leveldb::DB::Open(opts, testLDBDir.c_str(), &ldb);
1839
assert(leveldb::ldbCheckStatus(stat));
1841
for(uint32_t i=0; i<10; i++)
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 );
1850
cout << "Inserting: (" << insertKey.toHexStr() << ","
1851
<< insertVal.toHexStr() << ")" << endl;
1853
stat = ldb->Put(leveldb::WriteOptions(),
1854
insertKey.toBinStr(),
1855
insertVal.toBinStr());
1856
assert(leveldb::ldbCheckStatus(stat));
1859
leveldb::Iterator* it = ldb->NewIterator(leveldb::ReadOptions());
1861
for(it->SeekToFirst(); it->Valid(); it->Next())
1863
BinaryData key(it->key().ToString());
1864
BinaryData val(it->value().ToString());
1865
cout << idx++ << ": " << key.toHexStr() << ": " << val.toHexStr() << endl;
1868
cout << "Keys in DB: " << idx-1 << endl;
1871
stat = ldb->Get(leveldb::ReadOptions(), "MyKey", &val2);
1872
leveldb::ldbCheckStatus(stat);
1873
cout << "Plowed through the error..." << endl;
1876
//delete opts.filter_policy;
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));
1885
ifstream is(blkfilepath.c_str(), ios::in | ios::binary);
1886
assert(is.is_open());
1888
uint64_t filesize = BtcUtils::GetFileSize(blkfilepath);
1889
BinaryStreamBuffer bsb;
1890
bsb.attachAsStreamBuffer(is, filesize);
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())
1899
while(bsb.reader().getSizeRemaining() > 8)
1903
bsb.reader().advance(4);
1904
nextBlkSize = bsb.reader().get_uint32_t();
1908
if(bsb.reader().getSizeRemaining() < nextBlkSize)
1910
alreadyRead8B = true;
1913
alreadyRead8B = false;
1915
BinaryRefReader brr(bsb.reader().getCurrPtr(), nextBlkSize);
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);
1923
stat = ldb->Put(leveldb::WriteOptions(),
1924
headerHash.toBinStr(),
1925
headerRaw.toBinStr());
1926
assert(leveldb::ldbCheckStatus(stat));
1929
uint32_t nTx = brr.get_var_int();
1930
for(uint32_t itx=0; itx<nTx; itx++)
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);
1938
stat = ldb->Put(leveldb::WriteOptions(),
1941
assert(leveldb::ldbCheckStatus(stat));
1945
nBytesRead += nextBlkSize;
1946
bsb.reader().advance(nextBlkSize);
1948
if(nBlkRead % 5000 == 0)
1949
cout << nBlkRead << " blocks read..." << endl;
1952
TIMER_STOP("NaiveScan");
1958
void TestLDBScanBlockchain(string testdbpath)
1960
leveldb::Options opts;
1961
opts.create_if_missing = true;
1962
opts.compression = leveldb::kNoCompression;
1965
leveldb::Status stat = leveldb::DB::Open(opts, testdbpath.c_str(), &ldb);
1966
assert(leveldb::ldbCheckStatus(stat));
1969
map<BinaryData, int> addrMap;
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;
1977
map<OutPoint, uint64_t> unspentOutPoints;
1979
leveldb::Iterator* it = ldb->NewIterator(leveldb::ReadOptions());
1981
vector<uint32_t> offsetsIn;
1982
vector<uint32_t> offsetsOut;
1984
TIMER_START("Rescan_from_LevelDB");
1987
cout << "Entry Lengths: ";
1988
for(it->SeekToFirst(); it->Valid(); it->Next())
1990
BinaryData val(it->value().ToString());
1991
if(val.getSize()==80) // need to add another condition
1994
uint32_t txLen = BtcUtils::TxCalcLength(val.getPtr(), &offsetsIn, &offsetsOut);
1998
for(uint32_t iout=0; iout<offsetsOut.size()-1; iout++)
2000
static uint8_t scriptLenFirstByte;
2001
static HashString addr20(20);
2003
uint8_t const * ptr = (val.getPtr() + offsetsOut[iout] + 8);
2004
scriptLenFirstByte = *(uint8_t*)ptr;
2005
if(scriptLenFirstByte == 25)
2007
// Std TxOut with 25-byte script
2008
addr20.copyFrom(ptr+4, 20);
2009
if( addrMap.find(addr20) != addrMap.end() )
2011
uint64_t val = *(uint64_t*)(ptr-8);
2012
cout << " Received a TxOut! " << val/1e8 << endl;
2014
op.setTxHash(it->key().ToString());
2015
op.setTxOutIndex(iout);
2016
unspentOutPoints[op] = val;
2019
else if(scriptLenFirstByte==67)
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() )
2026
uint64_t val = *(uint64_t*)(ptr-8);
2027
cout << " Received a TxOut!" << val/1e8 << endl;
2029
op.setTxHash(it->key().ToString());
2030
op.setTxOutIndex(iout);
2031
unspentOutPoints[op] = val;
2040
if(++nObj % 50000 == 0)
2041
cout << "Processed " << nObj << " tx " << endl;
2044
for(it->SeekToFirst(); it->Valid(); it->Next())
2046
BinaryData val(it->value().ToString());
2047
if(val.getSize()==80) // need to add another condition
2050
uint32_t txLen = BtcUtils::TxCalcLength(val.getPtr(), &offsetsIn, &offsetsOut);
2053
map<OutPoint, uint64_t>::iterator iter;
2054
for(uint32_t iin=0; iin<offsetsIn.size()-1; iin++)
2056
op.unserialize(val.getPtr() + offsetsIn[iin]);
2057
iter = unspentOutPoints.find(op);
2058
if(iter != unspentOutPoints.end())
2060
cout << " Spent a TxOut! " << endl;
2061
allbtc -= iter->second;
2062
unspentOutPoints.erase(iter);
2067
TIMER_STOP("Rescan_from_LevelDB");
2068
cout << "Total TxOuts: " << allbtc/1e8 << endl;
2074
void TestLdbBlockchainUtils(string blkdir)
2076
BlockDataManager_LevelDB & bdm = BlockDataManager_LevelDB::GetInstance();
2077
bdm.SetBlkFileLocation(blkdir, 4, 1);
2079
string pathH("testldb/ldbtestHeaders");
2080
string pathT("testldb/ldbtestTx");
2081
string pathR("testldb/ldbtestTransient");
2083
//bdm.setLevelDBPaths(pathH, pathT, pathR);