-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDbWrapper.cpp
More file actions
95 lines (85 loc) · 2.55 KB
/
DbWrapper.cpp
File metadata and controls
95 lines (85 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <stdexcept>
#include <memory>
#include <fstream>
#include "DbWrapper.h"
#include "utils.h"
#include "Utxo.h"
#include "DbWrapperException.h"
DBWrapper::DBWrapper(const std::filesystem::path& dbName)
: m_dbName(dbName)
{
m_options = leveldb::Options();
openDB();
setObfuscationKey();
}
DBWrapper::~DBWrapper()
{
delete m_db;
}
void DBWrapper::setObfuscationKey()
{
m_obfuscationKeyKey = {0x0e, 0x00};
m_obfuscationKeyKey += "obfuscate_key";
std::string obfuscationKeyString;
read(m_obfuscationKeyKey, obfuscationKeyString);
utils::stringToHexBytes(obfuscationKeyString, m_obfuscationKey);
m_obfuscationKey.erase(m_obfuscationKey.begin());
}
void DBWrapper::openDB()
{
if (m_dbName.empty()) {
throw std::invalid_argument{"No database specified"};
}
// Check that the provided path exists
std::filesystem::path p = m_dbName;
p.append("LOCK");
if (!std::filesystem::exists(p)) {
throw DbWrapperException("The provided path is not a LevelDB database.");
}
leveldb::Status status = leveldb::DB::Open(m_options, m_dbName.string(), &m_db);
if (!status.ok()) {
throw DbWrapperException("Can't open the specified database.");
}
m_readOptions.verify_checksums = true;
}
void DBWrapper::read(const std::string& key, std::string& val)
{
leveldb::Status status = m_db->Get(m_readOptions, key, &val);
if (!m_status.ok()) {
std::string errMsg("Error reading obfuscation key");
errMsg += ". ";
errMsg += m_status.ToString();
throw DbWrapperException(errMsg.c_str());
}
}
void DBWrapper::dumpAllUTXOs(const std::filesystem::path& path) {
std::unique_ptr<leveldb::Iterator> it(m_db->NewIterator(m_readOptions));
std::ofstream file(path);
for (it->SeekToFirst(); it->Valid(); it->Next()) {
const size_t keySize = 33;
auto key = it->key();
const char* keyData = key.data();
if (keyData[0] == 'C') { // from the https://en.bitcoin.it/wiki/Bitcoin_Core_0.11_(ch_2):_Data_Storage
BytesVec deObfuscatedValue;
deObfuscatedValue.reserve(it->value().size());
deObfuscate(it->value(), deObfuscatedValue);
Varint v(deObfuscatedValue);
BytesVec txid;
assert(key.size() > keySize);
txid.insert(txid.begin(), keyData + 1, keyData + keySize);
utils::switchEndianness(txid);
UTXO u(v);
if (u.getAmount()) {
u.setTXID(txid);
const auto& pubKey = u.getPublicKey();
std::string scriptPubKeyStr;
utils::bytesToHexstring(pubKey, scriptPubKeyStr);
file << scriptPubKeyStr << "," << u.getAmount() << std::endl;
}
}
}
if (!it->status().ok()) {
throw DbWrapperException("Can't parse all UTXOS");
}
}