-
Notifications
You must be signed in to change notification settings - Fork 2
/
Operate_Wallet.cxx
293 lines (242 loc) · 8.01 KB
/
Operate_Wallet.cxx
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/* Operate_Wallet.cxx */
/* ====================================================================
* SOURCE FILE FOR LAUNCHING THE WALLET PROGRAM(AFTER INITIALIZATION).
*
* !!! WARNINGS !!! PLEASE READ !!!
*
* MAKE SURE YOU FIRST INITIALIZE THE WALLET OR THE PROGRAM MIGHT FAIL.
*
* A PASSWORD IS REQUIRED IN ORDER TO USE THE WALLET, BUT THE PROGRAM
* WILL NOT INFORM THE USER WHETHER THE PASSWORD IS CORRECT OR NOT. THIS
* IS DONE TO PREVENT A BRUTE FORCE ATTACK. IF YOU DO NOT HAVE A VALID
* PASSWORD, THE TRANSACTIONS CREATED WILL BE INVALID AND THEREFORE NEVER
* MINED BY BITCOIN NETWORK PEERS.
* ====================================================================
*
* BUILD COMMAND: g++ -Wall -o runSafeBook Operate_Wallet.cxx btcTools.cxx btcStructs.cxx -lcrypto -lssl
* RUN COMMAND: ./runSafeBook
*
*/
#include "btcStructs.h"
#include "btcTools.h"
#include <boost/multiprecision/cpp_int.hpp>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <openssl/ec.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cmath>
#include <iomanip>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include <limits>
using namespace std;
using namespace boost::multiprecision;
typedef vector<unsigned char>::iterator vbit;
int simple_rng(size_t maxv) {
// A simple random number generator.
int rnum;
srand(time(NULL));
rnum = rand() % maxv;
return rnum;
}
double wallet_balance(vector<UTXO>& t_utxo_set) {
// calculate the current balance of the wallet.
double balance;
for (size_t i = 0; i < t_utxo_set.size(); ++i) {
if (t_utxo_set[i].good())
{balance += t_utxo_set[i].get_balance();}
}
if (balance < 0.00000001) {balance = 0;}
return balance;
}
void display_help() {
// display command options.
cout << "\n----- Command Options -----\n" << endl;
cout << "-h display help" << endl;
cout << "-r get a receive address" << endl;
cout << "-b display your current balance" << endl;
cout << "-u load a new UTXO into the wallet" << endl;
cout << "-s send Bitcoin to another address" << endl;
cout << "-q end the session and quit" << endl;
cout << "\n----- END -----\n" << endl;
}
void get_address(vector<string>& t_addr_set) {
// return a randomly chosen Bitcoin address from the wallet.
string address;
size_t ksize = t_addr_set.size();
address = t_addr_set[simple_rng(ksize)];
cout << "\nReceive address: " << address << "\n" << endl;
}
string get_address_c(vector<string>& t_addr_set) {
// for internal function use.
string address;
size_t ksize = t_addr_set.size();
address = t_addr_set[simple_rng(ksize)];
cout << "Change address: " << address << endl;
return address;
}
void new_utxo(vector<UTXO>& t_utxo_set) {
// add a new UTXO to the set after your wallet is paid Bitcoin.
char cf;
string id, addr;
int ix;
double amt;
cout << "\nEnter the transaction ID: " << endl;
cin >> id;
cout << "Enter the output index: " << endl;
cin >> ix;
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "invalid entry. Enter a numeric:" << endl;
cin >> ix;
}
cout << "Enter the receiving address (from your current wallet only!): " << endl;
cin >> addr;
cout << "Enter the amount in BTC: " << endl;
cin >> amt;
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "invalid entry. Enter a numeric:" << endl;
cin >> amt;
}
cout << "\nAre your sure the information is correct and ";
cout << "want to continue?(Y/N)?" << endl;
cin >> cf;
if (cf == 'Y' or cf == 'y')
{t_utxo_set.push_back(UTXO(id, addr, "YES", ix, amt));
cout << "\nCompleted.\n" << endl;}
else {cout << "Aborted.\n" << endl;}
}
void new_transaction(vector<UTXO>& t_utxo_set, vector<string>& t_wif_set, vector<string>& t_addr_set) {
// generate the raw byte data for a new transaction for sending Bitcoin.
char cg, cf;
string radd, cadd;
double txpay, txfee;
cout << "\nEnter the recipient's address: " << endl;
cin >> radd;
cout << "Use a random change address?(Y/N)?" << endl;
cin >> cg;
if (cg == 'Y' or cg == 'y')
{cadd = get_address_c(t_addr_set);}
else {cout << "Enter the change address: " << endl; cin >> cadd;}
cout << "Enter the amount you wish to send in BTC: " << endl;
cin >> txpay;
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "invalid entry. Enter a numeric:" << endl;
cin >> txpay;
}
cout << "Enter the transaction fee in BTC: " << endl;
cin >> txfee;
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "invalid entry. Enter a numeric:" << endl;
cin >> txfee;
}
cout << "\nAre you sure the information is correct and ";
cout << "want to continue?(Y/N)?" << endl;
cin >> cf;
if (cf == 'Y' or cf == 'y') {
if (wallet_balance(t_utxo_set) > (txpay + txfee)) {
cout << "\nOK, processing your request......\n" << endl;
create_raw_transaction(t_utxo_set, t_wif_set, radd, cadd, txpay, txfee);
cout << "\nWould you like to register the change as a new UTXO?(Y/N)" << endl;
cin >> cg;
if (cg == 'Y' or cg == 'y') {
t_utxo_set[t_utxo_set.size() - 1].activate();
cout << "\nOutput loaded and activated.\n" << endl;
}
else {cout << "\nYou can add this UTXO later after network confirmation.\n" << endl;}
}
else {cout << "\nCan't proceed due to insufficient balance.\n" << endl;}
}
else {cout << "Aborted.\n" << endl;}
}
int main() {
cout << "\n========== SAFEBOOK OFFLINE OPERATION ==========\n" << endl;
cout << "***WARNING***" << endl;
cout << "MAKE SURE YOUR MACHINE IS DISCONNECTED.\n" << endl;
ifstream pkhFile("wallet_data/Addresses.txt");
ifstream cp6File("wallet_data/Cipher_Keys.txt");
ifstream utxoFile("wallet_data/UTXOs.txt");
if (pkhFile.good() and cp6File.good() and utxoFile.good()) {
// load UTXOs and back up the data.
cout << "Backing up UTXOs file......" << endl;
vector<UTXO> utxo_set;
string a, b, c, dd, ee;
int d; double e;
while (utxoFile >> a >> b >> c >> dd >> ee) {
stringstream(dd) >> d;
stringstream(ee) >> e;
utxo_set.push_back(UTXO(a, b, c, d, e));
}
ofstream utxoBack("wallet_data/UTXOs.txt.bak");
if (utxoBack) {
for (size_t i = 0; i < utxo_set.size(); ++i)
{utxo_set[i].export_to_file(utxoBack);}
}
utxoBack.close();
utxoFile.close();
cout << "Done.\n" << endl;
// load wallet data and decrypt keys.
string pw, tm;
cout << "Please enter your password: " << endl;
cin >> pw;
cout << "\nOK, decrypting keys......" << endl;
vector<string> addr_set, wif_set;
while (pkhFile >> tm)
{addr_set.push_back(tm);}
while (cp6File >> tm) {
tm = priv_to_wif_comp(cipher6p_decrypt(tm, pw));
wif_set.push_back(tm);
}
pkhFile.close();
cp6File.close();
cout << "Done.\n" << endl;
cout << "Your wallet is now ready for use." << endl;
cout << "Your current balance: " << wallet_balance(utxo_set) << " BTC\n" << endl;
// main operation loop for the application.
cout << "Enter a user command to perform action. Enter -h for help." << endl;
string cmd;
while (true) {
cout << "$ ";
cin >> cmd;
if (cmd == "-h")
{display_help();}
else if (cmd == "-r")
{get_address(addr_set);}
else if (cmd == "-b")
{cout << "\nYour current balance: " << wallet_balance(utxo_set) << " BTC\n" << endl;}
else if (cmd == "-u")
{new_utxo(utxo_set);}
else if (cmd == "-s")
{new_transaction(utxo_set, wif_set, addr_set);}
else if (cmd == "-q")
{break;}
else {cout << "\nInvalid command.\n" << endl;}
}
// export the new UTXO data and exit.
ofstream utxoEx("wallet_data/UTXOs.txt");
cout << "\nRefreshing UTXO list......" << endl;
if (utxoEx) {
for (size_t i = 0; i < utxo_set.size(); ++i)
{utxo_set[i].export_to_file(utxoEx);}
}
utxoEx.close();
cout << "Done." << endl;
cout << "\nSession ended successfully.\n" << endl;
}
else {cout << "No wallet data found. Please initialize first.\n" << endl;}
return 0;
}