mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
Compare commits
654 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e0c5e3778 | ||
|
|
23e7583a8c | ||
|
|
b90b8159db | ||
|
|
bd05d057eb | ||
|
|
c58ff3781d | ||
|
|
57ca021e7e | ||
|
|
4bd6299efd | ||
|
|
fcbeaff8d0 | ||
|
|
414e0407df | ||
|
|
7c1773cf37 | ||
|
|
28a498d5a6 | ||
|
|
2d90330d8c | ||
|
|
4d87a33eae | ||
|
|
63ee422ab3 | ||
|
|
469f6da8bc | ||
|
|
87593b9837 | ||
|
|
4aa8021a96 | ||
|
|
db4036a829 | ||
|
|
5e322a72f9 | ||
|
|
6ec9d30905 | ||
|
|
3703150d56 | ||
|
|
8f0c0c16d3 | ||
|
|
1bc2f0a37b | ||
|
|
276cfd8530 | ||
|
|
0b1fda6f65 | ||
|
|
ca39829ecb | ||
|
|
a973e225e7 | ||
|
|
5482b5d23b | ||
|
|
1903033bad | ||
|
|
b825e816e4 | ||
|
|
01ed45cbbc | ||
|
|
9849f50b68 | ||
|
|
9a48f56fb0 | ||
|
|
722ff53718 | ||
|
|
af413c0a0f | ||
|
|
a0ea95d3ce | ||
|
|
fdd907c9f1 | ||
|
|
7c4de78a5c | ||
|
|
82a227b263 | ||
|
|
17badef789 | ||
|
|
a49927a46d | ||
|
|
d67b0434f2 | ||
|
|
3b36da6d27 | ||
|
|
a2de1ea2d5 | ||
|
|
b6862f7b74 | ||
|
|
d7534272c6 | ||
|
|
8a39b0d613 | ||
|
|
087fc28f7d | ||
|
|
58ac600b2c | ||
|
|
b2de28c740 | ||
|
|
d11488abd0 | ||
|
|
e10622d129 | ||
|
|
334668cde4 | ||
|
|
c45c2c380d | ||
|
|
77b0f86a43 | ||
|
|
fba681519a | ||
|
|
3a05f1d2ce | ||
|
|
738592a002 | ||
|
|
c455aec699 | ||
|
|
10593f3be1 | ||
|
|
dc15d56b2d | ||
|
|
0d174e130b | ||
|
|
182738e177 | ||
|
|
7532c476fe | ||
|
|
d306fd833c | ||
|
|
7700b94d33 | ||
|
|
7515f00aa3 | ||
|
|
9e52f51223 | ||
|
|
93b5eff274 | ||
|
|
99101685f6 | ||
|
|
40fd689eb1 | ||
|
|
aaff04791d | ||
|
|
f0f1b3775e | ||
|
|
ca0816152d | ||
|
|
91b13a0dff | ||
|
|
8f9123a157 | ||
|
|
8fa3259664 | ||
|
|
cd0527453b | ||
|
|
35a07f8ec4 | ||
|
|
fac3476993 | ||
|
|
18b4eccddb | ||
|
|
8ff1873096 | ||
|
|
b481373001 | ||
|
|
1fa846bbb6 | ||
|
|
b803009c84 | ||
|
|
60953d05c8 | ||
|
|
6bcefc1338 | ||
|
|
afff998ef0 | ||
|
|
2403bb79bc | ||
|
|
eb3f661add | ||
|
|
5e27f737fa | ||
|
|
05ff9680ba | ||
|
|
dfdaee9310 | ||
|
|
5cbe24202a | ||
|
|
293f2644ff | ||
|
|
486f7c8f65 | ||
|
|
e38d492822 | ||
|
|
9b661e57bf | ||
|
|
457ff3a437 | ||
|
|
5da2dce524 | ||
|
|
700e5a4d86 | ||
|
|
adecb2ea00 | ||
|
|
e2b9bf9e6e | ||
|
|
b94e6eb5a5 | ||
|
|
d41f22cb76 | ||
|
|
607739befb | ||
|
|
479c99022e | ||
|
|
65077e1177 | ||
|
|
ee932c6e35 | ||
|
|
c328c684c2 | ||
|
|
57cd445e95 | ||
|
|
a1a5a89063 | ||
|
|
b2e5f797b5 | ||
|
|
6a89317f62 | ||
|
|
ad5a4c7c47 | ||
|
|
cae1a68267 | ||
|
|
397737b913 | ||
|
|
1210aa435f | ||
|
|
e23a121afe | ||
|
|
6789e99e4f | ||
|
|
e099e1568a | ||
|
|
4898482915 | ||
|
|
8edec3f9d6 | ||
|
|
e6578e7fa7 | ||
|
|
ca97bde8ff | ||
|
|
8a6329a7ac | ||
|
|
50d710496d | ||
|
|
e19ccfa657 | ||
|
|
6d25b0e99a | ||
|
|
3ee5f8aac3 | ||
|
|
68103043ce | ||
|
|
bd51e8ef8a | ||
|
|
1c94f88d5e | ||
|
|
f8e4d43be7 | ||
|
|
00d971e1e7 | ||
|
|
810b4fad7d | ||
|
|
be8651dde7 | ||
|
|
1fb6e2d9bf | ||
|
|
ec4997d48f | ||
|
|
0acb1e715c | ||
|
|
6974aff668 | ||
|
|
6c055e506d | ||
|
|
813dc92cdc | ||
|
|
3a70f3a4ec | ||
|
|
655b1b0cc2 | ||
|
|
dd02f3ca6e | ||
|
|
824e8dde8b | ||
|
|
b7a2b6e1aa | ||
|
|
0acbe31cfc | ||
|
|
cedcec2dec | ||
|
|
5ad4028050 | ||
|
|
8ba4282c3f | ||
|
|
e5f43fe309 | ||
|
|
ccfcdc2e3d | ||
|
|
2b4d7735b6 | ||
|
|
c18b82d5db | ||
|
|
3eb5fdbf5f | ||
|
|
aff6456e8a | ||
|
|
ea22a380de | ||
|
|
dfac636fd7 | ||
|
|
282e3ffe6e | ||
|
|
2c31cfc271 | ||
|
|
dfead66eac | ||
|
|
27d4b53a5c | ||
|
|
b2997dc043 | ||
|
|
287ce61dc2 | ||
|
|
42ce57687a | ||
|
|
fdb204abb1 | ||
|
|
9e71a5cd23 | ||
|
|
08e663d7e2 | ||
|
|
e1ea3ce7aa | ||
|
|
cfc45319fe | ||
|
|
83743ed681 | ||
|
|
5e9dc15360 | ||
|
|
c21121752d | ||
|
|
07d1a50aee | ||
|
|
c2e8c8acd8 | ||
|
|
735a60698c | ||
|
|
5aa0b23825 | ||
|
|
1d8c7a9557 | ||
|
|
c0a0a93d02 | ||
|
|
7bd9c3a3cf | ||
|
|
ef758662c5 | ||
|
|
faf705a42a | ||
|
|
a2d0fcbe38 | ||
|
|
f4203de302 | ||
|
|
66116c3847 | ||
|
|
a93ab87787 | ||
|
|
d0fe14ffec | ||
|
|
c43a9ea77d | ||
|
|
e5b980d72f | ||
|
|
8104274701 | ||
|
|
bd043f19c8 | ||
|
|
457661f640 | ||
|
|
7dbe393629 | ||
|
|
d5eb41fa08 | ||
|
|
febe76e316 | ||
|
|
8449a8788a | ||
|
|
6a7a42be16 | ||
|
|
88dc2d6c6a | ||
|
|
b6c837cbe1 | ||
|
|
cdcc319c2d | ||
|
|
7be8b2ff9c | ||
|
|
e46704dd90 | ||
|
|
9862229d4d | ||
|
|
dc42bf52c1 | ||
|
|
00b9c0f4b2 | ||
|
|
9553c35d89 | ||
|
|
3b9e6b7820 | ||
|
|
871c3557bf | ||
|
|
8c8e8c2e93 | ||
|
|
a6fa147c8d | ||
|
|
e401e5eb79 | ||
|
|
ac4161e25d | ||
|
|
559fc3c610 | ||
|
|
031eae7864 | ||
|
|
dc588faf59 | ||
|
|
7f34351910 | ||
|
|
1b7e5cbcad | ||
|
|
2abd083ea4 | ||
|
|
0c3aa881e2 | ||
|
|
774e9b6dbb | ||
|
|
ef2f3ddaf7 | ||
|
|
d506c160eb | ||
|
|
1175d8f6a1 | ||
|
|
0a83c0fcef | ||
|
|
c23617fef3 | ||
|
|
caeddc5d37 | ||
|
|
1ffeb89a52 | ||
|
|
6b6aaa1698 | ||
|
|
ccd65d4261 | ||
|
|
9eace6b113 | ||
|
|
ed6d0b5f85 | ||
|
|
b97d54355e | ||
|
|
12570da46f | ||
|
|
e873dc654c | ||
|
|
c581cc16bb | ||
|
|
ce8c93498a | ||
|
|
8bff8ac079 | ||
|
|
7fa3ad83a9 | ||
|
|
4941aad657 | ||
|
|
8f2b50f178 | ||
|
|
dd21ce5f1b | ||
|
|
ea9627979e | ||
|
|
865a0c1674 | ||
|
|
e2ce6438a9 | ||
|
|
7a5452ffb3 | ||
|
|
088a13331b | ||
|
|
3374c3ef09 | ||
|
|
e73b792b1a | ||
|
|
79fc752b61 | ||
|
|
1bdfa94a01 | ||
|
|
8460185dec | ||
|
|
9c236a945c | ||
|
|
678a319888 | ||
|
|
0aa0bb1ead | ||
|
|
fdcafa3535 | ||
|
|
5f4fee559e | ||
|
|
c4381587a6 | ||
|
|
85e975f379 | ||
|
|
f650d62fc6 | ||
|
|
401db6d96b | ||
|
|
9fb89c26f3 | ||
|
|
0dd710acb6 | ||
|
|
c3fad8350b | ||
|
|
3a78f82a78 | ||
|
|
c376ac359e | ||
|
|
ab9dc75a18 | ||
|
|
ca4c4c53a8 | ||
|
|
d01903e751 | ||
|
|
8e45ed66dd | ||
|
|
235507ae48 | ||
|
|
5a701eb7ea | ||
|
|
7c3db2129e | ||
|
|
cb1035a008 | ||
|
|
79940a6793 | ||
|
|
e962c7f532 | ||
|
|
b7566fe29c | ||
|
|
b557c17a37 | ||
|
|
fced2231f8 | ||
|
|
9ea8e60a0c | ||
|
|
c99ddfaa22 | ||
|
|
da7bbd9dfd | ||
|
|
6642ffb761 | ||
|
|
2e120f28e0 | ||
|
|
11cd416525 | ||
|
|
76d8170ce8 | ||
|
|
87207a2e08 | ||
|
|
8add7822ce | ||
|
|
1f29d399f4 | ||
|
|
f9f625fb32 | ||
|
|
2eb665c634 | ||
|
|
02a38ac22b | ||
|
|
f2862f1a49 | ||
|
|
a558054709 | ||
|
|
1f91797535 | ||
|
|
e88b6b341d | ||
|
|
278074eb23 | ||
|
|
760d9480ed | ||
|
|
a7a0c7a1bf | ||
|
|
6f6f524f1a | ||
|
|
22014c31e5 | ||
|
|
46ba858817 | ||
|
|
3fddc8effc | ||
|
|
c1d0547cf6 | ||
|
|
b970067298 | ||
|
|
8deb9822e4 | ||
|
|
9925d34a49 | ||
|
|
2d67195ed2 | ||
|
|
e72c6a1830 | ||
|
|
6b8e7eefcc | ||
|
|
c3c203ccd9 | ||
|
|
7a743148c9 | ||
|
|
8b09cd3a4d | ||
|
|
b3a6e613fc | ||
|
|
b7dc02381f | ||
|
|
181400c3d5 | ||
|
|
d844cb58a8 | ||
|
|
7261945eb5 | ||
|
|
b1a99c3a1f | ||
|
|
1e8c62b29c | ||
|
|
9e0dba8c17 | ||
|
|
460b66b14b | ||
|
|
b87c0fc440 | ||
|
|
93e447b631 | ||
|
|
940e22fd81 | ||
|
|
4ac24cf59e | ||
|
|
ca2c1cb446 | ||
|
|
ee12c3d60c | ||
|
|
1f56046fd5 | ||
|
|
06de079091 | ||
|
|
bcaa5f1c04 | ||
|
|
2232717cba | ||
|
|
5ca4f13b87 | ||
|
|
37e7e72041 | ||
|
|
4577167170 | ||
|
|
5d464a4a55 | ||
|
|
702764f53b | ||
|
|
b56772e5df | ||
|
|
a20c0d0f67 | ||
|
|
86d5634941 | ||
|
|
962e2fcdb6 | ||
|
|
1a275bac2b | ||
|
|
9c2c932f8c | ||
|
|
1044391135 | ||
|
|
f342dac1cb | ||
|
|
908037fe16 | ||
|
|
f8dcd5ca6f | ||
|
|
9bf1140b90 | ||
|
|
527b512cf7 | ||
|
|
892fcaf291 | ||
|
|
bf1f995c4c | ||
|
|
ce33356094 | ||
|
|
d652709aba | ||
|
|
138d08c531 | ||
|
|
fa2544e79f | ||
|
|
3e34352222 | ||
|
|
42c63d3ad2 | ||
|
|
36949554ab | ||
|
|
93fb7489a7 | ||
|
|
9c24588e73 | ||
|
|
9362da78b0 | ||
|
|
8ae76e0f5d | ||
|
|
9682087b65 | ||
|
|
f9781fc62e | ||
|
|
a93bb51604 | ||
|
|
3acee27b14 | ||
|
|
7993454a92 | ||
|
|
3e0e10add3 | ||
|
|
0d10cb7a1f | ||
|
|
0af2f2d856 | ||
|
|
c7057326ea | ||
|
|
0167938c26 | ||
|
|
e88ed65a39 | ||
|
|
399ff1fe05 | ||
|
|
895c12943b | ||
|
|
ea2cc8fc4a | ||
|
|
c7fa55bb87 | ||
|
|
78494ffecc | ||
|
|
4a8d0f3b10 | ||
|
|
7f10522c43 | ||
|
|
60d5ab3a16 | ||
|
|
5ce4c2a23a | ||
|
|
723cafcbcf | ||
|
|
e5c027b49b | ||
|
|
cf8525a571 | ||
|
|
fc42e9fae2 | ||
|
|
ea8c55cfd7 | ||
|
|
53e596512c | ||
|
|
d02833c76a | ||
|
|
bf754cfd01 | ||
|
|
f487746ded | ||
|
|
3a8ca61bd0 | ||
|
|
fe1725a141 | ||
|
|
658cf0b1be | ||
|
|
a37092fcf4 | ||
|
|
91d7e847e0 | ||
|
|
092631f0ba | ||
|
|
1376cd9d7f | ||
|
|
ef9ab3c2a0 | ||
|
|
724c65c1f8 | ||
|
|
8fae3dae11 | ||
|
|
6806677841 | ||
|
|
712fd182b7 | ||
|
|
3f47eb4a9a | ||
|
|
2f98e8c1a4 | ||
|
|
1fafcee66d | ||
|
|
d53fbb4a53 | ||
|
|
d15180297f | ||
|
|
60f89779a3 | ||
|
|
b0a7e05a45 | ||
|
|
cadae3588c | ||
|
|
5cccb13dad | ||
|
|
5a60b66a9d | ||
|
|
7cfbe1fee4 | ||
|
|
1a3f0da922 | ||
|
|
5d7cebdadc | ||
|
|
6cb6d62347 | ||
|
|
f0b5e9e116 | ||
|
|
98e6175874 | ||
|
|
7e7bcce2d9 | ||
|
|
55f69a4700 | ||
|
|
fc8c44e3d5 | ||
|
|
52d3a48128 | ||
|
|
703d64469e | ||
|
|
853a4a81b3 | ||
|
|
ec9a4904f3 | ||
|
|
3263a245bb | ||
|
|
a7a69cd07a | ||
|
|
e9de46c436 | ||
|
|
c7c0c93172 | ||
|
|
5519660a0d | ||
|
|
068ed1e838 | ||
|
|
9ceae8acea | ||
|
|
2675fe6218 | ||
|
|
85ea8b4f43 | ||
|
|
91c5132ab5 | ||
|
|
d3f220b2c2 | ||
|
|
fdef04e77b | ||
|
|
542a1380aa | ||
|
|
811bde8267 | ||
|
|
f3da2a88c9 | ||
|
|
dce656f9e0 | ||
|
|
b5271c8861 | ||
|
|
94e6967e98 | ||
|
|
7e05b97229 | ||
|
|
3d1d5fafc1 | ||
|
|
2eba535348 | ||
|
|
ddd0d9ae54 | ||
|
|
0b637e0b86 | ||
|
|
9a133240d3 | ||
|
|
6085033f31 | ||
|
|
9504e415cb | ||
|
|
a41957b873 | ||
|
|
fea0a27ddc | ||
|
|
1941765ae2 | ||
|
|
04dc79f1cc | ||
|
|
b6751ed1b2 | ||
|
|
8ed1f7c153 | ||
|
|
68d889db34 | ||
|
|
e364ad962f | ||
|
|
166004aca5 | ||
|
|
fcc547346a | ||
|
|
d1eafe56c8 | ||
|
|
2ac8af4534 | ||
|
|
cdc6b8d6a6 | ||
|
|
815a3605c1 | ||
|
|
17a5fd9248 | ||
|
|
2f2ac3fece | ||
|
|
0e6c6e3fd1 | ||
|
|
b4c7b6a384 | ||
|
|
e20417c333 | ||
|
|
0ae535cdb2 | ||
|
|
1194f00350 | ||
|
|
00d832756c | ||
|
|
0a1c5c9b10 | ||
|
|
b3ba40c6bf | ||
|
|
ecf07f2729 | ||
|
|
1a4ac2b4d0 | ||
|
|
1422e5bf51 | ||
|
|
8b3a795ea6 | ||
|
|
1db5f43dc4 | ||
|
|
c1c86b147b | ||
|
|
eca170286e | ||
|
|
78b9d2de40 | ||
|
|
27960a36de | ||
|
|
91aadbdacf | ||
|
|
458b6e6436 | ||
|
|
7f23df06d7 | ||
|
|
f322aa4d60 | ||
|
|
ffef16404d | ||
|
|
76a3bfa17c | ||
|
|
4986c35d74 | ||
|
|
d05c03ab4e | ||
|
|
b4f8c8f5f9 | ||
|
|
11c34e0f6c | ||
|
|
b3b4b008e3 | ||
|
|
9cf600e6da | ||
|
|
7013cc3d97 | ||
|
|
88aa771536 | ||
|
|
4fc8c042a2 | ||
|
|
e9865a41d6 | ||
|
|
d7962747c4 | ||
|
|
3108aed0f2 | ||
|
|
ef48e9b7df | ||
|
|
0b11082d36 | ||
|
|
feb3c15335 | ||
|
|
1be5779124 | ||
|
|
ab2be34059 | ||
|
|
54fee2d0ce | ||
|
|
001a64c71c | ||
|
|
b085138f89 | ||
|
|
471e0bdc7c | ||
|
|
caad1add4f | ||
|
|
33e0c3a866 | ||
|
|
82705af1eb | ||
|
|
69ce70866d | ||
|
|
6fb186f4bb | ||
|
|
fdb365df0e | ||
|
|
8960f2fc33 | ||
|
|
43163a5a4d | ||
|
|
fb811c31fd | ||
|
|
0365f19dec | ||
|
|
25be0597ca | ||
|
|
6928794f56 | ||
|
|
d52397b3c0 | ||
|
|
622f1438de | ||
|
|
41cde5bbdc | ||
|
|
6ebb141bf9 | ||
|
|
4c38fbae95 | ||
|
|
9ab932b769 | ||
|
|
8ad6996cc3 | ||
|
|
888ac4e7a3 | ||
|
|
76e707a44e | ||
|
|
84d228ed83 | ||
|
|
a21e4da901 | ||
|
|
b5d9c7d9fb | ||
|
|
4bbd72cca1 | ||
|
|
da6a3919a9 | ||
|
|
e7c3e6e4b4 | ||
|
|
ccd69c7d22 | ||
|
|
4664aae3fe | ||
|
|
cac23a5a0b | ||
|
|
06e0f79ae5 | ||
|
|
882e00e215 | ||
|
|
c11e2b8679 | ||
|
|
d841fc969a | ||
|
|
c13d50d861 | ||
|
|
c1c6de6ad4 | ||
|
|
7120874983 | ||
|
|
1b6d8f3fca | ||
|
|
e5b031f5d2 | ||
|
|
edb563e8a5 | ||
|
|
bccbc5f4c3 | ||
|
|
22388eac08 | ||
|
|
1677743fca | ||
|
|
d1e56838dc | ||
|
|
a0db9a79e5 | ||
|
|
8f378e98c5 | ||
|
|
3d3f9cd120 | ||
|
|
5df1a22c2e | ||
|
|
54ed0a0432 | ||
|
|
b0870346f2 | ||
|
|
1181bf86d1 | ||
|
|
382e613ef5 | ||
|
|
c144672045 | ||
|
|
a5b875f47b | ||
|
|
70550ed81b | ||
|
|
5df96269d3 | ||
|
|
948072c39f | ||
|
|
880c478635 | ||
|
|
98811f6ad4 | ||
|
|
83201b12ae | ||
|
|
507848b63d | ||
|
|
cc19ba76e4 | ||
|
|
6e1e62a04c | ||
|
|
9b53650a45 | ||
|
|
2d8bc0e6da | ||
|
|
21aa161453 | ||
|
|
09308a3882 | ||
|
|
7de7913abd | ||
|
|
780a182317 | ||
|
|
99e9601e80 | ||
|
|
45099b19da | ||
|
|
a2e9767225 | ||
|
|
20e3f2aefc | ||
|
|
fb88f1cc97 | ||
|
|
eb2a10afd6 | ||
|
|
cc6bd19660 | ||
|
|
84393f15b6 | ||
|
|
b52b6f2e38 | ||
|
|
a91a40febd | ||
|
|
3b8051864b | ||
|
|
961cf14ab3 | ||
|
|
8632383161 | ||
|
|
ab4b52a239 | ||
|
|
96f1723bb1 | ||
|
|
027d149352 | ||
|
|
96c700f5e4 | ||
|
|
f503a1486a | ||
|
|
987f26aa1a | ||
|
|
6be2c9b5b4 | ||
|
|
7aa253d3ec | ||
|
|
9ea0699278 | ||
|
|
f1a6d74775 | ||
|
|
5fe2dbd7b6 | ||
|
|
ace5ce05be | ||
|
|
98c0b8b85e | ||
|
|
1f53204045 | ||
|
|
181b863d22 | ||
|
|
142e5056cd | ||
|
|
9a7f4948c6 | ||
|
|
12c69167e3 | ||
|
|
b379bc5eef | ||
|
|
16e7c05de7 | ||
|
|
4c519a47a9 | ||
|
|
ba56a88ca5 | ||
|
|
fe5cc3b7f8 | ||
|
|
5d901f1ba0 | ||
|
|
0e6425da4a | ||
|
|
f8c3eb9568 | ||
|
|
d27be1f557 | ||
|
|
3741185a51 | ||
|
|
cba18514c0 | ||
|
|
a7d735dcc2 | ||
|
|
094c35cffc | ||
|
|
b683118cd0 | ||
|
|
1c4be55a99 | ||
|
|
7597fcd92f | ||
|
|
adb9f7ddde | ||
|
|
99fe0af2fe | ||
|
|
45593c271a | ||
|
|
d885aba347 | ||
|
|
36b1eb7631 | ||
|
|
76ef6d89b9 | ||
|
|
c4a3bf9e55 | ||
|
|
90de05e88e | ||
|
|
2bf36b4e7d | ||
|
|
831d24a19d | ||
|
|
1aafd7464f | ||
|
|
586ea168c2 | ||
|
|
1179f6373d | ||
|
|
0143c024af | ||
|
|
2744ea8c1f | ||
|
|
00eae584a2 | ||
|
|
ef4280e08b | ||
|
|
ed176ba584 | ||
|
|
38a976d5bb | ||
|
|
b526cbaa71 | ||
|
|
aec5c5fe26 | ||
|
|
600dc62559 | ||
|
|
030d7acf7d | ||
|
|
20cff2ade4 | ||
|
|
7944d81567 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/version.cpp export-subst
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
src/*.exe
|
||||
src/bitcoin
|
||||
src/bitcoind
|
||||
src/test_bitcoin
|
||||
src/build.h
|
||||
.*.swp
|
||||
*.*~*
|
||||
*.bak
|
||||
@@ -19,3 +21,4 @@ qrc_*.cpp
|
||||
*.pro.user
|
||||
#mac specific
|
||||
.DS_Store
|
||||
build
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
VERSION = 0.6.0
|
||||
VERSION = 0.6.3.0
|
||||
INCLUDEPATH += src src/json src/qt
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
|
||||
CONFIG += no_include_pwd
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
@@ -62,12 +62,6 @@ contains(USE_DBUS, 1) {
|
||||
QT += dbus
|
||||
}
|
||||
|
||||
# use: qmake "USE_SSL=1"
|
||||
contains(USE_SSL, 1) {
|
||||
message(Building with SSL support for RPC)
|
||||
DEFINES += USE_SSL
|
||||
}
|
||||
|
||||
# use: qmake "FIRST_CLASS_MESSAGING=1"
|
||||
contains(FIRST_CLASS_MESSAGING, 1) {
|
||||
message(Building with first-class messaging)
|
||||
@@ -86,11 +80,20 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
# do not enable this on windows, as it will result in a non-working executable!
|
||||
}
|
||||
|
||||
# disable quite some warnings because bitcoin core "sins" a lot
|
||||
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wno-strict-aliasing -Wno-invalid-offsetof -Wno-unused-variable -Wno-unused-parameter -Wno-sign-compare -Wno-char-subscripts -Wno-unused-value -Wno-sequence-point -Wno-parentheses -Wno-unknown-pragmas -Wno-switch
|
||||
# regenerate src/build.h
|
||||
!windows || contains(USE_BUILD_INFO, 1) {
|
||||
genbuild.depends = FORCE
|
||||
genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h
|
||||
genbuild.target = genbuildhook
|
||||
PRE_TARGETDEPS += genbuildhook
|
||||
QMAKE_EXTRA_TARGETS += genbuild
|
||||
DEFINES += HAVE_BUILD_INFO
|
||||
}
|
||||
|
||||
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-invalid-offsetof -Wno-sign-compare -Wno-unused-parameter
|
||||
|
||||
# Input
|
||||
DEPENDPATH += src/qt src src json/include
|
||||
DEPENDPATH += src src/json src/qt
|
||||
HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/transactiontablemodel.h \
|
||||
src/qt/addresstablemodel.h \
|
||||
@@ -114,10 +117,9 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/net.h \
|
||||
src/key.h \
|
||||
src/db.h \
|
||||
src/walletdb.h \
|
||||
src/script.h \
|
||||
src/noui.h \
|
||||
src/init.h \
|
||||
src/headers.h \
|
||||
src/irc.h \
|
||||
src/mruset.h \
|
||||
src/json/json_spirit_writer_template.h \
|
||||
@@ -135,7 +137,6 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/guiconstants.h \
|
||||
src/qt/optionsmodel.h \
|
||||
src/qt/monitoreddatamapper.h \
|
||||
src/qtui.h \
|
||||
src/qt/transactiondesc.h \
|
||||
src/qt/transactiondescdialog.h \
|
||||
src/qt/bitcoinamountfield.h \
|
||||
@@ -155,7 +156,9 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/askpassphrasedialog.h \
|
||||
src/protocol.h \
|
||||
src/qt/notificator.h \
|
||||
src/qt/qtipcserver.h
|
||||
src/qt/qtipcserver.h \
|
||||
src/allocators.h \
|
||||
src/ui_interface.h
|
||||
|
||||
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/transactiontablemodel.cpp \
|
||||
@@ -167,6 +170,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/aboutdialog.cpp \
|
||||
src/qt/editaddressdialog.cpp \
|
||||
src/qt/bitcoinaddressvalidator.cpp \
|
||||
src/version.cpp \
|
||||
src/util.cpp \
|
||||
src/netbase.cpp \
|
||||
src/key.cpp \
|
||||
@@ -178,6 +182,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/checkpoints.cpp \
|
||||
src/addrman.cpp \
|
||||
src/db.cpp \
|
||||
src/walletdb.cpp \
|
||||
src/json/json_spirit_writer.cpp \
|
||||
src/json/json_spirit_value.cpp \
|
||||
src/json/json_spirit_reader.cpp \
|
||||
@@ -231,8 +236,8 @@ FORMS += src/qt/forms/qrcodedialog.ui
|
||||
|
||||
contains(BITCOIN_QT_TEST, 1) {
|
||||
SOURCES += src/qt/test/test_main.cpp \
|
||||
src/qt/test/urltests.cpp
|
||||
HEADERS += src/qt/test/urltests.h
|
||||
src/qt/test/uritests.cpp
|
||||
HEADERS += src/qt/test/uritests.h
|
||||
DEPENDPATH += src/qt/test
|
||||
QT += testlib
|
||||
TARGET = bitcoin-qt_test
|
||||
@@ -261,7 +266,7 @@ PRE_TARGETDEPS += compiler_TSQM_make_all
|
||||
|
||||
# "Other files" to show in Qt Creator
|
||||
OTHER_FILES += \
|
||||
doc/*.rst doc/*.txt doc/README README.md
|
||||
doc/*.rst doc/*.txt doc/README README.md res/bitcoin-qt.rc
|
||||
|
||||
# platform specific defaults, if not overridden on command line
|
||||
isEmpty(BOOST_LIB_SUFFIX) {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Encoding=UTF-8
|
||||
Name=Bitcoin
|
||||
Comment=Bitcoin P2P Cryptocurrency
|
||||
Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
|
||||
Comment[tr]=Bitcoin, eşten eşe kriptografik sanal para birimi
|
||||
Exec=/usr/bin/bitcoin-qt
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
||||
@@ -35,7 +35,7 @@ Description: peer-to-peer network based digital currency - daemon
|
||||
By default connects to an IRC network to discover other peers.
|
||||
.
|
||||
Full transaction history is stored locally at each client. This
|
||||
requires 150+ MB of space, slowly growing.
|
||||
requires 2+ GB of space, slowly growing.
|
||||
.
|
||||
This package provides bitcoind, a combined daemon and CLI tool to
|
||||
interact with the daemon.
|
||||
@@ -53,6 +53,6 @@ Description: peer-to-peer network based digital currency - QT GUI
|
||||
By default connects to an IRC network to discover other peers.
|
||||
.
|
||||
Full transaction history is stored locally at each client. This
|
||||
requires 150+ MB of space, slowly growing.
|
||||
requires 2+ GB of space, slowly growing.
|
||||
.
|
||||
This package provides bitcoin-qt, a GUI for Bitcoin based on QT.
|
||||
|
||||
@@ -20,7 +20,7 @@ override_dh_auto_clean:
|
||||
cd src; $(MAKE) -f makefile.unix clean
|
||||
|
||||
override_dh_auto_configure:
|
||||
qmake bitcoin-qt.pro USE_SSL=1 USE_QRCODE=1
|
||||
qmake bitcoin-qt.pro USE_QRCODE=1
|
||||
|
||||
override_dh_auto_test:
|
||||
cd src; $(MAKE) -f makefile.unix test_bitcoin
|
||||
|
||||
@@ -13,7 +13,7 @@ packages:
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes: []
|
||||
files:
|
||||
- "openssl-1.0.0e.tar.gz"
|
||||
- "openssl-1.0.1b.tar.gz"
|
||||
- "db-4.8.30.NC.tar.gz"
|
||||
- "miniupnpc-1.6.tar.gz"
|
||||
- "zlib-1.2.6.tar.gz"
|
||||
@@ -25,8 +25,8 @@ script: |
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
#
|
||||
tar xzf openssl-1.0.0e.tar.gz
|
||||
cd openssl-1.0.0e
|
||||
tar xzf openssl-1.0.1b.tar.gz
|
||||
cd openssl-1.0.1b
|
||||
./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
|
||||
make
|
||||
cd ..
|
||||
@@ -62,7 +62,7 @@ script: |
|
||||
make $MAKEOPTS
|
||||
cd ..
|
||||
#
|
||||
zip -r $OUTDIR/bitcoin-deps-0.0.3.zip \
|
||||
zip -r $OUTDIR/bitcoin-deps-0.0.4.zip \
|
||||
$(ls qrencode-*/{qrencode.h,.libs/libqrencode.{,l}a} | sort) \
|
||||
$(ls db-*/build_unix/{libdb_cxx.a,db.h,db_cxx.h,libdb.a,.libs/libdb_cxx-?.?.a} | sort) \
|
||||
$(find openssl-* -name '*.a' -o -name '*.h' | sort) \
|
||||
|
||||
@@ -17,7 +17,7 @@ remotes:
|
||||
files:
|
||||
- "qt-win32-4.7.4-gitian.zip"
|
||||
- "boost-win32-1.47.0-gitian.zip"
|
||||
- "bitcoin-deps-0.0.3.zip"
|
||||
- "bitcoin-deps-0.0.4.zip"
|
||||
script: |
|
||||
#
|
||||
mkdir $HOME/qt
|
||||
@@ -39,31 +39,36 @@ script: |
|
||||
mv include/boost .
|
||||
cd ..
|
||||
#
|
||||
unzip bitcoin-deps-0.0.3.zip
|
||||
unzip bitcoin-deps-0.0.4.zip
|
||||
#
|
||||
find -type f | xargs touch --date="$REFERENCE_DATETIME"
|
||||
#
|
||||
cd bitcoin
|
||||
mkdir -p $OUTDIR/src
|
||||
cp -a . $OUTDIR/src
|
||||
rm -rf $OUTDIR/src/.git
|
||||
git archive HEAD | tar -x -C $OUTDIR/src
|
||||
cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt
|
||||
cp $OUTDIR/src/COPYING $OUTDIR/license.txt
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
$HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross USE_SSL=1 MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.0e OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.0e/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin
|
||||
$HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1b OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1b/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1
|
||||
make $MAKEOPTS
|
||||
cp release/bitcoin-qt.exe $OUTDIR/
|
||||
#
|
||||
cd src
|
||||
sed 's/$(DEBUGFLAGS)/-frandom-seed=bitcoin/' -i makefile.linux-mingw
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_SSL=1 USE_UPNP=0
|
||||
make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0 DEBUGFLAGS="-frandom-seed=bitcoin"
|
||||
i586-mingw32msvc-strip bitcoind.exe
|
||||
makensis ../share/setup.nsi
|
||||
cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/
|
||||
mkdir $OUTDIR/daemon
|
||||
cp bitcoind.exe $OUTDIR/daemon
|
||||
cd ..
|
||||
mkdir nsis
|
||||
git archive HEAD | tar -x -C nsis
|
||||
cd nsis/src
|
||||
mkdir ../release
|
||||
cp ../../release/* ../release/
|
||||
cp ../../src/*.exe .
|
||||
makensis ../share/setup.nsi
|
||||
cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/
|
||||
|
||||
@@ -42,16 +42,14 @@ script: |
|
||||
#
|
||||
cd bitcoin
|
||||
mkdir -p $OUTDIR/src
|
||||
cp -a . $OUTDIR/src
|
||||
rm -rf $OUTDIR/src/.git
|
||||
git archive HEAD | tar -x -C $OUTDIR/src
|
||||
cp $OUTDIR/src/doc/README $OUTDIR
|
||||
cp $OUTDIR/src/COPYING $OUTDIR
|
||||
cd src
|
||||
sed 's/$(DEBUGFLAGS)//' -i makefile.unix
|
||||
make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 USE_SSL=1
|
||||
make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 DEBUGFLAGS=
|
||||
mkdir -p $OUTDIR/bin/$GBUILD_BITS
|
||||
install -s bitcoind $OUTDIR/bin/$GBUILD_BITS
|
||||
cd ..
|
||||
qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" RELEASE=1 USE_SSL=1 USE_QRCODE=1
|
||||
qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" RELEASE=1 USE_QRCODE=1
|
||||
make $MAKEOPTS
|
||||
install bitcoin-qt $OUTDIR/bin/$GBUILD_BITS
|
||||
|
||||
@@ -15,9 +15,13 @@ signers:
|
||||
weight: 40
|
||||
name: Devrandom
|
||||
key: devrandom
|
||||
E463A93F5F3117EEDE6C7316BD02942421F4889F:
|
||||
weight: 40
|
||||
name: Luke-Jr
|
||||
key: luke-jr
|
||||
D762373D24904A3E42F33B08B9A408E71DAAC974:
|
||||
weight: 40
|
||||
name: Sipa
|
||||
name: "Pieter Wuille"
|
||||
key: sipa
|
||||
77E72E69DA7EE0A148C06B21B34821D4944DE5F7:
|
||||
weight: 40
|
||||
@@ -27,7 +31,7 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
71A3B16735405025D447E8F274810B012346C9A6:
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
|
||||
BIN
contrib/gitian-downloader/luke-jr-key.pgp
Normal file
BIN
contrib/gitian-downloader/luke-jr-key.pgp
Normal file
Binary file not shown.
Binary file not shown.
@@ -15,9 +15,13 @@ signers:
|
||||
weight: 40
|
||||
name: Devrandom
|
||||
key: devrandom
|
||||
E463A93F5F3117EEDE6C7316BD02942421F4889F:
|
||||
weight: 40
|
||||
name: Luke-Jr
|
||||
key: luke-jr
|
||||
D762373D24904A3E42F33B08B9A408E71DAAC974:
|
||||
weight: 40
|
||||
name: Sipa
|
||||
name: "Pieter Wuille"
|
||||
key: sipa
|
||||
77E72E69DA7EE0A148C06B21B34821D4944DE5F7:
|
||||
weight: 40
|
||||
@@ -27,7 +31,7 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
71A3B16735405025D447E8F274810B012346C9A6:
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bitcoin 0.6.0 BETA
|
||||
Bitcoin 0.6.3 BETA
|
||||
|
||||
Copyright (c) 2009-2012 Bitcoin Developers
|
||||
Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bitcoin 0.6.0 BETA
|
||||
Bitcoin 0.6.3 BETA
|
||||
|
||||
Copyright (c) 2009-2012 Bitcoin Developers
|
||||
Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Code: src/strlcpy.h
|
||||
Author: Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
License: ISC
|
||||
|
||||
Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
|
||||
src/qt/res/src/*.svg
|
||||
Designer: Wladimir van der Laan
|
||||
|
||||
@@ -24,7 +24,7 @@ Dependencies
|
||||
Libraries you need to download separately and build:
|
||||
|
||||
default path download
|
||||
OpenSSL \openssl-1.0.0d-mgw http://www.openssl.org/source/
|
||||
OpenSSL \openssl-1.0.1b-mgw http://www.openssl.org/source/
|
||||
Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html
|
||||
Boost \boost-1.47.0-mgw http://www.boost.org/users/download/
|
||||
miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/
|
||||
@@ -36,7 +36,7 @@ Boost MIT-like license
|
||||
miniupnpc New (3-clause) BSD license
|
||||
|
||||
Versions used in this release:
|
||||
OpenSSL 1.0.0e
|
||||
OpenSSL 1.0.1b
|
||||
Berkeley DB 4.8.30.NC
|
||||
Boost 1.47.0
|
||||
miniupnpc 1.6
|
||||
@@ -48,7 +48,7 @@ MSYS shell:
|
||||
un-tar sources with MSYS 'tar xfz' to avoid issue with symlinks (OpenSSL ticket 2377)
|
||||
change 'MAKE' env. variable from 'C:\MinGW32\bin\mingw32-make.exe' to '/c/MinGW32/bin/mingw32-make.exe'
|
||||
|
||||
cd /c/openssl-1.0.0e-mgw
|
||||
cd /c/openssl-1.0.1b-mgw
|
||||
./config
|
||||
make
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@ Dependencies
|
||||
miniupnpc may be used for UPnP port mapping. It can be downloaded from
|
||||
http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and
|
||||
turned off by default. Set USE_UPNP to a different value to control this:
|
||||
USE_UPNP= No UPnP support - miniupnp not required
|
||||
USE_UPNP=- No UPnP support - miniupnp not required
|
||||
USE_UPNP=0 (the default) UPnP support turned off by default at runtime
|
||||
USE_UPNP=1 UPnP support turned on by default at runtime
|
||||
|
||||
libqrencode may be used for QRCode image generation. It can be downloaded
|
||||
from http://fukuchi.org/works/qrencode/index.html.en, or installed via
|
||||
your package manager. Set USE_QRCODE to control this:
|
||||
USE_QRCODE=0 (the default) No QRCode support - libarcode not required
|
||||
USE_QRCODE=0 (the default) No QRCode support - libqrcode not required
|
||||
USE_QRCODE=1 QRCode support enabled
|
||||
|
||||
Licenses of statically linked libraries:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
* update (commit) version in sources
|
||||
bitcoin-qt.pro
|
||||
src/main.h (CLIENT_VERSION : PROTOCOL_VERSION in serialize.h is updated only on protocol changes)
|
||||
src/version.h
|
||||
share/setup.nsi
|
||||
doc/README*
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* Fetch and build inputs:
|
||||
mkdir -p inputs; cd inputs/
|
||||
wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz
|
||||
wget 'http://www.openssl.org/source/openssl-1.0.0e.tar.gz'
|
||||
wget 'http://www.openssl.org/source/openssl-1.0.1b.tar.gz'
|
||||
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
|
||||
wget 'http://zlib.net/zlib-1.2.6.tar.gz'
|
||||
wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.9.tar.gz'
|
||||
@@ -79,7 +79,7 @@
|
||||
Gavin also had trouble with the macports py27-appscript package; he
|
||||
ended up installing a version that worked with: /usr/bin/easy_install-2.7 appscript
|
||||
|
||||
qmake RELEASE=1 USE_SSL=1 USE_UPNP=1 USE_QRCODE=1 bitcoin-qt.pro
|
||||
qmake RELEASE=1 USE_UPNP=1 USE_QRCODE=1 bitcoin-qt.pro
|
||||
make
|
||||
export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files
|
||||
T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale)
|
||||
@@ -98,6 +98,8 @@
|
||||
|
||||
* update wiki download links
|
||||
|
||||
* update wiki changelog: https://en.bitcoin.it/wiki/Changelog
|
||||
|
||||
* Commit your signature to gitian.sigs:
|
||||
pushd gitian.sigs
|
||||
git add ${VERSION}/${SIGNER}
|
||||
|
||||
35
share/genbuild.sh
Executable file
35
share/genbuild.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
FILE="$1"
|
||||
shift
|
||||
if [ -f "$FILE" ]; then
|
||||
INFO="$(head -n 1 "$FILE")"
|
||||
fi
|
||||
else
|
||||
echo "Usage: $0 <filename>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "$(which git)" ]; then
|
||||
# clean 'dirty' status of touched files that haven't been modified
|
||||
git diff >/dev/null 2>/dev/null
|
||||
|
||||
# get a string like "v0.6.0-66-g59887e8-dirty"
|
||||
DESC="$(git describe --dirty 2>/dev/null)"
|
||||
|
||||
# get a string like "2012-04-10 16:27:19 +0200"
|
||||
TIME="$(git log -n 1 --format="%ci")"
|
||||
fi
|
||||
|
||||
if [ -n "$DESC" ]; then
|
||||
NEWINFO="#define BUILD_DESC \"$DESC\""
|
||||
else
|
||||
NEWINFO="// No build information available"
|
||||
fi
|
||||
|
||||
# only update build.h if necessary
|
||||
if [ "$INFO" != "$NEWINFO" ]; then
|
||||
echo "$NEWINFO" >"$FILE"
|
||||
echo "#define BUILD_DATE \"$TIME\"" >>"$FILE"
|
||||
fi
|
||||
@@ -4,6 +4,7 @@ Extract _("...") strings for translation and convert to Qt4 stringdefs so that
|
||||
they can be picked up by Qt linguist.
|
||||
'''
|
||||
from subprocess import Popen, PIPE
|
||||
import glob
|
||||
|
||||
OUT_CPP="src/qt/bitcoinstrings.cpp"
|
||||
EMPTY=['""']
|
||||
@@ -44,7 +45,7 @@ def parse_po(text):
|
||||
|
||||
return messages
|
||||
|
||||
files = ['src/base58.h', 'src/bignum.h', 'src/db.cpp', 'src/db.h', 'src/headers.h', 'src/init.cpp', 'src/init.h', 'src/irc.cpp', 'src/irc.h', 'src/key.h', 'src/main.cpp', 'src/main.h', 'src/net.cpp', 'src/net.h', 'src/noui.h', 'src/script.cpp', 'src/script.h', 'src/serialize.h', 'src/strlcpy.h', 'src/uint256.h', 'src/util.cpp', 'src/util.h']
|
||||
files = glob.glob('src/*.cpp') + glob.glob('src/*.h')
|
||||
|
||||
# xgettext -n --keyword=_ $FILES
|
||||
child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
|
||||
@@ -53,9 +54,15 @@ child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
|
||||
messages = parse_po(out)
|
||||
|
||||
f = open(OUT_CPP, 'w')
|
||||
f.write('#include <QtGlobal>\n')
|
||||
f.write('// Automatically generated by extract_strings.py\n')
|
||||
f.write('static const char *bitcoin_strings[] = {')
|
||||
f.write("""#include <QtGlobal>
|
||||
// Automatically generated by extract_strings.py
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
""")
|
||||
f.write('static const char UNUSED *bitcoin_strings[] = {')
|
||||
for (msgid, msgstr) in messages:
|
||||
if msgid != EMPTY:
|
||||
f.write('QT_TRANSLATE_NOOP("bitcoin-core", %s),\n' % ('\n'.join(msgid)))
|
||||
@@ -5,7 +5,7 @@ SetCompressor /SOLID lzma
|
||||
|
||||
# General Symbol Definitions
|
||||
!define REGKEY "SOFTWARE\$(^Name)"
|
||||
!define VERSION 0.6.0
|
||||
!define VERSION 0.6.3
|
||||
!define COMPANY "Bitcoin project"
|
||||
!define URL http://www.bitcoin.org/
|
||||
|
||||
@@ -45,13 +45,13 @@ Var StartMenuGroup
|
||||
!insertmacro MUI_LANGUAGE English
|
||||
|
||||
# Installer attributes
|
||||
OutFile bitcoin-0.6.0-win32-setup.exe
|
||||
OutFile bitcoin-0.6.3-win32-setup.exe
|
||||
InstallDir $PROGRAMFILES\Bitcoin
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
BrandingText " "
|
||||
ShowInstDetails show
|
||||
VIProductVersion 0.6.0.6
|
||||
VIProductVersion 0.6.3.0
|
||||
VIAddVersionKey ProductName Bitcoin
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey CompanyName "${COMPANY}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "addrman.h"
|
||||
|
||||
@@ -8,12 +8,12 @@ using namespace std;
|
||||
|
||||
int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH);
|
||||
CDataStream ss1(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchKey = GetKey();
|
||||
ss1 << nKey << vchKey;
|
||||
uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH);
|
||||
CDataStream ss2(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
ss2 << nKey << vchGroupKey << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP);
|
||||
uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
|
||||
@@ -22,13 +22,13 @@ int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const
|
||||
|
||||
int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH);
|
||||
CDataStream ss1(SER_GETHASH, 0);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
|
||||
ss1 << nKey << vchGroupKey << vchSourceGroupKey;
|
||||
uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH);
|
||||
CDataStream ss2(SER_GETHASH, 0);
|
||||
ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP);
|
||||
uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
|
||||
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
@@ -107,9 +107,15 @@ void CAddrMan::SwapRandom(int nRndPos1, int nRndPos2)
|
||||
if (nRndPos1 == nRndPos2)
|
||||
return;
|
||||
|
||||
assert(nRndPos1 >= 0 && nRndPos2 >= 0);
|
||||
assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
|
||||
|
||||
int nId1 = vRandom[nRndPos1];
|
||||
int nId2 = vRandom[nRndPos2];
|
||||
|
||||
assert(mapInfo.count(nId1) == 1);
|
||||
assert(mapInfo.count(nId2) == 1);
|
||||
|
||||
mapInfo[nId1].nRandomPos = nRndPos2;
|
||||
mapInfo[nId2].nRandomPos = nRndPos1;
|
||||
|
||||
@@ -124,26 +130,32 @@ int CAddrMan::SelectTried(int nKBucket)
|
||||
// random shuffle the first few elements (using the entire list)
|
||||
// find the least recently tried among them
|
||||
int64 nOldest = -1;
|
||||
for (int i=0; i<ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i<vTried.size(); i++)
|
||||
int nOldestPos = -1;
|
||||
for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++)
|
||||
{
|
||||
int nPos = GetRandInt(vTried.size() - i) + i;
|
||||
int nTemp = vTried[nPos];
|
||||
vTried[nPos] = vTried[i];
|
||||
vTried[i] = nTemp;
|
||||
if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess)
|
||||
assert(nOldest == -1 || mapInfo.count(nTemp) == 1);
|
||||
if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) {
|
||||
nOldest = nTemp;
|
||||
nOldestPos = nPos;
|
||||
}
|
||||
}
|
||||
|
||||
return nOldest;
|
||||
return nOldestPos;
|
||||
}
|
||||
|
||||
int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
assert(nUBucket >= 0 && nUBucket < vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// first look for deletable items
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
assert(mapInfo.count(*it));
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (info.IsTerrible())
|
||||
{
|
||||
@@ -168,11 +180,13 @@ int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
|
||||
{
|
||||
assert(nOldest == -1 || mapInfo.count(*it) == 1);
|
||||
if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
|
||||
nOldest = *it;
|
||||
}
|
||||
nI++;
|
||||
}
|
||||
assert(mapInfo.count(nOldest) == 1);
|
||||
CAddrInfo &info = mapInfo[nOldest];
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
@@ -189,6 +203,8 @@ int CAddrMan::ShrinkNew(int nUBucket)
|
||||
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
{
|
||||
assert(vvNew[nOrigin].count(nId) == 1);
|
||||
|
||||
// remove the entry from all new buckets
|
||||
for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
|
||||
{
|
||||
@@ -197,6 +213,8 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
}
|
||||
nNew--;
|
||||
|
||||
assert(info.nRefCount == 0);
|
||||
|
||||
// what tried bucket to move the entry to
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
@@ -214,6 +232,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
int nPos = SelectTried(nKBucket);
|
||||
|
||||
// find which new bucket it belongs to
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
@@ -270,7 +289,7 @@ void CAddrMan::Good_(const CService &addr, int64 nTime)
|
||||
// find a bucket it is in now
|
||||
int nRnd = GetRandInt(vvNew.size());
|
||||
int nUBucket = -1;
|
||||
for (int n = 0; n < vvNew.size(); n++)
|
||||
for (unsigned int n = 0; n < vvNew.size(); n++)
|
||||
{
|
||||
int nB = (n+nRnd) % vvNew.size();
|
||||
std::set<int> &vNew = vvNew[nB];
|
||||
@@ -312,7 +331,7 @@ bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePen
|
||||
pinfo->nServices |= addr.nServices;
|
||||
|
||||
// do not update if no new information is present
|
||||
if (!addr.nTime || pinfo->nTime && addr.nTime <= pinfo->nTime)
|
||||
if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime))
|
||||
return false;
|
||||
|
||||
// do not update if the entry was already in the "tried" table
|
||||
@@ -385,6 +404,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
if (vTried.size() == 0) continue;
|
||||
int nPos = GetRandInt(vTried.size());
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
CAddrInfo &info = mapInfo[vTried[nPos]];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
@@ -402,6 +422,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
|
||||
std::set<int>::iterator it = vNew.begin();
|
||||
while (nPos--)
|
||||
it++;
|
||||
assert(mapInfo.count(*it) == 1);
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
@@ -481,6 +502,7 @@ void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr)
|
||||
{
|
||||
int nRndPos = GetRandInt(vRandom.size() - n) + n;
|
||||
SwapRandom(n, nRndPos);
|
||||
assert(mapInfo.count(vRandom[n]) == 1);
|
||||
vAddr.push_back(mapInfo[vRandom[n]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef _BITCOIN_ADDRMAN
|
||||
#define _BITCOIN_ADDRMAN 1
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
nRandomPos = -1;
|
||||
}
|
||||
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn)
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
@@ -266,8 +266,8 @@ public:
|
||||
//
|
||||
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
|
||||
// changes to the ADDRMAN_ parameters without breaking the on-disk structure.
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
unsigned char nVersion = 0;
|
||||
READWRITE(nVersion);
|
||||
READWRITE(nKey);
|
||||
@@ -398,8 +398,8 @@ public:
|
||||
void Check()
|
||||
{
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
int err;
|
||||
if ((err=Check_()))
|
||||
printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
|
||||
@@ -411,8 +411,8 @@ public:
|
||||
bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
|
||||
{
|
||||
bool fRet = false;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
fRet |= Add_(addr, source, nTimePenalty);
|
||||
Check();
|
||||
@@ -426,8 +426,8 @@ public:
|
||||
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
|
||||
{
|
||||
int nAdd = 0;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
|
||||
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
|
||||
@@ -441,8 +441,8 @@ public:
|
||||
// Mark an entry as accessible.
|
||||
void Good(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Good_(addr, nTime);
|
||||
Check();
|
||||
@@ -452,8 +452,8 @@ public:
|
||||
// Mark an entry as connection attempted to.
|
||||
void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Attempt_(addr, nTime);
|
||||
Check();
|
||||
@@ -465,8 +465,8 @@ public:
|
||||
CAddress Select(int nUnkBias = 50)
|
||||
{
|
||||
CAddress addrRet;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
addrRet = Select_(nUnkBias);
|
||||
Check();
|
||||
@@ -479,8 +479,10 @@ public:
|
||||
{
|
||||
Check();
|
||||
std::vector<CAddress> vAddr;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
GetAddr_(vAddr);
|
||||
}
|
||||
Check();
|
||||
return vAddr;
|
||||
}
|
||||
@@ -488,8 +490,8 @@ public:
|
||||
// Mark an entry as currently-connected-to.
|
||||
void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
LOCK(cs);
|
||||
Check();
|
||||
Connected_(addr, nTime);
|
||||
Check();
|
||||
|
||||
122
src/allocators.h
Normal file
122
src/allocators.h
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_ALLOCATORS_H
|
||||
#define BITCOIN_ALLOCATORS_H
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
// This is used to attempt to keep keying material out of swap
|
||||
// Note that VirtualLock does not provide this as a guarantee on Windows,
|
||||
// but, in practice, memory that has been VirtualLock'd almost never gets written to
|
||||
// the pagefile except in rare circumstances where memory is extremely low.
|
||||
#define mlock(p, n) VirtualLock((p), (n));
|
||||
#define munlock(p, n) VirtualUnlock((p), (n));
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <limits.h>
|
||||
/* This comes from limits.h if it's not defined there set a sane default */
|
||||
#ifndef PAGESIZE
|
||||
#include <unistd.h>
|
||||
#define PAGESIZE sysconf(_SC_PAGESIZE)
|
||||
#endif
|
||||
#define mlock(a,b) \
|
||||
mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
#define munlock(a,b) \
|
||||
munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
|
||||
(((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
|
||||
#endif
|
||||
|
||||
//
|
||||
// Allocator that locks its contents from being paged
|
||||
// out of memory and clears its contents before deletion.
|
||||
//
|
||||
template<typename T>
|
||||
struct secure_allocator : public std::allocator<T>
|
||||
{
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
secure_allocator() throw() {}
|
||||
secure_allocator(const secure_allocator& a) throw() : base(a) {}
|
||||
template <typename U>
|
||||
secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
|
||||
~secure_allocator() throw() {}
|
||||
template<typename _Other> struct rebind
|
||||
{ typedef secure_allocator<_Other> other; };
|
||||
|
||||
T* allocate(std::size_t n, const void *hint = 0)
|
||||
{
|
||||
T *p;
|
||||
p = std::allocator<T>::allocate(n, hint);
|
||||
if (p != NULL)
|
||||
mlock(p, sizeof(T) * n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL)
|
||||
{
|
||||
memset(p, 0, sizeof(T) * n);
|
||||
munlock(p, sizeof(T) * n);
|
||||
}
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Allocator that clears its contents before deletion.
|
||||
//
|
||||
template<typename T>
|
||||
struct zero_after_free_allocator : public std::allocator<T>
|
||||
{
|
||||
// MSVC8 default copy constructor is broken
|
||||
typedef std::allocator<T> base;
|
||||
typedef typename base::size_type size_type;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::const_pointer const_pointer;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::const_reference const_reference;
|
||||
typedef typename base::value_type value_type;
|
||||
zero_after_free_allocator() throw() {}
|
||||
zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
|
||||
template <typename U>
|
||||
zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {}
|
||||
~zero_after_free_allocator() throw() {}
|
||||
template<typename _Other> struct rebind
|
||||
{ typedef zero_after_free_allocator<_Other> other; };
|
||||
|
||||
void deallocate(T* p, std::size_t n)
|
||||
{
|
||||
if (p != NULL)
|
||||
memset(p, 0, sizeof(T) * n);
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
// This is exactly like std::string, but with a custom allocator.
|
||||
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
|
||||
|
||||
#endif
|
||||
14
src/base58.h
14
src/base58.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
//
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
int nExpectedSize = 20;
|
||||
unsigned int nExpectedSize = 20;
|
||||
bool fExpectTestNet = false;
|
||||
switch(nVersion)
|
||||
{
|
||||
@@ -396,6 +396,16 @@ public:
|
||||
return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
|
||||
}
|
||||
|
||||
bool SetString(const char* pszSecret)
|
||||
{
|
||||
return CBase58Data::SetString(pszSecret) && IsValid();
|
||||
}
|
||||
|
||||
bool SetString(const std::string& strSecret)
|
||||
{
|
||||
return SetString(strSecret.c_str());
|
||||
}
|
||||
|
||||
CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
SetSecret(vchSecret, fCompressed);
|
||||
|
||||
19
src/bignum.h
19
src/bignum.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_BIGNUM_H
|
||||
#define BITCOIN_BIGNUM_H
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <vector>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "util.h" // for uint64
|
||||
|
||||
/** Errors thrown by the bignum class */
|
||||
class bignum_error : public std::runtime_error
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** C++ wrapper for BIGNUM (OpenSSl bignum) */
|
||||
/** C++ wrapper for BIGNUM (OpenSSL bignum) */
|
||||
class CBigNum : public BIGNUM
|
||||
{
|
||||
public:
|
||||
@@ -78,7 +78,8 @@ public:
|
||||
BN_clear_free(this);
|
||||
}
|
||||
|
||||
CBigNum(char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
//CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
|
||||
CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); }
|
||||
@@ -116,9 +117,9 @@ public:
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
|
||||
else
|
||||
return (n > std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64 n)
|
||||
@@ -221,7 +222,7 @@ public:
|
||||
if (vch.size() > 4)
|
||||
vch[4] &= 0x7f;
|
||||
uint256 n = 0;
|
||||
for (int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
|
||||
for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
|
||||
((unsigned char*)&n)[i] = vch[j];
|
||||
return n;
|
||||
}
|
||||
@@ -296,12 +297,12 @@ public:
|
||||
psz++;
|
||||
|
||||
// hex string to bignum
|
||||
static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
static signed char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
|
||||
*this = 0;
|
||||
while (isxdigit(*psz))
|
||||
{
|
||||
*this <<= 4;
|
||||
int n = phexdigit[*psz++];
|
||||
int n = phexdigit[(unsigned char)*psz++];
|
||||
*this += n;
|
||||
}
|
||||
if (fNegative)
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "main.h"
|
||||
#include "wallet.h"
|
||||
#include "db.h"
|
||||
#include "walletdb.h"
|
||||
#include "net.h"
|
||||
#include "init.h"
|
||||
#include "ui_interface.h"
|
||||
#include "bitcoinrpc.h"
|
||||
|
||||
#undef printf
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -14,15 +19,10 @@
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#ifdef USE_SSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
|
||||
#endif
|
||||
#include "json/json_spirit_reader_template.h"
|
||||
#include "json/json_spirit_writer_template.h"
|
||||
#include "json/json_spirit_utils.h"
|
||||
|
||||
#define printf OutputDebugStringF
|
||||
// MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
|
||||
// precompiled in headers.h. The problem might be when the pch file goes over
|
||||
@@ -35,8 +35,6 @@ using namespace boost::asio;
|
||||
using namespace json_spirit;
|
||||
|
||||
void ThreadRPCServer2(void* parg);
|
||||
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
||||
extern map<string, rpcfn_type> mapCallTable;
|
||||
|
||||
static std::string strRPCUserColonPass;
|
||||
|
||||
@@ -140,7 +138,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||
{
|
||||
Object result;
|
||||
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
||||
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
|
||||
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
|
||||
result.push_back(Pair("height", blockindex->nHeight));
|
||||
result.push_back(Pair("version", block.nVersion));
|
||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||
@@ -166,6 +164,44 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||
/// Note: This interface may still be subject to change.
|
||||
///
|
||||
|
||||
string CRPCTable::help(string strCommand) const
|
||||
{
|
||||
string strRet;
|
||||
set<rpcfn_type> setDone;
|
||||
for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
|
||||
{
|
||||
const CRPCCommand *pcmd = mi->second;
|
||||
string strMethod = mi->first;
|
||||
// We already filter duplicates, but these deprecated screw up the sort order
|
||||
if (strMethod == "getamountreceived" ||
|
||||
strMethod == "getallreceived" ||
|
||||
strMethod == "getblocknumber" || // deprecated
|
||||
(strMethod.find("label") != string::npos))
|
||||
continue;
|
||||
if (strCommand != "" && strMethod != strCommand)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
Array params;
|
||||
rpcfn_type pfn = pcmd->actor;
|
||||
if (setDone.insert(pfn).second)
|
||||
(*pfn)(params, true);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Help text is returned in an exception
|
||||
string strHelp = string(e.what());
|
||||
if (strCommand == "")
|
||||
if (strHelp.find('\n') != string::npos)
|
||||
strHelp = strHelp.substr(0, strHelp.find('\n'));
|
||||
strRet += strHelp + "\n";
|
||||
}
|
||||
}
|
||||
if (strRet == "")
|
||||
strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
|
||||
strRet = strRet.substr(0,strRet.size()-1);
|
||||
return strRet;
|
||||
}
|
||||
|
||||
Value help(const Array& params, bool fHelp)
|
||||
{
|
||||
@@ -178,40 +214,7 @@ Value help(const Array& params, bool fHelp)
|
||||
if (params.size() > 0)
|
||||
strCommand = params[0].get_str();
|
||||
|
||||
string strRet;
|
||||
set<rpcfn_type> setDone;
|
||||
for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
|
||||
{
|
||||
string strMethod = (*mi).first;
|
||||
// We already filter duplicates, but these deprecated screw up the sort order
|
||||
if (strMethod == "getamountreceived" ||
|
||||
strMethod == "getallreceived" ||
|
||||
strMethod == "getblocknumber" || // deprecated
|
||||
(strMethod.find("label") != string::npos))
|
||||
continue;
|
||||
if (strCommand != "" && strMethod != strCommand)
|
||||
continue;
|
||||
try
|
||||
{
|
||||
Array params;
|
||||
rpcfn_type pfn = (*mi).second;
|
||||
if (setDone.insert(pfn).second)
|
||||
(*pfn)(params, true);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Help text is returned in an exception
|
||||
string strHelp = string(e.what());
|
||||
if (strCommand == "")
|
||||
if (strHelp.find('\n') != -1)
|
||||
strHelp = strHelp.substr(0, strHelp.find('\n'));
|
||||
strRet += strHelp + "\n";
|
||||
}
|
||||
}
|
||||
if (strRet == "")
|
||||
strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
|
||||
strRet = strRet.substr(0,strRet.size()-1);
|
||||
return strRet;
|
||||
return tableRPC.help(strCommand);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,13 +224,9 @@ Value stop(const Array& params, bool fHelp)
|
||||
throw runtime_error(
|
||||
"stop\n"
|
||||
"Stop bitcoin server.");
|
||||
#ifndef QT_GUI
|
||||
// Shutdown will take long enough that the response should get back
|
||||
CreateThread(Shutdown, NULL);
|
||||
StartShutdown();
|
||||
return "bitcoin server stopping";
|
||||
#else
|
||||
throw runtime_error("NYI: cannot shut down GUI with RPC command");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -369,7 +368,7 @@ Value getmininginfo(const Array& params, bool fHelp)
|
||||
obj.push_back(Pair("generate", GetBoolArg("-gen")));
|
||||
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
|
||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||
obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
|
||||
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
return obj;
|
||||
}
|
||||
@@ -604,7 +603,7 @@ Value signmessage(const Array& params, bool fHelp)
|
||||
if (!pwalletMain->GetKey(addr, key))
|
||||
throw JSONRPCError(-4, "Private key not available");
|
||||
|
||||
CDataStream ss(SER_GETHASH);
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << strMessageMagic;
|
||||
ss << strMessage;
|
||||
|
||||
@@ -636,7 +635,7 @@ Value verifymessage(const Array& params, bool fHelp)
|
||||
if (fInvalid)
|
||||
throw JSONRPCError(-5, "Malformed base64 encoding");
|
||||
|
||||
CDataStream ss(SER_GETHASH);
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << strMessageMagic;
|
||||
ss << strMessage;
|
||||
|
||||
@@ -802,8 +801,10 @@ Value getbalance(const Array& params, bool fHelp)
|
||||
list<pair<CBitcoinAddress, int64> > listSent;
|
||||
wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
|
||||
nBalance += r.second;
|
||||
}
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
|
||||
nBalance -= r.second;
|
||||
nBalance -= allFee;
|
||||
@@ -838,7 +839,8 @@ Value movecmd(const Array& params, bool fHelp)
|
||||
strComment = params[4].get_str();
|
||||
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
walletdb.TxnBegin();
|
||||
if (!walletdb.TxnBegin())
|
||||
throw JSONRPCError(-20, "database error");
|
||||
|
||||
int64 nNow = GetAdjustedTime();
|
||||
|
||||
@@ -860,7 +862,8 @@ Value movecmd(const Array& params, bool fHelp)
|
||||
credit.strComment = strComment;
|
||||
walletdb.WriteAccountingEntry(credit);
|
||||
|
||||
walletdb.TxnCommit();
|
||||
if (!walletdb.TxnCommit())
|
||||
throw JSONRPCError(-20, "database error");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -990,8 +993,6 @@ Value addmultisigaddress(const Array& params, bool fHelp)
|
||||
"If [account] is specified, assign address to [account].";
|
||||
throw runtime_error(msg);
|
||||
}
|
||||
if (!fTestNet)
|
||||
throw runtime_error("addmultisigaddress available only when running -testnet\n");
|
||||
|
||||
int nRequired = params[0].get_int();
|
||||
const Array& keys = params[1].get_array();
|
||||
@@ -1000,13 +1001,15 @@ Value addmultisigaddress(const Array& params, bool fHelp)
|
||||
strAccount = AccountFromValue(params[2]);
|
||||
|
||||
// Gather public keys
|
||||
if (nRequired < 1 || keys.size() < nRequired)
|
||||
if (nRequired < 1)
|
||||
throw runtime_error("a multisignature address must require at least one key to redeem");
|
||||
if ((int)keys.size() < nRequired)
|
||||
throw runtime_error(
|
||||
strprintf("wrong number of keys"
|
||||
"(got %d, need at least %d)", keys.size(), nRequired));
|
||||
strprintf("not enough keys supplied "
|
||||
"(got %d keys, but need at least %d to redeem)", keys.size(), nRequired));
|
||||
std::vector<CKey> pubkeys;
|
||||
pubkeys.resize(keys.size());
|
||||
for (int i = 0; i < keys.size(); i++)
|
||||
for (unsigned int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
const std::string& ks = keys[i].get_str();
|
||||
|
||||
@@ -1236,6 +1239,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
|
||||
// Received
|
||||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
{
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
|
||||
{
|
||||
string account;
|
||||
@@ -1253,6 +1257,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
ret.push_back(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
|
||||
@@ -1289,14 +1294,21 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
if (params.size() > 2)
|
||||
nFrom = params[2].get_int();
|
||||
|
||||
if (nCount < 0)
|
||||
throw JSONRPCError(-8, "Negative count");
|
||||
if (nFrom < 0)
|
||||
throw JSONRPCError(-8, "Negative from");
|
||||
|
||||
Array ret;
|
||||
CWalletDB walletdb(pwalletMain->strWalletFile);
|
||||
|
||||
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
|
||||
// First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
|
||||
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
|
||||
typedef multimap<int64, TxPair > TxItems;
|
||||
TxItems txByTime;
|
||||
|
||||
// Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
|
||||
// would make this much faster for applications that do this a lot.
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
CWalletTx* wtx = &((*it).second);
|
||||
@@ -1309,10 +1321,8 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
|
||||
}
|
||||
|
||||
// Now: iterate backwards until we have nCount items to return:
|
||||
TxItems::reverse_iterator it = txByTime.rbegin();
|
||||
if (txByTime.size() > nFrom) std::advance(it, nFrom);
|
||||
for (; it != txByTime.rend(); ++it)
|
||||
// iterate backwards until we have nCount items to return:
|
||||
for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
|
||||
{
|
||||
CWalletTx *const pwtx = (*it).second.first;
|
||||
if (pwtx != 0)
|
||||
@@ -1321,18 +1331,23 @@ Value listtransactions(const Array& params, bool fHelp)
|
||||
if (pacentry != 0)
|
||||
AcentryToJSON(*pacentry, strAccount, ret);
|
||||
|
||||
if (ret.size() >= nCount) break;
|
||||
if (ret.size() >= (nCount+nFrom)) break;
|
||||
}
|
||||
// ret is now newest to oldest
|
||||
// ret is newest to oldest
|
||||
|
||||
// Make sure we return only last nCount items (sends-to-self might give us an extra):
|
||||
if (ret.size() > nCount)
|
||||
{
|
||||
Array::iterator last = ret.begin();
|
||||
std::advance(last, nCount);
|
||||
ret.erase(last, ret.end());
|
||||
}
|
||||
std::reverse(ret.begin(), ret.end()); // oldest to newest
|
||||
if (nFrom > (int)ret.size())
|
||||
nFrom = ret.size();
|
||||
if ((nFrom + nCount) > (int)ret.size())
|
||||
nCount = ret.size() - nFrom;
|
||||
Array::iterator first = ret.begin();
|
||||
std::advance(first, nFrom);
|
||||
Array::iterator last = ret.begin();
|
||||
std::advance(last, nFrom+nCount);
|
||||
|
||||
if (last != ret.end()) ret.erase(last, ret.end());
|
||||
if (first != ret.begin()) ret.erase(ret.begin(), first);
|
||||
|
||||
std::reverse(ret.begin(), ret.end()); // Return oldest to newest
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1392,8 +1407,8 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp)
|
||||
throw runtime_error(
|
||||
"listsinceblock [blockid] [target-confirmations]\n"
|
||||
"Get all transactions in blocks since block [blockid], or all transactions if omitted");
|
||||
"listsinceblock [blockhash] [target-confirmations]\n"
|
||||
"Get all transactions in blocks since block [blockhash], or all transactions if omitted");
|
||||
|
||||
CBlockIndex *pindex = NULL;
|
||||
int target_confirms = 1;
|
||||
@@ -1430,7 +1445,6 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||
|
||||
if (target_confirms == 1)
|
||||
{
|
||||
printf("oops!\n");
|
||||
lastblock = hashBestChain;
|
||||
}
|
||||
else
|
||||
@@ -1655,8 +1669,8 @@ Value walletlock(const Array& params, bool fHelp)
|
||||
if (!pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
|
||||
|
||||
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||
{
|
||||
LOCK(cs_nWalletUnlockTime);
|
||||
pwalletMain->Lock();
|
||||
nWalletUnlockTime = 0;
|
||||
}
|
||||
@@ -1676,11 +1690,6 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
if (pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
|
||||
|
||||
#ifdef QT_GUI
|
||||
// shutting down via RPC while the GUI is running does not work (yet):
|
||||
throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
|
||||
#endif
|
||||
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make params[0] mlock()'d to begin with.
|
||||
SecureString strWalletPass;
|
||||
@@ -1698,7 +1707,7 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
// BDB seems to have a bad habit of writing old data into
|
||||
// slack space in .dat files; that is bad if the old data is
|
||||
// unencrypted private keys. So:
|
||||
CreateThread(Shutdown, NULL);
|
||||
StartShutdown();
|
||||
return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
|
||||
}
|
||||
|
||||
@@ -1918,7 +1927,7 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
if(tx.IsCoinBase())
|
||||
continue;
|
||||
|
||||
CDataStream ssTx;
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << tx;
|
||||
|
||||
transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
|
||||
@@ -1940,7 +1949,7 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
else
|
||||
{
|
||||
// Parse parameters
|
||||
CDataStream ssBlock(ParseHex(params[0].get_str()));
|
||||
CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CBlock pblock;
|
||||
ssBlock >> pblock;
|
||||
|
||||
@@ -2000,86 +2009,77 @@ Value getblock(const Array& params, bool fHelp)
|
||||
// Call Table
|
||||
//
|
||||
|
||||
pair<string, rpcfn_type> pCallTable[] =
|
||||
{
|
||||
make_pair("help", &help),
|
||||
make_pair("stop", &stop),
|
||||
make_pair("getblockcount", &getblockcount),
|
||||
make_pair("getblocknumber", &getblocknumber),
|
||||
make_pair("getconnectioncount", &getconnectioncount),
|
||||
make_pair("getdifficulty", &getdifficulty),
|
||||
make_pair("getgenerate", &getgenerate),
|
||||
make_pair("setgenerate", &setgenerate),
|
||||
make_pair("gethashespersec", &gethashespersec),
|
||||
make_pair("getinfo", &getinfo),
|
||||
make_pair("getmininginfo", &getmininginfo),
|
||||
make_pair("getnewaddress", &getnewaddress),
|
||||
make_pair("getaccountaddress", &getaccountaddress),
|
||||
make_pair("setaccount", &setaccount),
|
||||
make_pair("getaccount", &getaccount),
|
||||
make_pair("getaddressesbyaccount", &getaddressesbyaccount),
|
||||
make_pair("sendtoaddress", &sendtoaddress),
|
||||
make_pair("getreceivedbyaddress", &getreceivedbyaddress),
|
||||
make_pair("getreceivedbyaccount", &getreceivedbyaccount),
|
||||
make_pair("listreceivedbyaddress", &listreceivedbyaddress),
|
||||
make_pair("listreceivedbyaccount", &listreceivedbyaccount),
|
||||
make_pair("backupwallet", &backupwallet),
|
||||
make_pair("keypoolrefill", &keypoolrefill),
|
||||
make_pair("walletpassphrase", &walletpassphrase),
|
||||
make_pair("walletpassphrasechange", &walletpassphrasechange),
|
||||
make_pair("walletlock", &walletlock),
|
||||
make_pair("encryptwallet", &encryptwallet),
|
||||
make_pair("validateaddress", &validateaddress),
|
||||
make_pair("getbalance", &getbalance),
|
||||
make_pair("move", &movecmd),
|
||||
make_pair("sendfrom", &sendfrom),
|
||||
make_pair("sendmany", &sendmany),
|
||||
make_pair("addmultisigaddress", &addmultisigaddress),
|
||||
make_pair("getblock", &getblock),
|
||||
make_pair("getblockhash", &getblockhash),
|
||||
make_pair("gettransaction", &gettransaction),
|
||||
make_pair("listtransactions", &listtransactions),
|
||||
make_pair("signmessage", &signmessage),
|
||||
make_pair("verifymessage", &verifymessage),
|
||||
make_pair("getwork", &getwork),
|
||||
make_pair("listaccounts", &listaccounts),
|
||||
make_pair("settxfee", &settxfee),
|
||||
make_pair("getmemorypool", &getmemorypool),
|
||||
make_pair("listsinceblock", &listsinceblock),
|
||||
make_pair("dumpprivkey", &dumpprivkey),
|
||||
make_pair("importprivkey", &importprivkey)
|
||||
|
||||
static const CRPCCommand vRPCCommands[] =
|
||||
{ // name function safe mode?
|
||||
// ------------------------ ----------------------- ----------
|
||||
{ "help", &help, true },
|
||||
{ "stop", &stop, true },
|
||||
{ "getblockcount", &getblockcount, true },
|
||||
{ "getblocknumber", &getblocknumber, true },
|
||||
{ "getconnectioncount", &getconnectioncount, true },
|
||||
{ "getdifficulty", &getdifficulty, true },
|
||||
{ "getgenerate", &getgenerate, true },
|
||||
{ "setgenerate", &setgenerate, true },
|
||||
{ "gethashespersec", &gethashespersec, true },
|
||||
{ "getinfo", &getinfo, true },
|
||||
{ "getmininginfo", &getmininginfo, true },
|
||||
{ "getnewaddress", &getnewaddress, true },
|
||||
{ "getaccountaddress", &getaccountaddress, true },
|
||||
{ "setaccount", &setaccount, true },
|
||||
{ "getaccount", &getaccount, false },
|
||||
{ "getaddressesbyaccount", &getaddressesbyaccount, true },
|
||||
{ "sendtoaddress", &sendtoaddress, false },
|
||||
{ "getreceivedbyaddress", &getreceivedbyaddress, false },
|
||||
{ "getreceivedbyaccount", &getreceivedbyaccount, false },
|
||||
{ "listreceivedbyaddress", &listreceivedbyaddress, false },
|
||||
{ "listreceivedbyaccount", &listreceivedbyaccount, false },
|
||||
{ "backupwallet", &backupwallet, true },
|
||||
{ "keypoolrefill", &keypoolrefill, true },
|
||||
{ "walletpassphrase", &walletpassphrase, true },
|
||||
{ "walletpassphrasechange", &walletpassphrasechange, false },
|
||||
{ "walletlock", &walletlock, true },
|
||||
{ "encryptwallet", &encryptwallet, false },
|
||||
{ "validateaddress", &validateaddress, true },
|
||||
{ "getbalance", &getbalance, false },
|
||||
{ "move", &movecmd, false },
|
||||
{ "sendfrom", &sendfrom, false },
|
||||
{ "sendmany", &sendmany, false },
|
||||
{ "addmultisigaddress", &addmultisigaddress, false },
|
||||
{ "getblock", &getblock, false },
|
||||
{ "getblockhash", &getblockhash, false },
|
||||
{ "gettransaction", &gettransaction, false },
|
||||
{ "listtransactions", &listtransactions, false },
|
||||
{ "signmessage", &signmessage, false },
|
||||
{ "verifymessage", &verifymessage, false },
|
||||
{ "getwork", &getwork, true },
|
||||
{ "listaccounts", &listaccounts, false },
|
||||
{ "settxfee", &settxfee, false },
|
||||
{ "getmemorypool", &getmemorypool, true },
|
||||
{ "listsinceblock", &listsinceblock, false },
|
||||
{ "dumpprivkey", &dumpprivkey, false },
|
||||
{ "importprivkey", &importprivkey, false },
|
||||
};
|
||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||
|
||||
string pAllowInSafeMode[] =
|
||||
CRPCTable::CRPCTable()
|
||||
{
|
||||
"help",
|
||||
"stop",
|
||||
"getblockcount",
|
||||
"getblocknumber", // deprecated
|
||||
"getconnectioncount",
|
||||
"getdifficulty",
|
||||
"getgenerate",
|
||||
"setgenerate",
|
||||
"gethashespersec",
|
||||
"getinfo",
|
||||
"getmininginfo",
|
||||
"getnewaddress",
|
||||
"getaccountaddress",
|
||||
"getaccount",
|
||||
"getaddressesbyaccount",
|
||||
"backupwallet",
|
||||
"keypoolrefill",
|
||||
"walletpassphrase",
|
||||
"walletlock",
|
||||
"validateaddress",
|
||||
"getwork",
|
||||
"getmemorypool",
|
||||
};
|
||||
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
|
||||
|
||||
unsigned int vcidx;
|
||||
for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
|
||||
{
|
||||
const CRPCCommand *pcmd;
|
||||
|
||||
pcmd = &vRPCCommands[vcidx];
|
||||
mapCommands[pcmd->name] = pcmd;
|
||||
}
|
||||
}
|
||||
|
||||
const CRPCCommand *CRPCTable::operator[](string name) const
|
||||
{
|
||||
map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
|
||||
if (it == mapCommands.end())
|
||||
return NULL;
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
//
|
||||
// HTTP protocol
|
||||
@@ -2207,7 +2207,7 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
|
||||
|
||||
// Read header
|
||||
int nLen = ReadHTTPHeader(stream, mapHeadersRet);
|
||||
if (nLen < 0 || nLen > MAX_SIZE)
|
||||
if (nLen < 0 || nLen > (int)MAX_SIZE)
|
||||
return 500;
|
||||
|
||||
// Read message
|
||||
@@ -2284,7 +2284,6 @@ bool ClientAllowed(const string& strAddress)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
//
|
||||
// IOStream device that speaks SSL but can also speak non-SSL
|
||||
//
|
||||
@@ -2336,7 +2335,6 @@ private:
|
||||
bool fUseSSL;
|
||||
SSLStream& stream;
|
||||
};
|
||||
#endif
|
||||
|
||||
void ThreadRPCServer(void* parg)
|
||||
{
|
||||
@@ -2371,7 +2369,7 @@ void ThreadRPCServer2(void* parg)
|
||||
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
|
||||
else if (mapArgs.count("-daemon"))
|
||||
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
|
||||
::error(
|
||||
ThreadSafeMessageBox(strprintf(
|
||||
_("%s, you must set a rpcpassword in the configuration file:\n %s\n"
|
||||
"It is recommended you use the following random password:\n"
|
||||
"rpcuser=bitcoinrpc\n"
|
||||
@@ -2379,11 +2377,10 @@ void ThreadRPCServer2(void* parg)
|
||||
"(you do not need to remember this password)\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
|
||||
strWhatAmI.c_str(),
|
||||
GetConfigFile().c_str(),
|
||||
EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
|
||||
#ifndef QT_GUI
|
||||
CreateThread(Shutdown, NULL);
|
||||
#endif
|
||||
GetConfigFile().string().c_str(),
|
||||
EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
|
||||
_("Error"), wxOK | wxMODAL);
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2392,51 +2389,51 @@ void ThreadRPCServer2(void* parg)
|
||||
|
||||
asio::io_service io_service;
|
||||
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
|
||||
ip::tcp::acceptor acceptor(io_service, endpoint);
|
||||
ip::tcp::acceptor acceptor(io_service);
|
||||
try
|
||||
{
|
||||
acceptor.open(endpoint.protocol());
|
||||
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||
acceptor.bind(endpoint);
|
||||
acceptor.listen(socket_base::max_connections);
|
||||
}
|
||||
catch(boost::system::system_error &e)
|
||||
{
|
||||
ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
|
||||
_("Error"), wxOK | wxMODAL);
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||
|
||||
#ifdef USE_SSL
|
||||
ssl::context context(io_service, ssl::context::sslv23);
|
||||
if (fUseSSL)
|
||||
{
|
||||
context.set_options(ssl::context::no_sslv2);
|
||||
filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
|
||||
if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
|
||||
if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
|
||||
else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
|
||||
filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
|
||||
if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
|
||||
if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
|
||||
else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
|
||||
|
||||
string ciphers = GetArg("-rpcsslciphers",
|
||||
"TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
|
||||
SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
|
||||
filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
|
||||
if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
|
||||
if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
|
||||
else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
|
||||
|
||||
filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
|
||||
if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
|
||||
if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
|
||||
else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
|
||||
|
||||
string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
|
||||
SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
|
||||
}
|
||||
#else
|
||||
if (fUseSSL)
|
||||
throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
|
||||
#endif
|
||||
|
||||
loop
|
||||
{
|
||||
// Accept connection
|
||||
#ifdef USE_SSL
|
||||
SSLStream sslStream(io_service, context);
|
||||
SSLIOStreamDevice d(sslStream, fUseSSL);
|
||||
iostreams::stream<SSLIOStreamDevice> stream(d);
|
||||
#else
|
||||
ip::tcp::iostream stream;
|
||||
#endif
|
||||
|
||||
ip::tcp::endpoint peer;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]--;
|
||||
#ifdef USE_SSL
|
||||
acceptor.accept(sslStream.lowest_layer(), peer);
|
||||
#else
|
||||
acceptor.accept(*stream.rdbuf(), peer);
|
||||
#endif
|
||||
vnThreadsRunning[4]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
@@ -2513,22 +2510,24 @@ void ThreadRPCServer2(void* parg)
|
||||
throw JSONRPCError(-32600, "Params must be an array");
|
||||
|
||||
// Find method
|
||||
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
|
||||
if (mi == mapCallTable.end())
|
||||
const CRPCCommand *pcmd = tableRPC[strMethod];
|
||||
if (!pcmd)
|
||||
throw JSONRPCError(-32601, "Method not found");
|
||||
|
||||
// Observe safe mode
|
||||
string strWarning = GetWarnings("rpc");
|
||||
if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
|
||||
if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
|
||||
!pcmd->okSafeMode)
|
||||
throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
|
||||
|
||||
try
|
||||
{
|
||||
// Execute
|
||||
Value result;
|
||||
CRITICAL_BLOCK(cs_main)
|
||||
CRITICAL_BLOCK(pwalletMain->cs_wallet)
|
||||
result = (*(*mi).second)(params, false);
|
||||
{
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
result = pcmd->actor(params, false);
|
||||
}
|
||||
|
||||
// Send reply
|
||||
string strReply = JSONRPCReply(result, Value::null, id);
|
||||
@@ -2559,11 +2558,10 @@ Object CallRPC(const string& strMethod, const Array& params)
|
||||
throw runtime_error(strprintf(
|
||||
_("You must set rpcpassword=<password> in the configuration file:\n%s\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions."),
|
||||
GetConfigFile().c_str()));
|
||||
GetConfigFile().string().c_str()));
|
||||
|
||||
// Connect to localhost
|
||||
bool fUseSSL = GetBoolArg("-rpcssl");
|
||||
#ifdef USE_SSL
|
||||
asio::io_service io_service;
|
||||
ssl::context context(io_service, ssl::context::sslv23);
|
||||
context.set_options(ssl::context::no_sslv2);
|
||||
@@ -2572,15 +2570,6 @@ Object CallRPC(const string& strMethod, const Array& params)
|
||||
iostreams::stream<SSLIOStreamDevice> stream(d);
|
||||
if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
|
||||
throw runtime_error("couldn't connect to server");
|
||||
#else
|
||||
if (fUseSSL)
|
||||
throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
|
||||
|
||||
ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
|
||||
if (stream.fail())
|
||||
throw runtime_error("couldn't connect to server");
|
||||
#endif
|
||||
|
||||
|
||||
// HTTP basic authentication
|
||||
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
|
||||
@@ -2778,3 +2767,5 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const CRPCTable tableRPC;
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef _BITCOINRPC_H_
|
||||
#define _BITCOINRPC_H_ 1
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "json/json_spirit_reader_template.h"
|
||||
#include "json/json_spirit_writer_template.h"
|
||||
#include "json/json_spirit_utils.h"
|
||||
|
||||
void ThreadRPCServer(void* parg);
|
||||
int CommandLineRPC(int argc, char *argv[]);
|
||||
|
||||
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
class CRPCCommand
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
rpcfn_type actor;
|
||||
bool okSafeMode;
|
||||
};
|
||||
|
||||
class CRPCTable
|
||||
{
|
||||
private:
|
||||
std::map<std::string, const CRPCCommand*> mapCommands;
|
||||
public:
|
||||
CRPCTable();
|
||||
const CRPCCommand* operator[](std::string name) const;
|
||||
std::string help(std::string name) const;
|
||||
};
|
||||
|
||||
extern const CRPCTable tableRPC;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "headers.h"
|
||||
#include "checkpoints.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "uint256.h"
|
||||
|
||||
namespace Checkpoints
|
||||
{
|
||||
typedef std::map<int, uint256> MapCheckpoints;
|
||||
@@ -23,14 +25,11 @@ namespace Checkpoints
|
||||
boost::assign::map_list_of
|
||||
( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"))
|
||||
( 33333, uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6"))
|
||||
( 68555, uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a"))
|
||||
( 70567, uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a"))
|
||||
( 74000, uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))
|
||||
(105000, uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"))
|
||||
(118000, uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))
|
||||
(134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
|
||||
(140700, uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd"))
|
||||
(168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
|
||||
(185333, uint256("0x00000000000002334c71b8706940c20348af897a9cfc0f1a6dab0d14d4ceb815"))
|
||||
;
|
||||
|
||||
bool CheckBlock(int nHeight, const uint256& hash)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_CHECKPOINT_H
|
||||
#define BITCOIN_CHECKPOINT_H
|
||||
|
||||
#include <map>
|
||||
#include "util.h"
|
||||
|
||||
class uint256;
|
||||
class CBlockIndex;
|
||||
|
||||
23
src/compat.h
23
src/compat.h
@@ -1,10 +1,30 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef _BITCOIN_COMPAT_H
|
||||
#define _BITCOIN_COMPAT_H 1
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
typedef u_int SOCKET;
|
||||
#ifdef WIN32
|
||||
#define MSG_NOSIGNAL 0
|
||||
@@ -39,4 +59,5 @@ inline int myclosesocket(SOCKET& hSocket)
|
||||
}
|
||||
#define closesocket(s) myclosesocket(s)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,14 +6,11 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "headers.h"
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "crypter.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
|
||||
{
|
||||
@@ -31,7 +28,7 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v
|
||||
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
|
||||
(unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV);
|
||||
|
||||
if (i != WALLET_CRYPTO_KEY_SIZE)
|
||||
if (i != (int)WALLET_CRYPTO_KEY_SIZE)
|
||||
{
|
||||
memset(&chKey, 0, sizeof chKey);
|
||||
memset(&chIV, 0, sizeof chIV);
|
||||
@@ -73,14 +70,16 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
bool fOk = true;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||
|
||||
EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
|
||||
EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
|
||||
|
||||
if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||
if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen);
|
||||
if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
if (!fOk) return false;
|
||||
|
||||
vchCiphertext.resize(nCLen + nFLen);
|
||||
return true;
|
||||
}
|
||||
@@ -98,14 +97,16 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
bool fOk = true;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||
|
||||
EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
|
||||
EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
|
||||
|
||||
if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV);
|
||||
if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen);
|
||||
if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
|
||||
if (!fOk) return false;
|
||||
|
||||
vchPlaintext.resize(nPLen + nFLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
#ifndef __CRYPTER_H__
|
||||
#define __CRYPTER_H__
|
||||
|
||||
#include "util.h" /* for SecureString */
|
||||
#include "allocators.h" /* for SecureString */
|
||||
#include "key.h"
|
||||
#include "serialize.h"
|
||||
|
||||
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
||||
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
||||
|
||||
537
src/db.cpp
537
src/db.cpp
@@ -1,21 +1,24 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "db.h"
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#ifndef WIN32
|
||||
#include "sys/stat.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
|
||||
unsigned int nWalletDBUpdated;
|
||||
uint64 nAccountingEntryNumber = 0;
|
||||
|
||||
|
||||
|
||||
@@ -23,12 +26,12 @@ uint64 nAccountingEntryNumber = 0;
|
||||
// CDB
|
||||
//
|
||||
|
||||
static CCriticalSection cs_db;
|
||||
CCriticalSection cs_db;
|
||||
static bool fDbEnvInit = false;
|
||||
bool fDetachDB = false;
|
||||
DbEnv dbenv(0);
|
||||
static map<string, int> mapFileUseCount;
|
||||
map<string, int> mapFileUseCount;
|
||||
static map<string, Db*> mapDb;
|
||||
static int64 nTxn = 0;
|
||||
|
||||
static void EnvShutdown()
|
||||
{
|
||||
@@ -44,7 +47,7 @@ static void EnvShutdown()
|
||||
{
|
||||
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
|
||||
}
|
||||
DbEnv(0).remove(GetDataDir().c_str(), 0);
|
||||
DbEnv(0).remove(GetDataDir().string().c_str(), 0);
|
||||
}
|
||||
|
||||
class CDBInit
|
||||
@@ -61,7 +64,7 @@ public:
|
||||
instance_of_cdbinit;
|
||||
|
||||
|
||||
CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
|
||||
CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
|
||||
{
|
||||
int ret;
|
||||
if (pszFile == NULL)
|
||||
@@ -73,29 +76,30 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
|
||||
if (fCreate)
|
||||
nFlags |= DB_CREATE;
|
||||
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (!fDbEnvInit)
|
||||
{
|
||||
if (fShutdown)
|
||||
return;
|
||||
string strDataDir = GetDataDir();
|
||||
string strLogDir = strDataDir + "/database";
|
||||
filesystem::create_directory(strLogDir.c_str());
|
||||
string strErrorFile = strDataDir + "/db.log";
|
||||
printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
|
||||
filesystem::path pathDataDir = GetDataDir();
|
||||
filesystem::path pathLogDir = pathDataDir / "database";
|
||||
filesystem::create_directory(pathLogDir);
|
||||
filesystem::path pathErrorFile = pathDataDir / "db.log";
|
||||
printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str());
|
||||
|
||||
int nDbCache = GetArg("-dbcache", 25);
|
||||
dbenv.set_lg_dir(strLogDir.c_str());
|
||||
dbenv.set_lg_dir(pathLogDir.string().c_str());
|
||||
dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
|
||||
dbenv.set_lg_bsize(1048576);
|
||||
dbenv.set_lg_max(10485760);
|
||||
dbenv.set_lk_max_locks(10000);
|
||||
dbenv.set_lk_max_objects(10000);
|
||||
dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug
|
||||
dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
|
||||
dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
|
||||
ret = dbenv.open(strDataDir.c_str(),
|
||||
ret = dbenv.open(pathDataDir.string().c_str(),
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
@@ -127,8 +131,10 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
|
||||
{
|
||||
delete pdb;
|
||||
pdb = NULL;
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
--mapFileUseCount[strFile];
|
||||
}
|
||||
strFile = "";
|
||||
throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
|
||||
}
|
||||
@@ -161,25 +167,23 @@ void CDB::Close()
|
||||
nMinutes = 1;
|
||||
if (strFile == "addr.dat")
|
||||
nMinutes = 2;
|
||||
if (strFile == "blkindex.dat")
|
||||
nMinutes = 2;
|
||||
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
|
||||
nMinutes = 5;
|
||||
|
||||
if (nMinutes == 0 || nTxn > 200000)
|
||||
dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
|
||||
|
||||
{
|
||||
nTxn = 0;
|
||||
nMinutes = 0;
|
||||
}
|
||||
|
||||
dbenv.txn_checkpoint(0, nMinutes, 0);
|
||||
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
LOCK(cs_db);
|
||||
--mapFileUseCount[strFile];
|
||||
}
|
||||
}
|
||||
|
||||
void static CloseDb(const string& strFile)
|
||||
void CloseDb(const string& strFile)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (mapDb[strFile] != NULL)
|
||||
{
|
||||
// Close the database handle
|
||||
@@ -195,8 +199,8 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
{
|
||||
while (!fShutdown)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
|
||||
{
|
||||
// Flush log data to the dat file
|
||||
@@ -228,8 +232,8 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
if (pcursor)
|
||||
while (fSuccess)
|
||||
{
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
|
||||
if (ret == DB_NOTFOUND)
|
||||
{
|
||||
@@ -293,8 +297,8 @@ void DBFlush(bool fShutdown)
|
||||
printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
map<string, int>::iterator mi = mapFileUseCount.begin();
|
||||
while (mi != mapFileUseCount.end())
|
||||
{
|
||||
@@ -305,9 +309,13 @@ void DBFlush(bool fShutdown)
|
||||
{
|
||||
// Move log data to the dat file
|
||||
CloseDb(strFile);
|
||||
printf("%s checkpoint\n", strFile.c_str());
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
printf("%s flush\n", strFile.c_str());
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
if ((strFile != "blkindex.dat" && strFile != "addr.dat") || fDetachDB) {
|
||||
printf("%s detach\n", strFile.c_str());
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
}
|
||||
printf("%s closed\n", strFile.c_str());
|
||||
mapFileUseCount.erase(mi++);
|
||||
}
|
||||
else
|
||||
@@ -344,7 +352,6 @@ bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
|
||||
bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
|
||||
{
|
||||
assert(!fClient);
|
||||
nTxn++;
|
||||
return Write(make_pair(string("tx"), hash), txindex);
|
||||
}
|
||||
|
||||
@@ -355,7 +362,6 @@ bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeigh
|
||||
// Add to tx index
|
||||
uint256 hash = tx.GetHash();
|
||||
CTxIndex txindex(pos, tx.vout.size());
|
||||
nTxn++;
|
||||
return Write(make_pair(string("tx"), hash), txindex);
|
||||
}
|
||||
|
||||
@@ -387,10 +393,10 @@ bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>&
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
|
||||
CDataStream ssValue;
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
@@ -405,9 +411,15 @@ bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>&
|
||||
string strType;
|
||||
uint160 hashItem;
|
||||
CDiskTxPos pos;
|
||||
ssKey >> strType >> hashItem >> pos;
|
||||
int nItemHeight;
|
||||
ssValue >> nItemHeight;
|
||||
|
||||
try {
|
||||
ssKey >> strType >> hashItem >> pos;
|
||||
ssValue >> nItemHeight;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Read transaction
|
||||
if (strType != "owner" || hashItem != hash160)
|
||||
@@ -515,10 +527,10 @@ bool CTxDB::LoadBlockIndex()
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << make_pair(string("blockindex"), uint256(0));
|
||||
CDataStream ssValue;
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
@@ -527,9 +539,11 @@ bool CTxDB::LoadBlockIndex()
|
||||
return false;
|
||||
|
||||
// Unserialize
|
||||
|
||||
try {
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "blockindex")
|
||||
if (strType == "blockindex" && !fRequestShutdown)
|
||||
{
|
||||
CDiskBlockIndex diskindex;
|
||||
ssValue >> diskindex;
|
||||
@@ -556,11 +570,18 @@ bool CTxDB::LoadBlockIndex()
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
break; // if shutdown requested or finished loading block index
|
||||
}
|
||||
} // try
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
}
|
||||
pcursor->close();
|
||||
|
||||
if (fRequestShutdown)
|
||||
return true;
|
||||
|
||||
// Calculate bnChainWork
|
||||
vector<pair<int, CBlockIndex*> > vSortedByHeight;
|
||||
vSortedByHeight.reserve(mapBlockIndex.size());
|
||||
@@ -645,8 +666,9 @@ bool CTxDB::LoadBlockIndex()
|
||||
}
|
||||
}
|
||||
// check level 4: check whether spent txouts were spent within the main chain
|
||||
int nOutput = 0;
|
||||
unsigned int nOutput = 0;
|
||||
if (nCheckLevel>3)
|
||||
{
|
||||
BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
|
||||
{
|
||||
if (!txpos.IsNull())
|
||||
@@ -687,9 +709,11 @@ bool CTxDB::LoadBlockIndex()
|
||||
}
|
||||
nOutput++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check level 5: check whether all prevouts are marked spent
|
||||
if (nCheckLevel>4)
|
||||
{
|
||||
BOOST_FOREACH(const CTxIn &txin, tx.vin)
|
||||
{
|
||||
CTxIndex txindex;
|
||||
@@ -700,6 +724,7 @@ bool CTxDB::LoadBlockIndex()
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,8 +776,8 @@ bool CAddrDB::LoadAddresses()
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
@@ -787,419 +812,3 @@ bool LoadAddresses()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CWalletDB
|
||||
//
|
||||
|
||||
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(make_pair(string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
bool CWalletDB::EraseName(const string& strAddress)
|
||||
{
|
||||
// This should only be used for sending addresses, never for receiving addresses,
|
||||
// receiving addresses must always have an address book entry if they're not change return.
|
||||
nWalletDBUpdated++;
|
||||
return Erase(make_pair(string("name"), strAddress));
|
||||
}
|
||||
|
||||
bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account)
|
||||
{
|
||||
account.SetNull();
|
||||
return Read(make_pair(string("acc"), strAccount), account);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account)
|
||||
{
|
||||
return Write(make_pair(string("acc"), strAccount), account);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry)
|
||||
{
|
||||
return Write(boost::make_tuple(string("acentry"), acentry.strAccount, ++nAccountingEntryNumber), acentry);
|
||||
}
|
||||
|
||||
int64 CWalletDB::GetAccountCreditDebit(const string& strAccount)
|
||||
{
|
||||
list<CAccountingEntry> entries;
|
||||
ListAccountCreditDebit(strAccount, entries);
|
||||
|
||||
int64 nCreditDebit = 0;
|
||||
BOOST_FOREACH (const CAccountingEntry& entry, entries)
|
||||
nCreditDebit += entry.nCreditDebit;
|
||||
|
||||
return nCreditDebit;
|
||||
}
|
||||
|
||||
void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountingEntry>& entries)
|
||||
{
|
||||
bool fAllAccounts = (strAccount == "*");
|
||||
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor");
|
||||
unsigned int fFlags = DB_SET_RANGE;
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64(0));
|
||||
CDataStream ssValue;
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
{
|
||||
pcursor->close();
|
||||
throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB");
|
||||
}
|
||||
|
||||
// Unserialize
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType != "acentry")
|
||||
break;
|
||||
CAccountingEntry acentry;
|
||||
ssKey >> acentry.strAccount;
|
||||
if (!fAllAccounts && acentry.strAccount != strAccount)
|
||||
break;
|
||||
|
||||
ssValue >> acentry;
|
||||
entries.push_back(acentry);
|
||||
}
|
||||
|
||||
pcursor->close();
|
||||
}
|
||||
|
||||
|
||||
int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
{
|
||||
pwallet->vchDefaultKey.clear();
|
||||
int nFileVersion = 0;
|
||||
vector<uint256> vWalletUpgrade;
|
||||
bool fIsEncrypted = false;
|
||||
|
||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||
{
|
||||
int nMinVersion = 0;
|
||||
if (Read((string)"minversion", nMinVersion))
|
||||
{
|
||||
if (nMinVersion > CLIENT_VERSION)
|
||||
return DB_TOO_NEW;
|
||||
pwallet->LoadMinVersion(nMinVersion);
|
||||
}
|
||||
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
{
|
||||
printf("Error getting wallet database cursor\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
{
|
||||
printf("Error reading next record from wallet database\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
|
||||
// Unserialize
|
||||
// Taking advantage of the fact that pair serialization
|
||||
// is just the two items serialized one after the other
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "name")
|
||||
{
|
||||
string strAddress;
|
||||
ssKey >> strAddress;
|
||||
ssValue >> pwallet->mapAddressBook[strAddress];
|
||||
}
|
||||
else if (strType == "tx")
|
||||
{
|
||||
uint256 hash;
|
||||
ssKey >> hash;
|
||||
CWalletTx& wtx = pwallet->mapWallet[hash];
|
||||
ssValue >> wtx;
|
||||
wtx.BindWallet(pwallet);
|
||||
|
||||
if (wtx.GetHash() != hash)
|
||||
printf("Error in wallet.dat, hash mismatch\n");
|
||||
|
||||
// Undo serialize changes in 31600
|
||||
if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
|
||||
{
|
||||
if (!ssValue.empty())
|
||||
{
|
||||
char fTmp;
|
||||
char fUnused;
|
||||
ssValue >> fTmp >> fUnused >> wtx.strFromAccount;
|
||||
printf("LoadWallet() upgrading tx ver=%d %d '%s' %s\n", wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str());
|
||||
wtx.fTimeReceivedIsTxTime = fTmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str());
|
||||
wtx.fTimeReceivedIsTxTime = 0;
|
||||
}
|
||||
vWalletUpgrade.push_back(hash);
|
||||
}
|
||||
|
||||
//// debug print
|
||||
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
|
||||
//printf(" %12I64d %s %s %s\n",
|
||||
// wtx.vout[0].nValue,
|
||||
// DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
|
||||
// wtx.hashBlock.ToString().substr(0,20).c_str(),
|
||||
// wtx.mapValue["message"].c_str());
|
||||
}
|
||||
else if (strType == "acentry")
|
||||
{
|
||||
string strAccount;
|
||||
ssKey >> strAccount;
|
||||
uint64 nNumber;
|
||||
ssKey >> nNumber;
|
||||
if (nNumber > nAccountingEntryNumber)
|
||||
nAccountingEntryNumber = nNumber;
|
||||
}
|
||||
else if (strType == "key" || strType == "wkey")
|
||||
{
|
||||
vector<unsigned char> vchPubKey;
|
||||
ssKey >> vchPubKey;
|
||||
CKey key;
|
||||
if (strType == "key")
|
||||
{
|
||||
CPrivKey pkey;
|
||||
ssValue >> pkey;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetPrivKey(pkey);
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
printf("Error reading wallet database: CPrivKey pubkey inconsistency\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
if (!key.IsValid())
|
||||
{
|
||||
printf("Error reading wallet database: invalid CPrivKey\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CWalletKey wkey;
|
||||
ssValue >> wkey;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetPrivKey(wkey.vchPrivKey);
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
printf("Error reading wallet database: CWalletKey pubkey inconsistency\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
if (!key.IsValid())
|
||||
{
|
||||
printf("Error reading wallet database: invalid CWalletKey\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
if (!pwallet->LoadKey(key))
|
||||
{
|
||||
printf("Error reading wallet database: LoadKey failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
else if (strType == "mkey")
|
||||
{
|
||||
unsigned int nID;
|
||||
ssKey >> nID;
|
||||
CMasterKey kMasterKey;
|
||||
ssValue >> kMasterKey;
|
||||
if(pwallet->mapMasterKeys.count(nID) != 0)
|
||||
{
|
||||
printf("Error reading wallet database: duplicate CMasterKey id %u\n", nID);
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
pwallet->mapMasterKeys[nID] = kMasterKey;
|
||||
if (pwallet->nMasterKeyMaxID < nID)
|
||||
pwallet->nMasterKeyMaxID = nID;
|
||||
}
|
||||
else if (strType == "ckey")
|
||||
{
|
||||
vector<unsigned char> vchPubKey;
|
||||
ssKey >> vchPubKey;
|
||||
vector<unsigned char> vchPrivKey;
|
||||
ssValue >> vchPrivKey;
|
||||
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
|
||||
{
|
||||
printf("Error reading wallet database: LoadCryptedKey failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
fIsEncrypted = true;
|
||||
}
|
||||
else if (strType == "defaultkey")
|
||||
{
|
||||
ssValue >> pwallet->vchDefaultKey;
|
||||
}
|
||||
else if (strType == "pool")
|
||||
{
|
||||
int64 nIndex;
|
||||
ssKey >> nIndex;
|
||||
pwallet->setKeyPool.insert(nIndex);
|
||||
}
|
||||
else if (strType == "version")
|
||||
{
|
||||
ssValue >> nFileVersion;
|
||||
if (nFileVersion == 10300)
|
||||
nFileVersion = 300;
|
||||
}
|
||||
else if (strType == "cscript")
|
||||
{
|
||||
uint160 hash;
|
||||
ssKey >> hash;
|
||||
CScript script;
|
||||
ssValue >> script;
|
||||
if (!pwallet->LoadCScript(script))
|
||||
{
|
||||
printf("Error reading wallet database: LoadCScript failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
pcursor->close();
|
||||
}
|
||||
|
||||
BOOST_FOREACH(uint256 hash, vWalletUpgrade)
|
||||
WriteTx(hash, pwallet->mapWallet[hash]);
|
||||
|
||||
printf("nFileVersion = %d\n", nFileVersion);
|
||||
|
||||
|
||||
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
|
||||
if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000))
|
||||
return DB_NEED_REWRITE;
|
||||
|
||||
if (nFileVersion < CLIENT_VERSION) // Update
|
||||
{
|
||||
// Get rid of old debug.log file in current directory
|
||||
if (nFileVersion <= 105 && !pszSetDataDir[0])
|
||||
unlink("debug.log");
|
||||
|
||||
WriteVersion(CLIENT_VERSION);
|
||||
}
|
||||
|
||||
return DB_LOAD_OK;
|
||||
}
|
||||
|
||||
void ThreadFlushWalletDB(void* parg)
|
||||
{
|
||||
const string& strFile = ((const string*)parg)[0];
|
||||
static bool fOneThread;
|
||||
if (fOneThread)
|
||||
return;
|
||||
fOneThread = true;
|
||||
if (!GetBoolArg("-flushwallet", true))
|
||||
return;
|
||||
|
||||
unsigned int nLastSeen = nWalletDBUpdated;
|
||||
unsigned int nLastFlushed = nWalletDBUpdated;
|
||||
int64 nLastWalletUpdate = GetTime();
|
||||
while (!fShutdown)
|
||||
{
|
||||
Sleep(500);
|
||||
|
||||
if (nLastSeen != nWalletDBUpdated)
|
||||
{
|
||||
nLastSeen = nWalletDBUpdated;
|
||||
nLastWalletUpdate = GetTime();
|
||||
}
|
||||
|
||||
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
// Don't do this if any databases are in use
|
||||
int nRefCount = 0;
|
||||
map<string, int>::iterator mi = mapFileUseCount.begin();
|
||||
while (mi != mapFileUseCount.end())
|
||||
{
|
||||
nRefCount += (*mi).second;
|
||||
mi++;
|
||||
}
|
||||
|
||||
if (nRefCount == 0 && !fShutdown)
|
||||
{
|
||||
map<string, int>::iterator mi = mapFileUseCount.find(strFile);
|
||||
if (mi != mapFileUseCount.end())
|
||||
{
|
||||
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
|
||||
printf("Flushing wallet.dat\n");
|
||||
nLastFlushed = nWalletDBUpdated;
|
||||
int64 nStart = GetTimeMillis();
|
||||
|
||||
// Flush wallet.dat so it's self contained
|
||||
CloseDb(strFile);
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
|
||||
mapFileUseCount.erase(mi++);
|
||||
printf("Flushed wallet.dat %"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||
{
|
||||
if (!wallet.fFileBacked)
|
||||
return false;
|
||||
while (!fShutdown)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
if (!mapFileUseCount.count(wallet.strWalletFile) || mapFileUseCount[wallet.strWalletFile] == 0)
|
||||
{
|
||||
// Flush log data to the dat file
|
||||
CloseDb(wallet.strWalletFile);
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
dbenv.lsn_reset(wallet.strWalletFile.c_str(), 0);
|
||||
mapFileUseCount.erase(wallet.strWalletFile);
|
||||
|
||||
// Copy wallet.dat
|
||||
filesystem::path pathSrc(GetDataDir() + "/" + wallet.strWalletFile);
|
||||
filesystem::path pathDest(strDest);
|
||||
if (filesystem::is_directory(pathDest))
|
||||
pathDest = pathDest / wallet.strWalletFile;
|
||||
|
||||
try {
|
||||
#if BOOST_VERSION >= 104000
|
||||
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
|
||||
#else
|
||||
filesystem::copy_file(pathSrc, pathDest);
|
||||
#endif
|
||||
printf("copied wallet.dat to %s\n", pathDest.string().c_str());
|
||||
return true;
|
||||
} catch(const filesystem::filesystem_error &e) {
|
||||
printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
224
src/db.h
224
src/db.h
@@ -1,11 +1,11 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_DB_H
|
||||
#define BITCOIN_DB_H
|
||||
|
||||
#include "key.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
#include <db_cxx.h>
|
||||
|
||||
class CAccount;
|
||||
class CAccountingEntry;
|
||||
class CAddress;
|
||||
class CAddrMan;
|
||||
class CBlockLocator;
|
||||
@@ -27,6 +25,7 @@ class CWallet;
|
||||
class CWalletTx;
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
extern bool fDetachDB;
|
||||
extern DbEnv dbenv;
|
||||
|
||||
extern void DBFlush(bool fShutdown);
|
||||
@@ -59,7 +58,7 @@ protected:
|
||||
return false;
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK);
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
@@ -73,8 +72,13 @@ protected:
|
||||
return false;
|
||||
|
||||
// Unserialize value
|
||||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
|
||||
ssValue >> value;
|
||||
try {
|
||||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
|
||||
ssValue >> value;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear and free memory
|
||||
memset(datValue.get_data(), 0, datValue.get_size());
|
||||
@@ -91,13 +95,13 @@ protected:
|
||||
assert(!"Write called on database in read-only mode");
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK);
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Value
|
||||
CDataStream ssValue(SER_DISK);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
ssValue.reserve(10000);
|
||||
ssValue << value;
|
||||
Dbt datValue(&ssValue[0], ssValue.size());
|
||||
@@ -120,7 +124,7 @@ protected:
|
||||
assert(!"Erase called on database in read-only mode");
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK);
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
@@ -140,7 +144,7 @@ protected:
|
||||
return false;
|
||||
|
||||
// Key
|
||||
CDataStream ssKey(SER_DISK);
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
ssKey.reserve(1000);
|
||||
ssKey << key;
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
@@ -217,7 +221,7 @@ public:
|
||||
if (!pdb)
|
||||
return false;
|
||||
DbTxn* ptxn = NULL;
|
||||
int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
|
||||
int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_WRITE_NOSYNC);
|
||||
if (!ptxn || ret != 0)
|
||||
return false;
|
||||
vTxn.push_back(ptxn);
|
||||
@@ -313,198 +317,4 @@ public:
|
||||
bool LoadAddresses();
|
||||
|
||||
|
||||
/** A key pool entry */
|
||||
class CKeyPool
|
||||
{
|
||||
public:
|
||||
int64 nTime;
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
|
||||
CKeyPool()
|
||||
{
|
||||
nTime = GetTime();
|
||||
}
|
||||
|
||||
CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
|
||||
{
|
||||
nTime = GetTime();
|
||||
vchPubKey = vchPubKeyIn;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
if (!(nType & SER_GETHASH))
|
||||
READWRITE(nVersion);
|
||||
READWRITE(nTime);
|
||||
READWRITE(vchPubKey);
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Error statuses for the wallet database */
|
||||
enum DBErrors
|
||||
{
|
||||
DB_LOAD_OK,
|
||||
DB_CORRUPT,
|
||||
DB_TOO_NEW,
|
||||
DB_LOAD_FAIL,
|
||||
DB_NEED_REWRITE
|
||||
};
|
||||
|
||||
/** Access to the wallet database (wallet.dat) */
|
||||
class CWalletDB : public CDB
|
||||
{
|
||||
public:
|
||||
CWalletDB(std::string strFilename, const char* pszMode="r+") : CDB(strFilename.c_str(), pszMode)
|
||||
{
|
||||
}
|
||||
private:
|
||||
CWalletDB(const CWalletDB&);
|
||||
void operator=(const CWalletDB&);
|
||||
public:
|
||||
bool ReadName(const std::string& strAddress, std::string& strName)
|
||||
{
|
||||
strName = "";
|
||||
return Read(std::make_pair(std::string("name"), strAddress), strName);
|
||||
}
|
||||
|
||||
bool WriteName(const std::string& strAddress, const std::string& strName);
|
||||
|
||||
bool EraseName(const std::string& strAddress);
|
||||
|
||||
bool ReadTx(uint256 hash, CWalletTx& wtx)
|
||||
{
|
||||
return Read(std::make_pair(std::string("tx"), hash), wtx);
|
||||
}
|
||||
|
||||
bool WriteTx(uint256 hash, const CWalletTx& wtx)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("tx"), hash), wtx);
|
||||
}
|
||||
|
||||
bool EraseTx(uint256 hash)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("tx"), hash));
|
||||
}
|
||||
|
||||
bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
|
||||
{
|
||||
vchPrivKey.clear();
|
||||
return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey);
|
||||
}
|
||||
|
||||
bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
|
||||
}
|
||||
|
||||
bool WriteCryptedKey(const std::vector<unsigned char>& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, bool fEraseUnencryptedKey = true)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))
|
||||
return false;
|
||||
if (fEraseUnencryptedKey)
|
||||
{
|
||||
Erase(std::make_pair(std::string("key"), vchPubKey));
|
||||
Erase(std::make_pair(std::string("wkey"), vchPubKey));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||
}
|
||||
|
||||
// Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
|
||||
bool ReadCScript(const uint160 &hash, CScript& redeemScript)
|
||||
{
|
||||
redeemScript.clear();
|
||||
return Read(std::make_pair(std::string("cscript"), hash), redeemScript);
|
||||
}
|
||||
|
||||
bool WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false);
|
||||
}
|
||||
|
||||
bool WriteBestBlock(const CBlockLocator& locator)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::string("bestblock"), locator);
|
||||
}
|
||||
|
||||
bool ReadBestBlock(CBlockLocator& locator)
|
||||
{
|
||||
return Read(std::string("bestblock"), locator);
|
||||
}
|
||||
|
||||
bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
vchPubKey.clear();
|
||||
return Read(std::string("defaultkey"), vchPubKey);
|
||||
}
|
||||
|
||||
bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::string("defaultkey"), vchPubKey);
|
||||
}
|
||||
|
||||
bool ReadPool(int64 nPool, CKeyPool& keypool)
|
||||
{
|
||||
return Read(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool WritePool(int64 nPool, const CKeyPool& keypool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("pool"), nPool), keypool);
|
||||
}
|
||||
|
||||
bool ErasePool(int64 nPool)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("pool"), nPool));
|
||||
}
|
||||
|
||||
// Settings are no longer stored in wallet.dat; these are
|
||||
// used only for backwards compatibility:
|
||||
template<typename T>
|
||||
bool ReadSetting(const std::string& strKey, T& value)
|
||||
{
|
||||
return Read(std::make_pair(std::string("setting"), strKey), value);
|
||||
}
|
||||
template<typename T>
|
||||
bool WriteSetting(const std::string& strKey, const T& value)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("setting"), strKey), value);
|
||||
}
|
||||
bool EraseSetting(const std::string& strKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("setting"), strKey));
|
||||
}
|
||||
|
||||
bool WriteMinVersion(int nVersion)
|
||||
{
|
||||
return Write(std::string("minversion"), nVersion);
|
||||
}
|
||||
|
||||
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
||||
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
||||
bool WriteAccountingEntry(const CAccountingEntry& acentry);
|
||||
int64 GetAccountCreditDebit(const std::string& strAccount);
|
||||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries);
|
||||
|
||||
int LoadWallet(CWallet* pwallet);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // BITCOIN_DB_H
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4786)
|
||||
#pragma warning(disable:4804)
|
||||
#pragma warning(disable:4805)
|
||||
#pragma warning(disable:4717)
|
||||
#endif
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#ifdef _WIN32_IE
|
||||
#undef _WIN32_IE
|
||||
#endif
|
||||
#define _WIN32_IE 0x0400
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
|
||||
// Include boost/foreach here as it defines __STDC_LIMIT_MACROS on some systems.
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#if (defined(__unix__) || defined(unix)) && !defined(USG)
|
||||
#include <sys/param.h> // to get BSD define
|
||||
#endif
|
||||
#ifdef MAC_OSX
|
||||
#ifndef BSD
|
||||
#define BSD 1
|
||||
#endif
|
||||
#endif
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/ripemd.h>
|
||||
#include <db_cxx.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef BSD
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
#include "bignum.h"
|
||||
#include "base58.h"
|
||||
#include "main.h"
|
||||
#ifdef QT_GUI
|
||||
#include "qtui.h"
|
||||
#else
|
||||
#include "noui.h"
|
||||
#endif
|
||||
240
src/init.cpp
240
src/init.cpp
@@ -1,27 +1,21 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "headers.h"
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "db.h"
|
||||
#include "walletdb.h"
|
||||
#include "bitcoinrpc.h"
|
||||
#include "net.h"
|
||||
#include "init.h"
|
||||
#include "strlcpy.h"
|
||||
#include "util.h"
|
||||
#include "ui_interface.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
|
||||
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
|
||||
#define _BITCOIN_QT_PLUGINS_INCLUDED
|
||||
#define __INSURE__
|
||||
#include <QtPlugin>
|
||||
Q_IMPORT_PLUGIN(qcncodecs)
|
||||
Q_IMPORT_PLUGIN(qjpcodecs)
|
||||
Q_IMPORT_PLUGIN(qtwcodecs)
|
||||
Q_IMPORT_PLUGIN(qkrcodecs)
|
||||
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
||||
#ifndef WIN32
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
@@ -42,15 +36,29 @@ void ExitTimeout(void* parg)
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartShutdown()
|
||||
{
|
||||
#ifdef QT_GUI
|
||||
// ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards)
|
||||
QueueShutdown();
|
||||
#else
|
||||
// Without UI, Shutdown() can simply be started in a new thread
|
||||
CreateThread(Shutdown, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Shutdown(void* parg)
|
||||
{
|
||||
static CCriticalSection cs_Shutdown;
|
||||
static bool fTaken;
|
||||
bool fFirstThread = false;
|
||||
TRY_CRITICAL_BLOCK(cs_Shutdown)
|
||||
{
|
||||
fFirstThread = !fTaken;
|
||||
fTaken = true;
|
||||
TRY_LOCK(cs_Shutdown, lockShutdown);
|
||||
if (lockShutdown)
|
||||
{
|
||||
fFirstThread = !fTaken;
|
||||
fTaken = true;
|
||||
}
|
||||
}
|
||||
static bool fExit;
|
||||
if (fFirstThread)
|
||||
@@ -67,7 +75,10 @@ void Shutdown(void* parg)
|
||||
Sleep(50);
|
||||
printf("Bitcoin exiting\n\n");
|
||||
fExit = true;
|
||||
#ifndef QT_GUI
|
||||
// ensure non UI client get's exited here, but let Bitcoin-Qt reach return 0; in bitcoin.cpp
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,11 +164,12 @@ bool AppInit2(int argc, char* argv[])
|
||||
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
|
||||
#if !defined(QT_GUI)
|
||||
ParseParameters(argc, argv);
|
||||
if (!ReadConfigFile(mapArgs, mapMultiArgs))
|
||||
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
||||
{
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
Shutdown(NULL);
|
||||
}
|
||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||
#endif
|
||||
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
@@ -178,6 +190,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
" -splash \t\t " + _("Show splash screen on startup (default: 1)") + "\n" +
|
||||
" -datadir=<dir> \t\t " + _("Specify data directory") + "\n" +
|
||||
" -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" +
|
||||
" -dblogsize=<n> \t\t " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
|
||||
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
|
||||
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
|
||||
" -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" +
|
||||
@@ -201,6 +214,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
#else
|
||||
" -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" +
|
||||
#endif
|
||||
" -detachdb \t " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +
|
||||
#endif
|
||||
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send") + "\n" +
|
||||
#ifdef QT_GUI
|
||||
@@ -228,14 +242,12 @@ bool AppInit2(int argc, char* argv[])
|
||||
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
|
||||
" -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n";
|
||||
|
||||
#ifdef USE_SSL
|
||||
strUsage += string() +
|
||||
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
|
||||
" -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
|
||||
" -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)") + "\n" +
|
||||
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)") + "\n" +
|
||||
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
|
||||
#endif
|
||||
|
||||
strUsage += string() +
|
||||
" -? \t\t " + _("This help message") + "\n";
|
||||
@@ -244,7 +256,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
|
||||
#if defined(QT_GUI) && defined(WIN32)
|
||||
// On windows, show a message box, as there is no stderr
|
||||
wxMessageBox(strUsage, "Usage");
|
||||
ThreadSafeMessageBox(strUsage, _("Usage"), wxOK | wxMODAL);
|
||||
#else
|
||||
fprintf(stderr, "%s", strUsage.c_str());
|
||||
#endif
|
||||
@@ -258,6 +270,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
|
||||
fDebug = GetBoolArg("-debug");
|
||||
fDetachDB = GetBoolArg("-detachdb", false);
|
||||
|
||||
#if !defined(WIN32) && !defined(QT_GUI)
|
||||
fDaemon = GetBoolArg("-daemon");
|
||||
@@ -312,11 +325,11 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fDebug && !pszSetDataDir[0])
|
||||
if (!fDebug)
|
||||
ShrinkDebugFile();
|
||||
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||
printf("Bitcoin version %s\n", FormatFullVersion().c_str());
|
||||
printf("Default data directory %s\n", GetDefaultDataDir().c_str());
|
||||
printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str());
|
||||
printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
|
||||
|
||||
if (GetBoolArg("-loadblockindextest"))
|
||||
{
|
||||
@@ -327,13 +340,13 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Make sure only a single bitcoin process is using the data directory.
|
||||
string strLockFile = GetDataDir() + "/.lock";
|
||||
FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
|
||||
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
|
||||
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
|
||||
if (file) fclose(file);
|
||||
static boost::interprocess::file_lock lock(strLockFile.c_str());
|
||||
static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
|
||||
if (!lock.try_lock())
|
||||
{
|
||||
wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
|
||||
ThreadSafeMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str()), _("Bitcoin"), wxOK|wxMODAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -357,6 +370,15 @@ bool AppInit2(int argc, char* argv[])
|
||||
nStart = GetTimeMillis();
|
||||
if (!LoadBlockIndex())
|
||||
strErrors << _("Error loading blkindex.dat") << "\n";
|
||||
|
||||
// as LoadBlockIndex can take several minutes, it's possible the user
|
||||
// requested to kill bitcoin-qt during the last operation. If so, exit.
|
||||
// As the program has not fully started yet, Shutdown() is possibly overkill.
|
||||
if (fRequestShutdown)
|
||||
{
|
||||
printf("Shutdown requested. Exiting.\n");
|
||||
return false;
|
||||
}
|
||||
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
|
||||
InitMessage(_("Loading wallet..."));
|
||||
@@ -375,7 +397,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
{
|
||||
strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n";
|
||||
printf("%s", strErrors.str().c_str());
|
||||
wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -447,7 +469,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
|
||||
if (!strErrors.str().empty())
|
||||
{
|
||||
wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -503,7 +525,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
addrProxy = CService(mapArgs["-proxy"], 9050);
|
||||
if (!addrProxy.IsValid())
|
||||
{
|
||||
wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
|
||||
ThreadSafeMessageBox(_("Invalid -proxy address"), _("Bitcoin"), wxOK | wxMODAL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -534,7 +556,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
std::string strError;
|
||||
if (!BindListenPort(strError))
|
||||
{
|
||||
wxMessageBox(strError, "Bitcoin");
|
||||
ThreadSafeMessageBox(strError, _("Bitcoin"), wxOK | wxMODAL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -554,11 +576,11 @@ bool AppInit2(int argc, char* argv[])
|
||||
{
|
||||
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
|
||||
{
|
||||
wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
|
||||
ThreadSafeMessageBox(_("Invalid amount for -paytxfee=<amount>"), _("Bitcoin"), wxOK | wxMODAL);
|
||||
return false;
|
||||
}
|
||||
if (nTransactionFee > 0.25 * COIN)
|
||||
wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
||||
ThreadSafeMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -570,14 +592,14 @@ bool AppInit2(int argc, char* argv[])
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
if (!CreateThread(StartNode, NULL))
|
||||
wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
|
||||
ThreadSafeMessageBox(_("Error: CreateThread(StartNode) failed"), _("Bitcoin"), wxOK | wxMODAL);
|
||||
|
||||
if (fServer)
|
||||
CreateThread(ThreadRPCServer, NULL);
|
||||
|
||||
#ifdef QT_GUI
|
||||
if(GetStartOnSystemStartup())
|
||||
SetStartOnSystemStartup(true); // Remove startup links to bitcoin-wx
|
||||
if (GetStartOnSystemStartup())
|
||||
SetStartOnSystemStartup(true); // Remove startup links
|
||||
#endif
|
||||
|
||||
#if !defined(QT_GUI)
|
||||
@@ -588,151 +610,3 @@ bool AppInit2(int argc, char* argv[])
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
string StartupShortcutPath()
|
||||
{
|
||||
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
|
||||
}
|
||||
|
||||
bool GetStartOnSystemStartup()
|
||||
{
|
||||
return filesystem::exists(StartupShortcutPath().c_str());
|
||||
}
|
||||
|
||||
bool SetStartOnSystemStartup(bool fAutoStart)
|
||||
{
|
||||
// If the shortcut exists already, remove it for updating
|
||||
remove(StartupShortcutPath().c_str());
|
||||
|
||||
if (fAutoStart)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
||||
// Get a pointer to the IShellLink interface.
|
||||
IShellLink* psl = NULL;
|
||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IShellLink,
|
||||
reinterpret_cast<void**>(&psl));
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
// Get the current executable path
|
||||
TCHAR pszExePath[MAX_PATH];
|
||||
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
|
||||
|
||||
TCHAR pszArgs[5] = TEXT("-min");
|
||||
|
||||
// Set the path to the shortcut target
|
||||
psl->SetPath(pszExePath);
|
||||
PathRemoveFileSpec(pszExePath);
|
||||
psl->SetWorkingDirectory(pszExePath);
|
||||
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
|
||||
psl->SetArguments(pszArgs);
|
||||
|
||||
// Query IShellLink for the IPersistFile interface for
|
||||
// saving the shortcut in persistent storage.
|
||||
IPersistFile* ppf = NULL;
|
||||
hres = psl->QueryInterface(IID_IPersistFile,
|
||||
reinterpret_cast<void**>(&ppf));
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
WCHAR pwsz[MAX_PATH];
|
||||
// Ensure that the string is ANSI.
|
||||
MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
|
||||
// Save the link by calling IPersistFile::Save.
|
||||
hres = ppf->Save(pwsz, TRUE);
|
||||
ppf->Release();
|
||||
psl->Release();
|
||||
CoUninitialize();
|
||||
return true;
|
||||
}
|
||||
psl->Release();
|
||||
}
|
||||
CoUninitialize();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
// Follow the Desktop Application Autostart Spec:
|
||||
// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
|
||||
|
||||
boost::filesystem::path GetAutostartDir()
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
char* pszConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
if (pszConfigHome) return fs::path(pszConfigHome) / fs::path("autostart");
|
||||
char* pszHome = getenv("HOME");
|
||||
if (pszHome) return fs::path(pszHome) / fs::path(".config/autostart");
|
||||
return fs::path();
|
||||
}
|
||||
|
||||
boost::filesystem::path GetAutostartFilePath()
|
||||
{
|
||||
return GetAutostartDir() / boost::filesystem::path("bitcoin.desktop");
|
||||
}
|
||||
|
||||
bool GetStartOnSystemStartup()
|
||||
{
|
||||
boost::filesystem::ifstream optionFile(GetAutostartFilePath());
|
||||
if (!optionFile.good())
|
||||
return false;
|
||||
// Scan through file for "Hidden=true":
|
||||
string line;
|
||||
while (!optionFile.eof())
|
||||
{
|
||||
getline(optionFile, line);
|
||||
if (line.find("Hidden") != string::npos &&
|
||||
line.find("true") != string::npos)
|
||||
return false;
|
||||
}
|
||||
optionFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetStartOnSystemStartup(bool fAutoStart)
|
||||
{
|
||||
if (!fAutoStart)
|
||||
{
|
||||
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
|
||||
unlink(GetAutostartFilePath().string().c_str());
|
||||
#else
|
||||
unlink(GetAutostartFilePath().native_file_string().c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
char pszExePath[MAX_PATH+1];
|
||||
memset(pszExePath, 0, sizeof(pszExePath));
|
||||
if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
|
||||
return false;
|
||||
|
||||
boost::filesystem::create_directories(GetAutostartDir());
|
||||
|
||||
boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
|
||||
if (!optionFile.good())
|
||||
return false;
|
||||
// Write a bitcoin.desktop file to the autostart directory:
|
||||
optionFile << "[Desktop Entry]\n";
|
||||
optionFile << "Type=Application\n";
|
||||
optionFile << "Name=Bitcoin\n";
|
||||
optionFile << "Exec=" << pszExePath << " -min\n";
|
||||
optionFile << "Terminal=false\n";
|
||||
optionFile << "Hidden=false\n";
|
||||
optionFile.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
// TODO: OSX startup stuff; see:
|
||||
// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
|
||||
|
||||
bool GetStartOnSystemStartup() { return false; }
|
||||
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_INIT_H
|
||||
#define BITCOIN_INIT_H
|
||||
|
||||
#include "wallet.h"
|
||||
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
void StartShutdown();
|
||||
void Shutdown(void* parg);
|
||||
bool AppInit(int argc, char* argv[]);
|
||||
bool AppInit2(int argc, char* argv[]);
|
||||
|
||||
bool GetStartOnSystemStartup();
|
||||
bool SetStartOnSystemStartup(bool fAutoStart);
|
||||
|
||||
#endif
|
||||
|
||||
12
src/irc.cpp
12
src/irc.cpp
@@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "irc.h"
|
||||
#include "net.h"
|
||||
#include "strlcpy.h"
|
||||
#include "base58.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
@@ -108,13 +108,13 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha
|
||||
if (!RecvLineIRC(hSocket, strLine))
|
||||
return 0;
|
||||
printf("IRC %s\n", strLine.c_str());
|
||||
if (psz1 && strLine.find(psz1) != -1)
|
||||
if (psz1 && strLine.find(psz1) != string::npos)
|
||||
return 1;
|
||||
if (psz2 && strLine.find(psz2) != -1)
|
||||
if (psz2 && strLine.find(psz2) != string::npos)
|
||||
return 2;
|
||||
if (psz3 && strLine.find(psz3) != -1)
|
||||
if (psz3 && strLine.find(psz3) != string::npos)
|
||||
return 3;
|
||||
if (psz4 && strLine.find(psz4) != -1)
|
||||
if (psz4 && strLine.find(psz4) != string::npos)
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_IRC_H
|
||||
#define BITCOIN_IRC_H
|
||||
|
||||
|
||||
270
src/key.cpp
270
src/key.cpp
@@ -1,9 +1,14 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "key.h"
|
||||
#include "util.h"
|
||||
|
||||
// Generate a private key from just the secret parameter
|
||||
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
@@ -115,3 +120,264 @@ err:
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CKey::SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
|
||||
void CKey::Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
}
|
||||
|
||||
CKey::CKey()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
CKey::CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
|
||||
CKey& CKey::operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
CKey::~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
|
||||
bool CKey::IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
|
||||
bool CKey::IsCompressed() const
|
||||
{
|
||||
return fCompressedPubKey;
|
||||
}
|
||||
|
||||
void CKey::MakeNewKey(bool fCompressed)
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
if (fCompressed)
|
||||
SetCompressedPubKey();
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||
if (vchSecret.size() != 32)
|
||||
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
}
|
||||
BN_clear_free(bn);
|
||||
fSet = true;
|
||||
if (fCompressed || fCompressedPubKey)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret CKey::GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
int nBytes = BN_num_bytes(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
CPrivKey CKey::GetPrivKey() const
|
||||
{
|
||||
int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CKey::GetPubKey() const
|
||||
{
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
unsigned int nSize = ECDSA_size(pkey);
|
||||
vchSig.resize(nSize); // Make sure it is big enough
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
|
||||
{
|
||||
vchSig.clear();
|
||||
return false;
|
||||
}
|
||||
vchSig.resize(nSize); // Shrink to fit actual size
|
||||
return true;
|
||||
}
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
|
||||
if (sig==NULL)
|
||||
return false;
|
||||
vchSig.clear();
|
||||
vchSig.resize(65,0);
|
||||
int nBitsR = BN_num_bits(sig->r);
|
||||
int nBitsS = BN_num_bits(sig->s);
|
||||
if (nBitsR <= 256 && nBitsS <= 256)
|
||||
{
|
||||
int nRecId = -1;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
CKey keyRec;
|
||||
keyRec.fSet = true;
|
||||
if (fCompressedPubKey)
|
||||
keyRec.SetCompressedPubKey();
|
||||
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
|
||||
if (keyRec.GetPubKey() == this->GetPubKey())
|
||||
{
|
||||
nRecId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
|
||||
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
|
||||
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
|
||||
fOk = true;
|
||||
}
|
||||
ECDSA_SIG_free(sig);
|
||||
return fOk;
|
||||
}
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
BN_bin2bn(&vchSig[33],32,sig->s);
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (nV >= 31)
|
||||
{
|
||||
SetCompressedPubKey();
|
||||
nV -= 4;
|
||||
}
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
|
||||
{
|
||||
fSet = true;
|
||||
ECDSA_SIG_free(sig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetCompactSignature(hash, vchSig))
|
||||
return false;
|
||||
if (GetPubKey() != key.GetPubKey())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::IsValid()
|
||||
{
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
|
||||
272
src/key.h
272
src/key.h
@@ -1,20 +1,18 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEY_H
|
||||
#define BITCOIN_KEY_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "serialize.h"
|
||||
#include "allocators.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_KEY definition
|
||||
|
||||
// secp160k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 192;
|
||||
// const unsigned int PUBLIC_KEY_SIZE = 41;
|
||||
@@ -38,9 +36,6 @@
|
||||
// see www.keylength.com
|
||||
// script supports up to 75 for single byte push
|
||||
|
||||
int extern EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key);
|
||||
int extern ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check);
|
||||
|
||||
class key_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
@@ -62,267 +57,50 @@ protected:
|
||||
bool fSet;
|
||||
bool fCompressedPubKey;
|
||||
|
||||
void SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
void SetCompressedPubKey();
|
||||
|
||||
public:
|
||||
|
||||
void Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
}
|
||||
void Reset();
|
||||
|
||||
CKey()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
CKey();
|
||||
CKey(const CKey& b);
|
||||
|
||||
CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
CKey& operator=(const CKey& b);
|
||||
|
||||
CKey& operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
~CKey();
|
||||
|
||||
~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
bool IsNull() const;
|
||||
bool IsCompressed() const;
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
void MakeNewKey(bool fCompressed);
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey);
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
|
||||
CSecret GetSecret(bool &fCompressed) const;
|
||||
CPrivKey GetPrivKey() const;
|
||||
bool SetPubKey(const std::vector<unsigned char>& vchPubKey);
|
||||
std::vector<unsigned char> GetPubKey() const;
|
||||
|
||||
bool IsCompressed() const
|
||||
{
|
||||
return fCompressedPubKey;
|
||||
}
|
||||
|
||||
void MakeNewKey(bool fCompressed)
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
if (fCompressed)
|
||||
SetCompressedPubKey();
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||
if (vchSecret.size() != 32)
|
||||
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
}
|
||||
BN_clear_free(bn);
|
||||
fSet = true;
|
||||
if (fCompressed || fCompressedPubKey)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
int nBytes = BN_num_bytes(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
CPrivKey GetPrivKey() const
|
||||
{
|
||||
unsigned int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GetPubKey() const
|
||||
{
|
||||
unsigned int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
unsigned int nSize = ECDSA_size(pkey);
|
||||
vchSig.resize(nSize); // Make sure it is big enough
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
|
||||
{
|
||||
vchSig.clear();
|
||||
return false;
|
||||
}
|
||||
vchSig.resize(nSize); // Shrink to fit actual size
|
||||
return true;
|
||||
}
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
|
||||
if (sig==NULL)
|
||||
return false;
|
||||
vchSig.clear();
|
||||
vchSig.resize(65,0);
|
||||
int nBitsR = BN_num_bits(sig->r);
|
||||
int nBitsS = BN_num_bits(sig->s);
|
||||
if (nBitsR <= 256 && nBitsS <= 256)
|
||||
{
|
||||
int nRecId = -1;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
CKey keyRec;
|
||||
keyRec.fSet = true;
|
||||
if (fCompressedPubKey)
|
||||
keyRec.SetCompressedPubKey();
|
||||
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
|
||||
if (keyRec.GetPubKey() == this->GetPubKey())
|
||||
{
|
||||
nRecId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
|
||||
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
|
||||
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
|
||||
fOk = true;
|
||||
}
|
||||
ECDSA_SIG_free(sig);
|
||||
return fOk;
|
||||
}
|
||||
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
BN_bin2bn(&vchSig[33],32,sig->s);
|
||||
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (nV >= 31)
|
||||
{
|
||||
SetCompressedPubKey();
|
||||
nV -= 4;
|
||||
}
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
|
||||
{
|
||||
fSet = true;
|
||||
ECDSA_SIG_free(sig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
// Verify a compact signature
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetCompactSignature(hash, vchSig))
|
||||
return false;
|
||||
if (GetPubKey() != key.GetPubKey())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
bool IsValid();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "crypter.h"
|
||||
#include "db.h"
|
||||
#include "keystore.h"
|
||||
#include "script.h"
|
||||
|
||||
bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
|
||||
@@ -21,31 +19,37 @@ bool CBasicKeyStore::AddKey(const CKey& key)
|
||||
{
|
||||
bool fCompressed = false;
|
||||
CSecret secret = key.GetSecret(fCompressed);
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
mapScripts[Hash160(redeemScript)] = redeemScript;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveCScript(const uint160& hash) const
|
||||
{
|
||||
bool result;
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = (mapScripts.count(hash) > 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
ScriptMap::const_iterator mi = mapScripts.find(hash);
|
||||
if (mi != mapScripts.end())
|
||||
{
|
||||
@@ -58,8 +62,8 @@ bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) c
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
@@ -71,8 +75,8 @@ bool CCryptoKeyStore::SetCrypted()
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
@@ -84,6 +88,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
CSecret vchSecret;
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
CKey key;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetSecret(vchSecret);
|
||||
@@ -98,8 +104,8 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
|
||||
bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::AddKey(key);
|
||||
|
||||
@@ -121,8 +127,8 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
@@ -133,8 +139,8 @@ bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey,
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::GetKey(address, keyOut);
|
||||
|
||||
@@ -146,6 +152,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
CSecret vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
keyOut.SetPubKey(vchPubKey);
|
||||
keyOut.SetSecret(vchSecret);
|
||||
return true;
|
||||
@@ -156,8 +164,8 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CKeyStore::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
@@ -173,8 +181,8 @@ bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsi
|
||||
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEYSTORE_H
|
||||
#define BITCOIN_KEYSTORE_H
|
||||
|
||||
#include "crypter.h"
|
||||
#include "script.h"
|
||||
#include "util.h"
|
||||
#include "base58.h"
|
||||
|
||||
class CScript;
|
||||
|
||||
/** A virtual base class for key stores */
|
||||
class CKeyStore
|
||||
@@ -15,6 +18,8 @@ protected:
|
||||
mutable CCriticalSection cs_KeyStore;
|
||||
|
||||
public:
|
||||
virtual ~CKeyStore() {}
|
||||
|
||||
// Add a key to the store.
|
||||
virtual bool AddKey(const CKey& key) =0;
|
||||
|
||||
@@ -54,15 +59,17 @@ public:
|
||||
bool HaveKey(const CBitcoinAddress &address) const
|
||||
{
|
||||
bool result;
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = (mapKeys.count(address) > 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void GetKeys(std::set<CBitcoinAddress> &setAddress) const
|
||||
{
|
||||
setAddress.clear();
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
KeyMap::const_iterator mi = mapKeys.begin();
|
||||
while (mi != mapKeys.end())
|
||||
{
|
||||
@@ -73,8 +80,8 @@ public:
|
||||
}
|
||||
bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
KeyMap::const_iterator mi = mapKeys.find(address);
|
||||
if (mi != mapKeys.end())
|
||||
{
|
||||
@@ -129,8 +136,10 @@ public:
|
||||
if (!IsCrypted())
|
||||
return false;
|
||||
bool result;
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
result = vMasterKey.empty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -139,8 +148,10 @@ public:
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -149,8 +160,8 @@ public:
|
||||
bool AddKey(const CKey& key);
|
||||
bool HaveKey(const CBitcoinAddress &address) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return CBasicKeyStore::HaveKey(address);
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
|
||||
536
src/main.cpp
536
src/main.cpp
File diff suppressed because it is too large
Load Diff
116
src/main.h
116
src/main.h
@@ -1,41 +1,35 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_MAIN_H
|
||||
#define BITCOIN_MAIN_H
|
||||
|
||||
#include "bignum.h"
|
||||
#include "net.h"
|
||||
#include "key.h"
|
||||
#include "script.h"
|
||||
#include "db.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h> /* for _commit */
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
|
||||
class CWallet;
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
class CWalletTx;
|
||||
class CWallet;
|
||||
class CKeyItem;
|
||||
class CReserveKey;
|
||||
class CWalletDB;
|
||||
|
||||
class CAddress;
|
||||
class CInv;
|
||||
class CRequestTracker;
|
||||
class CNode;
|
||||
|
||||
static const int CLIENT_VERSION = 60006;
|
||||
static const bool VERSION_IS_BETA = true;
|
||||
extern const std::string CLIENT_NAME;
|
||||
|
||||
static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
||||
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
||||
static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
||||
static const int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
||||
static const int64 COIN = 100000000;
|
||||
static const int64 CENT = 1000000;
|
||||
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
||||
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
||||
static const int64 MIN_TX_FEE = 50000;
|
||||
static const int64 MIN_RELAY_TX_FEE = 10000;
|
||||
static const int64 MAX_MONEY = 21000000 * COIN;
|
||||
@@ -66,7 +60,6 @@ extern CBigNum bnBestChainWork;
|
||||
extern CBigNum bnBestInvalidWork;
|
||||
extern uint256 hashBestChain;
|
||||
extern CBlockIndex* pindexBest;
|
||||
extern uint64 nPooledTx;
|
||||
extern unsigned int nTransactionsUpdated;
|
||||
extern uint64 nLastBlockTx;
|
||||
extern uint64 nLastBlockSize;
|
||||
@@ -161,7 +154,7 @@ public:
|
||||
std::string ToString() const
|
||||
{
|
||||
if (IsNull())
|
||||
return strprintf("null");
|
||||
return "null";
|
||||
else
|
||||
return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
|
||||
}
|
||||
@@ -288,7 +281,7 @@ public:
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string str;
|
||||
str += strprintf("CTxIn(");
|
||||
str += "CTxIn(";
|
||||
str += prevout.ToString();
|
||||
if (prevout.IsNull())
|
||||
str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
|
||||
@@ -444,7 +437,7 @@ public:
|
||||
nBlockHeight = nBestHeight;
|
||||
if (nBlockTime == 0)
|
||||
nBlockTime = GetAdjustedTime();
|
||||
if ((int64)nLockTime < (nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
|
||||
if ((int64)nLockTime < ((int64)nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
|
||||
return true;
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
if (!txin.IsFinal())
|
||||
@@ -456,13 +449,13 @@ public:
|
||||
{
|
||||
if (vin.size() != old.vin.size())
|
||||
return false;
|
||||
for (int i = 0; i < vin.size(); i++)
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
if (vin[i].prevout != old.vin[i].prevout)
|
||||
return false;
|
||||
|
||||
bool fNewer = false;
|
||||
unsigned int nLowest = std::numeric_limits<unsigned int>::max();
|
||||
for (int i = 0; i < vin.size(); i++)
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
{
|
||||
if (vin[i].nSequence != old.vin[i].nSequence)
|
||||
{
|
||||
@@ -502,7 +495,7 @@ public:
|
||||
@return number of sigops this transaction's outputs will produce when spent
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
int GetLegacySigOpCount() const;
|
||||
unsigned int GetLegacySigOpCount() const;
|
||||
|
||||
/** Count ECDSA signature operations in pay-to-script-hash inputs.
|
||||
|
||||
@@ -510,7 +503,7 @@ public:
|
||||
@return maximum number of sigops required to validate this transaction's inputs
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
int GetP2SHSigOpCount(const MapPrevTx& mapInputs) const;
|
||||
unsigned int GetP2SHSigOpCount(const MapPrevTx& mapInputs) const;
|
||||
|
||||
/** Amount of bitcoins spent by this transaction.
|
||||
@return sum of all outputs (note: does not include fees)
|
||||
@@ -549,7 +542,7 @@ public:
|
||||
// Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
|
||||
int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
|
||||
|
||||
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
|
||||
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
|
||||
unsigned int nNewBlockSize = nBlockSize + nBytes;
|
||||
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
|
||||
|
||||
@@ -572,9 +565,11 @@ public:
|
||||
|
||||
// To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
|
||||
if (nMinFee < nBaseFee)
|
||||
{
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
if (txout.nValue < CENT)
|
||||
nMinFee = nBaseFee;
|
||||
}
|
||||
|
||||
// Raise the price as the block approaches full
|
||||
if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
|
||||
@@ -592,14 +587,20 @@ public:
|
||||
|
||||
bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
|
||||
{
|
||||
CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
|
||||
CAutoFile filein = CAutoFile(OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION);
|
||||
if (!filein)
|
||||
return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
|
||||
|
||||
// Read transaction
|
||||
if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
|
||||
return error("CTransaction::ReadFromDisk() : fseek failed");
|
||||
filein >> *this;
|
||||
|
||||
try {
|
||||
filein >> *this;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Return file pointer
|
||||
if (pfileRet)
|
||||
@@ -634,9 +635,9 @@ public:
|
||||
vin.size(),
|
||||
vout.size(),
|
||||
nLockTime);
|
||||
for (int i = 0; i < vin.size(); i++)
|
||||
for (unsigned int i = 0; i < vin.size(); i++)
|
||||
str += " " + vin[i].ToString() + "\n";
|
||||
for (int i = 0; i < vout.size(); i++)
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
str += " " + vout[i].ToString() + "\n";
|
||||
return str;
|
||||
}
|
||||
@@ -683,13 +684,9 @@ public:
|
||||
bool ClientConnectInputs();
|
||||
bool CheckTransaction() const;
|
||||
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
|
||||
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
|
||||
|
||||
protected:
|
||||
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
|
||||
bool AddToMemoryPoolUnchecked();
|
||||
public:
|
||||
bool RemoveFromMemoryPool();
|
||||
};
|
||||
|
||||
|
||||
@@ -705,7 +702,7 @@ public:
|
||||
int nIndex;
|
||||
|
||||
// memory only
|
||||
mutable char fMerkleVerified;
|
||||
mutable bool fMerkleVerified;
|
||||
|
||||
|
||||
CMerkleTx()
|
||||
@@ -944,7 +941,7 @@ public:
|
||||
bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet)
|
||||
{
|
||||
// Open history file to append
|
||||
CAutoFile fileout = AppendBlockFile(nFileRet);
|
||||
CAutoFile fileout = CAutoFile(AppendBlockFile(nFileRet), SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return error("CBlock::WriteToDisk() : AppendBlockFile failed");
|
||||
|
||||
@@ -953,9 +950,10 @@ public:
|
||||
fileout << FLATDATA(pchMessageStart) << nSize;
|
||||
|
||||
// Write block
|
||||
nBlockPosRet = ftell(fileout);
|
||||
if (nBlockPosRet == -1)
|
||||
long fileOutPos = ftell(fileout);
|
||||
if (fileOutPos < 0)
|
||||
return error("CBlock::WriteToDisk() : ftell failed");
|
||||
nBlockPosRet = fileOutPos;
|
||||
fileout << *this;
|
||||
|
||||
// Flush stdio buffers and commit to disk before returning
|
||||
@@ -977,14 +975,19 @@ public:
|
||||
SetNull();
|
||||
|
||||
// Open history file to read
|
||||
CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
|
||||
CAutoFile filein = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb"), SER_DISK, CLIENT_VERSION);
|
||||
if (!filein)
|
||||
return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
|
||||
if (!fReadTransactions)
|
||||
filein.nType |= SER_BLOCKHEADERONLY;
|
||||
|
||||
// Read block
|
||||
filein >> *this;
|
||||
try {
|
||||
filein >> *this;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Check the header
|
||||
if (!CheckProofOfWork(GetHash(), nBits))
|
||||
@@ -1004,13 +1007,13 @@ public:
|
||||
hashMerkleRoot.ToString().substr(0,10).c_str(),
|
||||
nTime, nBits, nNonce,
|
||||
vtx.size());
|
||||
for (int i = 0; i < vtx.size(); i++)
|
||||
for (unsigned int i = 0; i < vtx.size(); i++)
|
||||
{
|
||||
printf(" ");
|
||||
vtx[i].print();
|
||||
}
|
||||
printf(" vMerkleTree: ");
|
||||
for (int i = 0; i < vMerkleTree.size(); i++)
|
||||
for (unsigned int i = 0; i < vMerkleTree.size(); i++)
|
||||
printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1138,7 +1141,7 @@ public:
|
||||
bool EraseBlockFromDisk()
|
||||
{
|
||||
// Open history file
|
||||
CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
|
||||
CAutoFile fileout = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb+"), SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return false;
|
||||
|
||||
@@ -1598,7 +1601,7 @@ public:
|
||||
return error("CAlert::CheckSignature() : verify signature failed");
|
||||
|
||||
// Now unserialize the data
|
||||
CDataStream sMsg(vchMsg);
|
||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||
sMsg >> *(CUnsignedAlert*)this;
|
||||
return true;
|
||||
}
|
||||
@@ -1606,4 +1609,35 @@ public:
|
||||
bool ProcessAlert();
|
||||
};
|
||||
|
||||
class CTxMemPool
|
||||
{
|
||||
public:
|
||||
mutable CCriticalSection cs;
|
||||
std::map<uint256, CTransaction> mapTx;
|
||||
std::map<COutPoint, CInPoint> mapNextTx;
|
||||
|
||||
bool accept(CTxDB& txdb, CTransaction &tx,
|
||||
bool fCheckInputs, bool* pfMissingInputs);
|
||||
bool addUnchecked(CTransaction &tx);
|
||||
bool remove(CTransaction &tx);
|
||||
|
||||
unsigned long size()
|
||||
{
|
||||
LOCK(cs);
|
||||
return mapTx.size();
|
||||
}
|
||||
|
||||
bool exists(uint256 hash)
|
||||
{
|
||||
return (mapTx.count(hash) != 0);
|
||||
}
|
||||
|
||||
CTransaction& lookup(uint256 hash)
|
||||
{
|
||||
return mapTx[hash];
|
||||
}
|
||||
};
|
||||
|
||||
extern CTxMemPool mempool;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,13 +9,14 @@ USE_UPNP:=0
|
||||
INCLUDEPATHS= \
|
||||
-I"$(DEPSDIR)/boost_1_47_0" \
|
||||
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-I"$(DEPSDIR)/openssl-1.0.0e/include" \
|
||||
-I"$(DEPSDIR)"
|
||||
-I"$(DEPSDIR)/openssl-1.0.1b/include" \
|
||||
-I"$(DEPSDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
|
||||
LIBPATHS= \
|
||||
-L"$(DEPSDIR)/boost_1_47_0/stage/lib" \
|
||||
-L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-L"$(DEPSDIR)/openssl-1.0.0e"
|
||||
-L"$(DEPSDIR)/openssl-1.0.1b"
|
||||
|
||||
LIBS= \
|
||||
-l boost_system-mt-s \
|
||||
@@ -26,10 +27,11 @@ LIBS= \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
|
||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
|
||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
|
||||
DEBUGFLAGS=-g
|
||||
CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifdef USE_UPNP
|
||||
LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
|
||||
@@ -43,6 +45,7 @@ LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l w
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
@@ -59,28 +62,37 @@ OBJS= \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o
|
||||
|
||||
all: bitcoind.exe
|
||||
|
||||
obj/build.h: FORCE
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj/test/%.o: obj/test/%.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
|
||||
obj-test/%.o: test/%.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $<
|
||||
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework-mt-s
|
||||
test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f obj/*.o
|
||||
-rm -f obj/test/*.o
|
||||
-rm -f test/*.o
|
||||
-rm -f headers.h.gch
|
||||
-rm -f bitcoind.exe
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f test_bitcoin.exe
|
||||
-rm -f src/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -7,12 +7,12 @@ USE_UPNP:=0
|
||||
INCLUDEPATHS= \
|
||||
-I"C:\boost-1.47.0-mgw" \
|
||||
-I"C:\db-4.8.30.NC-mgw\build_unix" \
|
||||
-I"C:\openssl-1.0.0d-mgw\include"
|
||||
-I"C:\openssl-1.0.1b-mgw\include"
|
||||
|
||||
LIBPATHS= \
|
||||
-L"C:\boost-1.47.0-mgw\stage\lib" \
|
||||
-L"C:\db-4.8.30.NC-mgw\build_unix" \
|
||||
-L"C:\openssl-1.0.0d-mgw"
|
||||
-L"C:\openssl-1.0.1b-mgw"
|
||||
|
||||
LIBS= \
|
||||
-l boost_system-mgw45-mt-s-1_47 \
|
||||
@@ -23,10 +23,11 @@ LIBS= \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
|
||||
DEFS=-DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
|
||||
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
|
||||
DEBUGFLAGS=-g
|
||||
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifdef USE_UPNP
|
||||
INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw"
|
||||
@@ -41,6 +42,7 @@ LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
@@ -57,7 +59,9 @@ OBJS= \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o
|
||||
|
||||
|
||||
all: bitcoind.exe
|
||||
@@ -68,16 +72,16 @@ obj/%.o: %.cpp $(HEADERS)
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
obj/test/test_bitcoin.o: $(wildcard test/*.cpp) $(HEADERS)
|
||||
g++ -c $(CFLAGS) -o $@ test/test_bitcoin.cpp
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
obj-test/%.o: test/%.cpp $(HEADERS)
|
||||
g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $<
|
||||
|
||||
test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
|
||||
|
||||
clean:
|
||||
-del /Q bitcoind test_bitcoin
|
||||
-del /Q obj\*
|
||||
-del /Q obj\nogui\*
|
||||
-del /Q obj\test\*
|
||||
-del /Q test\*.o
|
||||
-del /Q headers.h.gch
|
||||
-del /Q obj-test\*
|
||||
-del /Q build.h
|
||||
|
||||
@@ -11,6 +11,7 @@ DEPSDIR=/opt/local
|
||||
|
||||
INCLUDEPATHS= \
|
||||
-I"$(CURDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
-I"$(DEPSDIR)/include" \
|
||||
-I"$(DEPSDIR)/include/db48"
|
||||
|
||||
@@ -21,6 +22,9 @@ LIBPATHS= \
|
||||
USE_UPNP:=1
|
||||
|
||||
LIBS= -dead_strip
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifdef STATIC
|
||||
# Build STATIC if you are redistributing the bitcoind binary
|
||||
TESTLIBS += \
|
||||
@@ -49,15 +53,23 @@ LIBS += \
|
||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||
endif
|
||||
|
||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DUSE_SSL
|
||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE
|
||||
|
||||
ifdef RELEASE
|
||||
# Compile for maximum compatibility and smallest size.
|
||||
# This requires that dependencies are compiled
|
||||
# the same way.
|
||||
CFLAGS = -mmacosx-version-min=10.5 -arch i386 -O3
|
||||
else
|
||||
CFLAGS = -g
|
||||
endif
|
||||
|
||||
DEBUGFLAGS=-g
|
||||
# ppc doesn't work because we don't support big-endian
|
||||
CFLAGS=-mmacosx-version-min=10.5 -arch i386 -O3 \
|
||||
-Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat-security \
|
||||
CFLAGS += -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wformat-security \
|
||||
$(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
|
||||
OBJS= \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
@@ -74,7 +86,9 @@ OBJS= \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o
|
||||
|
||||
ifdef USE_UPNP
|
||||
DEFS += -DUSE_UPNP=$(USE_UPNP)
|
||||
@@ -91,6 +105,11 @@ all: bitcoind
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/build.h: FORCE
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
@@ -119,3 +138,6 @@ clean:
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj-test/*.P
|
||||
-rm -f src/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
USE_UPNP:=0
|
||||
|
||||
DEFS=-DNOPCH
|
||||
DEFS=-DBOOST_SPIRIT_THREADSAFE
|
||||
|
||||
DEFS += $(addprefix -I,$(CURDIR) $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||
DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
LMODE = dynamic
|
||||
LMODE2 = dynamic
|
||||
ifdef STATIC
|
||||
@@ -39,10 +41,6 @@ ifneq (${USE_UPNP}, -)
|
||||
DEFS += -DUSE_UPNP=$(USE_UPNP)
|
||||
endif
|
||||
|
||||
ifneq (${USE_SSL}, 0)
|
||||
DEFS += -DUSE_SSL
|
||||
endif
|
||||
|
||||
LIBS+= \
|
||||
-Wl,-B$(LMODE2) \
|
||||
-l z \
|
||||
@@ -85,10 +83,11 @@ LIBS+= \
|
||||
|
||||
DEBUGFLAGS=-g
|
||||
CXXFLAGS=-O2
|
||||
xCXXFLAGS=-pthread -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat -Wformat-security \
|
||||
xCXXFLAGS=-pthread -Wall -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wno-unused-parameter -Wformat -Wformat-security \
|
||||
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
|
||||
|
||||
OBJS= \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
@@ -105,7 +104,9 @@ OBJS= \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o
|
||||
|
||||
|
||||
all: bitcoind
|
||||
@@ -114,6 +115,11 @@ all: bitcoind
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/build.h: FORCE
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
@@ -142,3 +148,6 @@ clean:
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj-test/*.P
|
||||
-rm -f src/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_MRUSET_H
|
||||
#define BITCOIN_MRUSET_H
|
||||
|
||||
|
||||
310
src/net.cpp
310
src/net.cpp
@@ -1,15 +1,15 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "irc.h"
|
||||
#include "db.h"
|
||||
#include "net.h"
|
||||
#include "init.h"
|
||||
#include "strlcpy.h"
|
||||
#include "addrman.h"
|
||||
#include "ui_interface.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <string.h>
|
||||
@@ -35,7 +35,7 @@ void ThreadOpenAddedConnections2(void* parg);
|
||||
void ThreadMapPort2(void* parg);
|
||||
#endif
|
||||
void ThreadDNSAddressSeed2(void* parg);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fUseGrant = true);
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ map<CInv, int64> mapAlreadyAskedFor;
|
||||
set<CNetAddr> setservAddNodeAddresses;
|
||||
CCriticalSection cs_setservAddNodeAddresses;
|
||||
|
||||
|
||||
static CSemaphore *semOutbound = NULL;
|
||||
|
||||
unsigned short GetListenPort()
|
||||
{
|
||||
@@ -159,14 +159,14 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
|
||||
}
|
||||
if (pszKeyword == NULL)
|
||||
break;
|
||||
if (strLine.find(pszKeyword) != -1)
|
||||
if (strLine.find(pszKeyword) != string::npos)
|
||||
{
|
||||
strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
|
||||
break;
|
||||
}
|
||||
}
|
||||
closesocket(hSocket);
|
||||
if (strLine.find("<") != -1)
|
||||
if (strLine.find("<") != string::npos)
|
||||
strLine = strLine.substr(0, strLine.find("<"));
|
||||
strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
|
||||
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
|
||||
@@ -269,9 +269,11 @@ void ThreadGetMyExternalIP(void* parg)
|
||||
// setAddrKnown automatically filters any duplicate sends.
|
||||
CAddress addr(addrLocalHost);
|
||||
addr.nTime = GetAdjustedTime();
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
pnode->PushAddress(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,111 +291,12 @@ void AddressCurrentlyConnected(const CService& addr)
|
||||
|
||||
|
||||
|
||||
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
|
||||
{
|
||||
// If the dialog might get closed before the reply comes back,
|
||||
// call this in the destructor so it doesn't get called after it's deleted.
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
CRITICAL_BLOCK(pnode->cs_mapRequests)
|
||||
{
|
||||
for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
|
||||
{
|
||||
CRequestTracker& tracker = (*mi).second;
|
||||
if (tracker.fn == fn && tracker.param1 == param1)
|
||||
pnode->mapRequests.erase(mi++);
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Subscription methods for the broadcast and subscription system.
|
||||
// Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
|
||||
//
|
||||
// The subscription system uses a meet-in-the-middle strategy.
|
||||
// With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
|
||||
// subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
|
||||
//
|
||||
|
||||
bool AnySubscribed(unsigned int nChannel)
|
||||
{
|
||||
if (pnodeLocalHost->IsSubscribed(nChannel))
|
||||
return true;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->IsSubscribed(nChannel))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNode::IsSubscribed(unsigned int nChannel)
|
||||
{
|
||||
if (nChannel >= vfSubscribe.size())
|
||||
return false;
|
||||
return vfSubscribe[nChannel];
|
||||
}
|
||||
|
||||
void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
|
||||
{
|
||||
if (nChannel >= vfSubscribe.size())
|
||||
return;
|
||||
|
||||
if (!AnySubscribed(nChannel))
|
||||
{
|
||||
// Relay subscribe
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode != this)
|
||||
pnode->PushMessage("subscribe", nChannel, nHops);
|
||||
}
|
||||
|
||||
vfSubscribe[nChannel] = true;
|
||||
}
|
||||
|
||||
void CNode::CancelSubscribe(unsigned int nChannel)
|
||||
{
|
||||
if (nChannel >= vfSubscribe.size())
|
||||
return;
|
||||
|
||||
// Prevent from relaying cancel if wasn't subscribed
|
||||
if (!vfSubscribe[nChannel])
|
||||
return;
|
||||
vfSubscribe[nChannel] = false;
|
||||
|
||||
if (!AnySubscribed(nChannel))
|
||||
{
|
||||
// Relay subscription cancel
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode != this)
|
||||
pnode->PushMessage("sub-cancel", nChannel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CNode* FindNode(const CNetAddr& ip)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if ((CNetAddr)pnode->addr == ip)
|
||||
return (pnode);
|
||||
@@ -403,8 +306,8 @@ CNode* FindNode(const CNetAddr& ip)
|
||||
|
||||
CNode* FindNode(const CService& addr)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if ((CService)pnode->addr == addr)
|
||||
return (pnode);
|
||||
@@ -458,8 +361,10 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
|
||||
pnode->AddRef(nTimeout);
|
||||
else
|
||||
pnode->AddRef();
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
}
|
||||
|
||||
pnode->nTimeConnected = GetTime();
|
||||
return pnode;
|
||||
@@ -486,13 +391,6 @@ void CNode::CloseSocketDisconnect()
|
||||
|
||||
void CNode::Cleanup()
|
||||
{
|
||||
// All of a nodes broadcasts and subscriptions are automatically torn down
|
||||
// when it goes down, so a node has to stay up to keep its broadcast going.
|
||||
|
||||
// Cancel subscriptions
|
||||
for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
|
||||
if (vfSubscribe[nChannel])
|
||||
CancelSubscribe(nChannel);
|
||||
}
|
||||
|
||||
|
||||
@@ -522,8 +420,8 @@ void CNode::ClearBanned()
|
||||
bool CNode::IsBanned(CNetAddr ip)
|
||||
{
|
||||
bool fResult = false;
|
||||
CRITICAL_BLOCK(cs_setBanned)
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
|
||||
if (i != setBanned.end())
|
||||
{
|
||||
@@ -547,9 +445,11 @@ bool CNode::Misbehaving(int howmuch)
|
||||
if (nMisbehavior >= GetArg("-banscore", 100))
|
||||
{
|
||||
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
|
||||
CRITICAL_BLOCK(cs_setBanned)
|
||||
{
|
||||
LOCK(cs_setBanned);
|
||||
if (setBanned[addr] < banTime)
|
||||
setBanned[addr] = banTime;
|
||||
}
|
||||
CloseSocketDisconnect();
|
||||
printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
|
||||
return true;
|
||||
@@ -591,15 +491,15 @@ void ThreadSocketHandler2(void* parg)
|
||||
{
|
||||
printf("ThreadSocketHandler started\n");
|
||||
list<CNode*> vNodesDisconnected;
|
||||
int nPrevNodeCount = 0;
|
||||
unsigned int nPrevNodeCount = 0;
|
||||
|
||||
loop
|
||||
{
|
||||
//
|
||||
// Disconnect nodes
|
||||
//
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
// Disconnect unused nodes
|
||||
vector<CNode*> vNodesCopy = vNodes;
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
@@ -610,6 +510,10 @@ void ThreadSocketHandler2(void* parg)
|
||||
// remove from vNodes
|
||||
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
|
||||
|
||||
if (pnode->fHasGrant)
|
||||
semOutbound->post();
|
||||
pnode->fHasGrant = false;
|
||||
|
||||
// close socket and cleanup
|
||||
pnode->CloseSocketDisconnect();
|
||||
pnode->Cleanup();
|
||||
@@ -630,11 +534,23 @@ void ThreadSocketHandler2(void* parg)
|
||||
if (pnode->GetRefCount() <= 0)
|
||||
{
|
||||
bool fDelete = false;
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_inventory)
|
||||
fDelete = true;
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend)
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vRecv, lockRecv);
|
||||
if (lockRecv)
|
||||
{
|
||||
TRY_LOCK(pnode->cs_mapRequests, lockReq);
|
||||
if (lockReq)
|
||||
{
|
||||
TRY_LOCK(pnode->cs_inventory, lockInv);
|
||||
if (lockInv)
|
||||
fDelete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fDelete)
|
||||
{
|
||||
vNodesDisconnected.remove(pnode);
|
||||
@@ -668,8 +584,8 @@ void ThreadSocketHandler2(void* parg)
|
||||
if(hListenSocket != INVALID_SOCKET)
|
||||
FD_SET(hListenSocket, &fdsetRecv);
|
||||
hSocketMax = max(hSocketMax, hListenSocket);
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
if (pnode->hSocket == INVALID_SOCKET)
|
||||
@@ -677,9 +593,11 @@ void ThreadSocketHandler2(void* parg)
|
||||
FD_SET(pnode->hSocket, &fdsetRecv);
|
||||
FD_SET(pnode->hSocket, &fdsetError);
|
||||
hSocketMax = max(hSocketMax, pnode->hSocket);
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
|
||||
if (!pnode->vSend.empty())
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend && !pnode->vSend.empty())
|
||||
FD_SET(pnode->hSocket, &fdsetSend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,10 +609,10 @@ void ThreadSocketHandler2(void* parg)
|
||||
if (nSelect == SOCKET_ERROR)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (hSocketMax > -1)
|
||||
if (hSocketMax != INVALID_SOCKET)
|
||||
{
|
||||
printf("socket select error %d\n", nErr);
|
||||
for (int i = 0; i <= hSocketMax; i++)
|
||||
for (unsigned int i = 0; i <= hSocketMax; i++)
|
||||
FD_SET(i, &fdsetRecv);
|
||||
}
|
||||
FD_ZERO(&fdsetSend);
|
||||
@@ -717,10 +635,12 @@ void ThreadSocketHandler2(void* parg)
|
||||
if (hSocket != INVALID_SOCKET)
|
||||
addr = CAddress(sockaddr);
|
||||
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
if (pnode->fInbound)
|
||||
nInbound++;
|
||||
}
|
||||
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
{
|
||||
@@ -729,9 +649,11 @@ void ThreadSocketHandler2(void* parg)
|
||||
}
|
||||
else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_setservAddNodeAddresses)
|
||||
{
|
||||
LOCK(cs_setservAddNodeAddresses);
|
||||
if (!setservAddNodeAddresses.count(addr))
|
||||
closesocket(hSocket);
|
||||
}
|
||||
}
|
||||
else if (CNode::IsBanned(addr))
|
||||
{
|
||||
@@ -743,8 +665,10 @@ void ThreadSocketHandler2(void* parg)
|
||||
printf("accepted connection %s\n", addr.ToString().c_str());
|
||||
CNode* pnode = new CNode(hSocket, addr, true);
|
||||
pnode->AddRef();
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodes.push_back(pnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,8 +677,8 @@ void ThreadSocketHandler2(void* parg)
|
||||
// Service each socket
|
||||
//
|
||||
vector<CNode*> vNodesCopy;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodesCopy = vNodes;
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
pnode->AddRef();
|
||||
@@ -771,7 +695,8 @@ void ThreadSocketHandler2(void* parg)
|
||||
continue;
|
||||
if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
|
||||
TRY_LOCK(pnode->cs_vRecv, lockRecv);
|
||||
if (lockRecv)
|
||||
{
|
||||
CDataStream& vRecv = pnode->vRecv;
|
||||
unsigned int nPos = vRecv.size();
|
||||
@@ -820,7 +745,8 @@ void ThreadSocketHandler2(void* parg)
|
||||
continue;
|
||||
if (FD_ISSET(pnode->hSocket, &fdsetSend))
|
||||
{
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend)
|
||||
{
|
||||
CDataStream& vSend = pnode->vSend;
|
||||
if (!vSend.empty())
|
||||
@@ -874,8 +800,8 @@ void ThreadSocketHandler2(void* parg)
|
||||
}
|
||||
}
|
||||
}
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
pnode->Release();
|
||||
}
|
||||
@@ -1086,7 +1012,7 @@ void ThreadDNSAddressSeed2(void* parg)
|
||||
{
|
||||
printf("Loading addresses from DNS seeds (could take a while)\n");
|
||||
|
||||
for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
|
||||
for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
|
||||
vector<CNetAddr> vaddr;
|
||||
vector<CAddress> vAdd;
|
||||
if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
|
||||
@@ -1263,7 +1189,7 @@ void ThreadOpenConnections2(void* parg)
|
||||
{
|
||||
CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
|
||||
if (addr.IsValid())
|
||||
OpenNetworkConnection(addr);
|
||||
OpenNetworkConnection(addr, false);
|
||||
for (int i = 0; i < 10 && i < nLoop; i++)
|
||||
{
|
||||
Sleep(500);
|
||||
@@ -1278,41 +1204,25 @@ void ThreadOpenConnections2(void* parg)
|
||||
int64 nStart = GetTime();
|
||||
loop
|
||||
{
|
||||
int nOutbound = 0;
|
||||
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
|
||||
Sleep(500);
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
|
||||
// Limit outbound connections
|
||||
loop
|
||||
{
|
||||
nOutbound = 0;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (!pnode->fInbound)
|
||||
nOutbound++;
|
||||
int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
|
||||
nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
|
||||
if (nOutbound < nMaxOutboundConnections)
|
||||
break;
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
|
||||
Sleep(2000);
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
}
|
||||
|
||||
bool fAddSeeds = false;
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
|
||||
semOutbound->wait();
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
|
||||
// Add seed nodes if IRC isn't working
|
||||
bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
|
||||
if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
|
||||
{
|
||||
std::vector<CAddress> vAdd;
|
||||
for (int i = 0; i < ARRAYLEN(pnSeed); i++)
|
||||
for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
|
||||
{
|
||||
// It'll only connect to one or two seed nodes because once it connects,
|
||||
// it'll get a pile of addresses with newer timestamps.
|
||||
@@ -1332,14 +1242,19 @@ void ThreadOpenConnections2(void* parg)
|
||||
// Choose an address to connect to based on most recently seen
|
||||
//
|
||||
CAddress addrConnect;
|
||||
int64 nBest = std::numeric_limits<int64>::min();
|
||||
|
||||
// Only connect to one address per a.b.?.? range.
|
||||
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
|
||||
int nOutbound = 0;
|
||||
set<vector<unsigned char> > setConnected;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||
setConnected.insert(pnode->addr.GetGroup());
|
||||
if (!pnode->fInbound)
|
||||
nOutbound++;
|
||||
}
|
||||
}
|
||||
|
||||
int64 nANow = GetAdjustedTime();
|
||||
|
||||
@@ -1369,6 +1284,8 @@ void ThreadOpenConnections2(void* parg)
|
||||
|
||||
if (addrConnect.IsValid())
|
||||
OpenNetworkConnection(addrConnect);
|
||||
else
|
||||
semOutbound->post();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1405,9 +1322,11 @@ void ThreadOpenAddedConnections2(void* parg)
|
||||
if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))
|
||||
{
|
||||
vservAddressesToAdd.push_back(vservNode);
|
||||
CRITICAL_BLOCK(cs_setservAddNodeAddresses)
|
||||
{
|
||||
LOCK(cs_setservAddNodeAddresses);
|
||||
BOOST_FOREACH(CService& serv, vservNode)
|
||||
setservAddNodeAddresses.insert(serv);
|
||||
}
|
||||
}
|
||||
}
|
||||
loop
|
||||
@@ -1415,7 +1334,8 @@ void ThreadOpenAddedConnections2(void* parg)
|
||||
vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
|
||||
// Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
|
||||
// (keeping in mind that addnode entries can have many IPs if fAllowDNS)
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
|
||||
BOOST_FOREACH(CService& addrNode, *(it))
|
||||
@@ -1425,8 +1345,10 @@ void ThreadOpenAddedConnections2(void* parg)
|
||||
it--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
|
||||
{
|
||||
semOutbound->wait();
|
||||
OpenNetworkConnection(CAddress(*(vserv.begin())));
|
||||
Sleep(500);
|
||||
if (fShutdown)
|
||||
@@ -1442,7 +1364,14 @@ void ThreadOpenAddedConnections2(void* parg)
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect)
|
||||
bool static ReleaseGrant(bool fUseGrant) {
|
||||
if (fUseGrant)
|
||||
semOutbound->post();
|
||||
return false;
|
||||
}
|
||||
|
||||
// only call this function when semOutbound has been waited for
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, bool fUseGrant)
|
||||
{
|
||||
//
|
||||
// Initiate outbound network connection
|
||||
@@ -1451,7 +1380,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
|
||||
return false;
|
||||
if ((CNetAddr)addrConnect == (CNetAddr)addrLocalHost || !addrConnect.IsIPv4() ||
|
||||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
|
||||
return false;
|
||||
return ReleaseGrant(fUseGrant);
|
||||
|
||||
vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
|
||||
CNode* pnode = ConnectNode(addrConnect);
|
||||
@@ -1459,7 +1388,13 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
|
||||
if (fShutdown)
|
||||
return false;
|
||||
if (!pnode)
|
||||
return false;
|
||||
return ReleaseGrant(fUseGrant);
|
||||
if (pnode->fHasGrant) {
|
||||
// node already has connection grant, release the one that was passed to us
|
||||
ReleaseGrant(fUseGrant);
|
||||
} else {
|
||||
pnode->fHasGrant = fUseGrant;
|
||||
}
|
||||
pnode->fNetworkNode = true;
|
||||
|
||||
return true;
|
||||
@@ -1498,8 +1433,8 @@ void ThreadMessageHandler2(void* parg)
|
||||
while (!fShutdown)
|
||||
{
|
||||
vector<CNode*> vNodesCopy;
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
vNodesCopy = vNodes;
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
pnode->AddRef();
|
||||
@@ -1512,20 +1447,26 @@ void ThreadMessageHandler2(void* parg)
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
{
|
||||
// Receive messages
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
|
||||
ProcessMessages(pnode);
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vRecv, lockRecv);
|
||||
if (lockRecv)
|
||||
ProcessMessages(pnode);
|
||||
}
|
||||
if (fShutdown)
|
||||
return;
|
||||
|
||||
// Send messages
|
||||
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
|
||||
SendMessages(pnode, pnode == pnodeTrickle);
|
||||
{
|
||||
TRY_LOCK(pnode->cs_vSend, lockSend);
|
||||
if (lockSend)
|
||||
SendMessages(pnode, pnode == pnodeTrickle);
|
||||
}
|
||||
if (fShutdown)
|
||||
return;
|
||||
}
|
||||
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||
pnode->Release();
|
||||
}
|
||||
@@ -1536,7 +1477,7 @@ void ThreadMessageHandler2(void* parg)
|
||||
vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
|
||||
Sleep(100);
|
||||
if (fRequestShutdown)
|
||||
Shutdown(NULL);
|
||||
StartShutdown();
|
||||
vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
|
||||
if (fShutdown)
|
||||
return;
|
||||
@@ -1630,6 +1571,12 @@ bool BindListenPort(string& strError)
|
||||
|
||||
void StartNode(void* parg)
|
||||
{
|
||||
if (semOutbound == NULL) {
|
||||
// initialize semaphore
|
||||
int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
|
||||
semOutbound = new CSemaphore(nMaxOutbound);
|
||||
}
|
||||
|
||||
#ifdef USE_UPNP
|
||||
#if USE_UPNP
|
||||
fUseUPnP = GetBoolArg("-upnp", true);
|
||||
@@ -1648,12 +1595,16 @@ void StartNode(void* parg)
|
||||
{
|
||||
vector<CNetAddr> vaddr;
|
||||
if (LookupHost(pszHostName, vaddr))
|
||||
{
|
||||
BOOST_FOREACH (const CNetAddr &addr, vaddr)
|
||||
{
|
||||
if (!addr.IsLocal())
|
||||
{
|
||||
addrLocalHost.SetIP(addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Get local host ip
|
||||
@@ -1752,6 +1703,9 @@ bool StopNode()
|
||||
fShutdown = true;
|
||||
nTransactionsUpdated++;
|
||||
int64 nStart = GetTime();
|
||||
if (semOutbound)
|
||||
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
|
||||
semOutbound->post();
|
||||
do
|
||||
{
|
||||
int nThreadsRunning = 0;
|
||||
|
||||
109
src/net.h
109
src/net.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NET_H
|
||||
#define BITCOIN_NET_H
|
||||
|
||||
@@ -29,7 +29,6 @@ extern int nBestHeight;
|
||||
|
||||
inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
|
||||
static const unsigned int PUBLISH_HOPS = 5;
|
||||
|
||||
bool RecvLine(SOCKET hSocket, std::string& strLine);
|
||||
bool GetMyExternalIP(CNetAddr& ipRet);
|
||||
@@ -37,8 +36,6 @@ void AddressCurrentlyConnected(const CService& addr);
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
CNode* FindNode(const CService& ip);
|
||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
||||
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
|
||||
bool AnySubscribed(unsigned int nChannel);
|
||||
void MapPort(bool fMapPort);
|
||||
bool BindListenPort(std::string& strError=REF(std::string()));
|
||||
void StartNode(void* parg);
|
||||
@@ -120,7 +117,7 @@ public:
|
||||
int64 nLastRecv;
|
||||
int64 nLastSendEmpty;
|
||||
int64 nTimeConnected;
|
||||
unsigned int nHeaderStart;
|
||||
int nHeaderStart;
|
||||
unsigned int nMessageStart;
|
||||
CAddress addr;
|
||||
int nVersion;
|
||||
@@ -130,6 +127,7 @@ public:
|
||||
bool fNetworkNode;
|
||||
bool fSuccessfullyConnected;
|
||||
bool fDisconnect;
|
||||
bool fHasGrant; // whether to call semOutbound.post() at disconnect
|
||||
protected:
|
||||
int nRefCount;
|
||||
|
||||
@@ -160,17 +158,10 @@ public:
|
||||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64, CInv> mapAskFor;
|
||||
|
||||
// publish and subscription
|
||||
std::vector<char> vfSubscribe;
|
||||
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
|
||||
{
|
||||
nServices = 0;
|
||||
hSocket = hSocketIn;
|
||||
vSend.SetType(SER_NETWORK);
|
||||
vRecv.SetType(SER_NETWORK);
|
||||
vSend.SetVersion(209);
|
||||
vRecv.SetVersion(209);
|
||||
nLastSend = 0;
|
||||
nLastRecv = 0;
|
||||
nLastSendEmpty = GetTime();
|
||||
@@ -181,6 +172,7 @@ public:
|
||||
nVersion = 0;
|
||||
strSubVer = "";
|
||||
fClient = false; // set by version message
|
||||
fHasGrant = false;
|
||||
fInbound = fInboundIn;
|
||||
fNetworkNode = false;
|
||||
fSuccessfullyConnected = false;
|
||||
@@ -192,7 +184,6 @@ public:
|
||||
hashLastGetBlocksEnd = 0;
|
||||
nStartingHeight = -1;
|
||||
fGetAddr = false;
|
||||
vfSubscribe.assign(256, false);
|
||||
nMisbehavior = 0;
|
||||
setInventoryKnown.max_size(SendBufferSize() / 1000);
|
||||
|
||||
@@ -254,15 +245,19 @@ public:
|
||||
|
||||
void AddInventoryKnown(const CInv& inv)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_inventory)
|
||||
{
|
||||
LOCK(cs_inventory);
|
||||
setInventoryKnown.insert(inv);
|
||||
}
|
||||
}
|
||||
|
||||
void PushInventory(const CInv& inv)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_inventory)
|
||||
{
|
||||
LOCK(cs_inventory);
|
||||
if (!setInventoryKnown.count(inv))
|
||||
vInventoryToSend.push_back(inv);
|
||||
}
|
||||
}
|
||||
|
||||
void AskFor(const CInv& inv)
|
||||
@@ -302,7 +297,7 @@ public:
|
||||
|
||||
void AbortMessage()
|
||||
{
|
||||
if (nHeaderStart == -1)
|
||||
if (nHeaderStart < 0)
|
||||
return;
|
||||
vSend.resize(nHeaderStart);
|
||||
nHeaderStart = -1;
|
||||
@@ -322,7 +317,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (nHeaderStart == -1)
|
||||
if (nHeaderStart < 0)
|
||||
return;
|
||||
|
||||
// Set the size
|
||||
@@ -347,7 +342,7 @@ public:
|
||||
|
||||
void EndMessageAbortIfEmpty()
|
||||
{
|
||||
if (nHeaderStart == -1)
|
||||
if (nHeaderStart < 0)
|
||||
return;
|
||||
int nSize = vSend.size() - nMessageStart;
|
||||
if (nSize > 0)
|
||||
@@ -526,8 +521,10 @@ public:
|
||||
uint256 hashReply;
|
||||
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
|
||||
|
||||
CRITICAL_BLOCK(cs_mapRequests)
|
||||
{
|
||||
LOCK(cs_mapRequests);
|
||||
mapRequests[hashReply] = CRequestTracker(fn, param1);
|
||||
}
|
||||
|
||||
PushMessage(pszCommand, hashReply);
|
||||
}
|
||||
@@ -539,8 +536,10 @@ public:
|
||||
uint256 hashReply;
|
||||
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
|
||||
|
||||
CRITICAL_BLOCK(cs_mapRequests)
|
||||
{
|
||||
LOCK(cs_mapRequests);
|
||||
mapRequests[hashReply] = CRequestTracker(fn, param1);
|
||||
}
|
||||
|
||||
PushMessage(pszCommand, hashReply, a1);
|
||||
}
|
||||
@@ -552,8 +551,10 @@ public:
|
||||
uint256 hashReply;
|
||||
RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
|
||||
|
||||
CRITICAL_BLOCK(cs_mapRequests)
|
||||
{
|
||||
LOCK(cs_mapRequests);
|
||||
mapRequests[hashReply] = CRequestTracker(fn, param1);
|
||||
}
|
||||
|
||||
PushMessage(pszCommand, hashReply, a1, a2);
|
||||
}
|
||||
@@ -599,15 +600,17 @@ public:
|
||||
inline void RelayInventory(const CInv& inv)
|
||||
{
|
||||
// Put on lists to offer to the other nodes
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
pnode->PushInventory(inv);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RelayMessage(const CInv& inv, const T& a)
|
||||
{
|
||||
CDataStream ss(SER_NETWORK);
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(10000);
|
||||
ss << a;
|
||||
RelayMessage(inv, ss);
|
||||
@@ -616,8 +619,8 @@ void RelayMessage(const CInv& inv, const T& a)
|
||||
template<>
|
||||
inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapRelay)
|
||||
{
|
||||
LOCK(cs_mapRelay);
|
||||
// Expire old relay messages
|
||||
while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
|
||||
{
|
||||
@@ -626,7 +629,7 @@ inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
|
||||
}
|
||||
|
||||
// Save original serialized message so newer versions are preserved
|
||||
mapRelay[inv] = ss;
|
||||
mapRelay.insert(std::make_pair(inv, ss));
|
||||
vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
|
||||
}
|
||||
|
||||
@@ -634,58 +637,4 @@ inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Templates for the publish and subscription system.
|
||||
// The object being published as T& obj needs to have:
|
||||
// a set<unsigned int> setSources member
|
||||
// specializations of AdvertInsert and AdvertErase
|
||||
// Currently implemented for CTable and CProduct.
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
|
||||
{
|
||||
// Add to sources
|
||||
obj.setSources.insert(pfrom->addr.ip);
|
||||
|
||||
if (!AdvertInsert(obj))
|
||||
return;
|
||||
|
||||
// Relay
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
|
||||
pnode->PushMessage("publish", nChannel, nHops, obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
|
||||
{
|
||||
uint256 hash = obj.GetHash();
|
||||
|
||||
CRITICAL_BLOCK(cs_vNodes)
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
|
||||
pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
|
||||
|
||||
AdvertErase(obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
|
||||
{
|
||||
// Remove a source
|
||||
obj.setSources.erase(pfrom->addr.ip);
|
||||
|
||||
// If no longer supported by any sources, cancel it
|
||||
if (obj.setSources.empty())
|
||||
AdvertStopPublish(pfrom, nChannel, nHops, obj);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
@@ -22,7 +22,7 @@ int nConnectTimeout = 5000;
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
vIP.clear();
|
||||
struct addrinfo aiHint;
|
||||
@@ -77,7 +77,7 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, int nM
|
||||
return (vIP.size() > 0);
|
||||
}
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
@@ -93,12 +93,12 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutio
|
||||
return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
}
|
||||
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions)
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions)
|
||||
{
|
||||
return LookupHost(pszName, vIP, nMaxSolutions, false);
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, int nMaxSolutions)
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
@@ -136,7 +136,7 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
|
||||
if (!fRet)
|
||||
return false;
|
||||
vAddr.resize(vIP.size());
|
||||
for (int i = 0; i < vIP.size(); i++)
|
||||
for (unsigned int i = 0; i < vIP.size(); i++)
|
||||
vAddr[i] = CService(vIP[i], port);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,21 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NETBASE_H
|
||||
#define BITCOIN_NETBASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef BSD
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "serialize.h"
|
||||
#include "compat.h"
|
||||
|
||||
extern int nConnectTimeout;
|
||||
|
||||
#ifdef WIN32
|
||||
// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
|
||||
#undef SetPort
|
||||
#endif
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
@@ -81,7 +68,7 @@ class CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
/** A combnation of a network address (CNetAddr) and a (TCP) port */
|
||||
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
@@ -126,10 +113,10 @@ class CService : public CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
|
||||
|
||||
|
||||
44
src/noui.cpp
Normal file
44
src/noui.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "ui_interface.h"
|
||||
|
||||
#include <string>
|
||||
#include "init.h"
|
||||
|
||||
int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
|
||||
{
|
||||
printf("%s: %s\n", caption.c_str(), message.c_str());
|
||||
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainFrameRepaint()
|
||||
{
|
||||
}
|
||||
|
||||
void AddressBookRepaint()
|
||||
{
|
||||
}
|
||||
|
||||
void InitMessage(const std::string &message)
|
||||
{
|
||||
}
|
||||
|
||||
std::string _(const char* psz)
|
||||
{
|
||||
return psz;
|
||||
}
|
||||
|
||||
void QueueShutdown()
|
||||
{
|
||||
// Without UI, Shutdown can simply be started in a new thread
|
||||
CreateThread(Shutdown, NULL);
|
||||
}
|
||||
|
||||
74
src/noui.h
74
src/noui.h
@@ -1,74 +0,0 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NOUI_H
|
||||
#define BITCOIN_NOUI_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
#include "wallet.h"
|
||||
|
||||
typedef void wxWindow;
|
||||
#define wxYES 0x00000002
|
||||
#define wxOK 0x00000004
|
||||
#define wxNO 0x00000008
|
||||
#define wxYES_NO (wxYES|wxNO)
|
||||
#define wxCANCEL 0x00000010
|
||||
#define wxAPPLY 0x00000020
|
||||
#define wxCLOSE 0x00000040
|
||||
#define wxOK_DEFAULT 0x00000000
|
||||
#define wxYES_DEFAULT 0x00000000
|
||||
#define wxNO_DEFAULT 0x00000080
|
||||
#define wxCANCEL_DEFAULT 0x80000000
|
||||
#define wxICON_EXCLAMATION 0x00000100
|
||||
#define wxICON_HAND 0x00000200
|
||||
#define wxICON_WARNING wxICON_EXCLAMATION
|
||||
#define wxICON_ERROR wxICON_HAND
|
||||
#define wxICON_QUESTION 0x00000400
|
||||
#define wxICON_INFORMATION 0x00000800
|
||||
#define wxICON_STOP wxICON_HAND
|
||||
#define wxICON_ASTERISK wxICON_INFORMATION
|
||||
#define wxICON_MASK (0x00000100|0x00000200|0x00000400|0x00000800)
|
||||
#define wxFORWARD 0x00001000
|
||||
#define wxBACKWARD 0x00002000
|
||||
#define wxRESET 0x00004000
|
||||
#define wxHELP 0x00008000
|
||||
#define wxMORE 0x00010000
|
||||
#define wxSETUP 0x00020000
|
||||
|
||||
inline int MyMessageBox(const std::string& message, const std::string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
|
||||
{
|
||||
printf("%s: %s\n", caption.c_str(), message.c_str());
|
||||
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
|
||||
return 4;
|
||||
}
|
||||
#define wxMessageBox MyMessageBox
|
||||
|
||||
inline int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
|
||||
{
|
||||
return MyMessageBox(message, caption, style, parent, x, y);
|
||||
}
|
||||
|
||||
inline bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void CalledSetStatusBar(const std::string& strText, int nField)
|
||||
{
|
||||
}
|
||||
|
||||
inline void UIThreadCall(boost::function0<void> fn)
|
||||
{
|
||||
}
|
||||
|
||||
inline void MainFrameRepaint()
|
||||
{
|
||||
}
|
||||
|
||||
inline void InitMessage(const std::string &message)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
2
src/obj/nogui/.gitignore
vendored
2
src/obj/nogui/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
||||
2
src/obj/test/.gitignore
vendored
2
src/obj/test/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
@@ -107,7 +107,7 @@ CInv::CInv(int typeIn, const uint256& hashIn)
|
||||
|
||||
CInv::CInv(const std::string& strType, const uint256& hashIn)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
|
||||
{
|
||||
if (strType == ppszTypeName[i])
|
||||
@@ -128,7 +128,7 @@ bool operator<(const CInv& a, const CInv& b)
|
||||
|
||||
bool CInv::IsKnownType() const
|
||||
{
|
||||
return (type >= 1 && type < ARRAYLEN(ppszTypeName));
|
||||
return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
|
||||
}
|
||||
|
||||
const char* CInv::GetCommand() const
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This header can only be compiled as C++.
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include "serialize.h"
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
#include <string>
|
||||
#include "uint256.h"
|
||||
|
||||
@@ -79,9 +78,10 @@ class CAddress : public CService
|
||||
if (fRead)
|
||||
pthis->Init();
|
||||
if (nType & SER_DISK)
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) ||
|
||||
(nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
READWRITE(nServices);
|
||||
READWRITE(*pip);
|
||||
)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "ui_aboutdialog.h"
|
||||
#include "clientmodel.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AboutDialog)
|
||||
|
||||
@@ -43,15 +43,19 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
ui->tableView->setFocus();
|
||||
break;
|
||||
case ForEditing:
|
||||
ui->buttonBox->hide();
|
||||
ui->buttonBox->setVisible(false);
|
||||
break;
|
||||
}
|
||||
switch(tab)
|
||||
{
|
||||
case SendingTab:
|
||||
ui->labelExplanation->hide();
|
||||
ui->labelExplanation->setVisible(false);
|
||||
ui->deleteButton->setVisible(true);
|
||||
ui->signMessage->setVisible(false);
|
||||
break;
|
||||
case ReceivingTab:
|
||||
ui->deleteButton->setVisible(false);
|
||||
ui->signMessage->setVisible(true);
|
||||
break;
|
||||
}
|
||||
ui->tableView->setTabKeyNavigation(false);
|
||||
@@ -90,8 +94,6 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
this->model = model;
|
||||
if(!model)
|
||||
return;
|
||||
// Refresh list from core
|
||||
model->updateList();
|
||||
|
||||
proxyModel = new QSortFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(model);
|
||||
@@ -121,11 +123,6 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(selectionChanged()));
|
||||
|
||||
if(mode == ForSending)
|
||||
{
|
||||
// Auto-select first row when in sending mode
|
||||
ui->tableView->selectRow(0);
|
||||
}
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
@@ -133,6 +130,7 @@ void AddressBookPage::on_copyToClipboard_clicked()
|
||||
{
|
||||
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
|
||||
}
|
||||
|
||||
void AddressBookPage::onCopyLabelAction()
|
||||
{
|
||||
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
|
||||
@@ -224,14 +222,18 @@ void AddressBookPage::selectionChanged()
|
||||
case SendingTab:
|
||||
// In sending tab, allow deletion of selection
|
||||
ui->deleteButton->setEnabled(true);
|
||||
ui->deleteButton->setVisible(true);
|
||||
deleteAction->setEnabled(true);
|
||||
ui->signMessage->setEnabled(false);
|
||||
ui->signMessage->setVisible(false);
|
||||
break;
|
||||
case ReceivingTab:
|
||||
// Deleting receiving addresses, however, is not allowed
|
||||
ui->deleteButton->setEnabled(false);
|
||||
ui->deleteButton->setVisible(false);
|
||||
deleteAction->setEnabled(false);
|
||||
ui->signMessage->setEnabled(true);
|
||||
ui->signMessage->setVisible(true);
|
||||
break;
|
||||
}
|
||||
ui->copyToClipboard->setEnabled(true);
|
||||
@@ -303,16 +305,12 @@ void AddressBookPage::on_showQRCode_clicked()
|
||||
QTableView *table = ui->tableView;
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
||||
|
||||
|
||||
QRCodeDialog *d;
|
||||
foreach (QModelIndex index, indexes)
|
||||
{
|
||||
QString address = index.data().toString(),
|
||||
label = index.sibling(index.row(), 0).data().toString(),
|
||||
title = QString("%1 << %2 >>").arg(label).arg(address);
|
||||
QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();
|
||||
|
||||
QRCodeDialog *d = new QRCodeDialog(title, address, label, tab == ReceivingTab, this);
|
||||
d->show();
|
||||
QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
|
||||
dialog->show();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "guiutil.h"
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "headers.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QColor>
|
||||
@@ -27,8 +27,9 @@ struct AddressTableEntry
|
||||
};
|
||||
|
||||
// Private implementation
|
||||
struct AddressTablePriv
|
||||
class AddressTablePriv
|
||||
{
|
||||
public:
|
||||
CWallet *wallet;
|
||||
QList<AddressTableEntry> cachedAddressTable;
|
||||
|
||||
@@ -39,8 +40,8 @@ struct AddressTablePriv
|
||||
{
|
||||
cachedAddressTable.clear();
|
||||
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
@@ -169,8 +170,8 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
|
||||
// Double-check that we're not overwriting a receiving address
|
||||
if(rec->type == AddressTableEntry::Sending)
|
||||
{
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
// Remove old entry
|
||||
wallet->DelAddressBookName(rec->address.toStdString());
|
||||
// Add new entry with new address
|
||||
@@ -231,7 +232,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & pa
|
||||
}
|
||||
}
|
||||
|
||||
void AddressTableModel::updateList()
|
||||
void AddressTableModel::update()
|
||||
{
|
||||
// Update address book model from Bitcoin core
|
||||
beginResetModel();
|
||||
@@ -254,8 +255,8 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
return QString();
|
||||
}
|
||||
// Check for duplicate addresses
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
if(wallet->mapAddressBook.count(strAddress))
|
||||
{
|
||||
editStatus = DUPLICATE_ADDRESS;
|
||||
@@ -285,10 +286,11 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
// Add entry and update list
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
// Add entry
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->SetAddressBookName(strAddress, strLabel);
|
||||
updateList();
|
||||
}
|
||||
return QString::fromStdString(strAddress);
|
||||
}
|
||||
|
||||
@@ -302,25 +304,19 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
|
||||
// Also refuse to remove receiving addresses.
|
||||
return false;
|
||||
}
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->DelAddressBookName(rec->address.toStdString());
|
||||
}
|
||||
updateList();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddressTableModel::update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Look up label for address in address book, if not found return empty string.
|
||||
*/
|
||||
QString AddressTableModel::labelForAddress(const QString &address) const
|
||||
{
|
||||
CRITICAL_BLOCK(wallet->cs_wallet)
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
CBitcoinAddress address_parsed(address.toStdString());
|
||||
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
|
||||
if (mi != wallet->mapAddressBook.end())
|
||||
|
||||
@@ -56,10 +56,6 @@ public:
|
||||
*/
|
||||
QString addRow(const QString &type, const QString &label, const QString &address);
|
||||
|
||||
/* Update address list from core. Invalidates any indices.
|
||||
*/
|
||||
void updateList();
|
||||
|
||||
/* Look up label for address in address book, if not found return empty string.
|
||||
*/
|
||||
QString labelForAddress(const QString &address) const;
|
||||
@@ -82,6 +78,8 @@ signals:
|
||||
void defaultAddressChanged(const QString &address);
|
||||
|
||||
public slots:
|
||||
/* Update address list from core. Invalidates any indices.
|
||||
*/
|
||||
void update();
|
||||
};
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
#include "clientmodel.h"
|
||||
#include "walletmodel.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "guiutil.h"
|
||||
|
||||
#include "headers.h"
|
||||
#include "init.h"
|
||||
#include "ui_interface.h"
|
||||
#include "qtipcserver.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QThread>
|
||||
#include <QTextCodec>
|
||||
#include <QLocale>
|
||||
#include <QTranslator>
|
||||
@@ -21,27 +21,35 @@
|
||||
|
||||
#include <boost/interprocess/ipc/message_queue.hpp>
|
||||
|
||||
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
|
||||
#define _BITCOIN_QT_PLUGINS_INCLUDED
|
||||
#define __INSURE__
|
||||
#include <QtPlugin>
|
||||
Q_IMPORT_PLUGIN(qcncodecs)
|
||||
Q_IMPORT_PLUGIN(qjpcodecs)
|
||||
Q_IMPORT_PLUGIN(qtwcodecs)
|
||||
Q_IMPORT_PLUGIN(qkrcodecs)
|
||||
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
||||
#endif
|
||||
|
||||
// Need a global reference for the notifications to find the GUI
|
||||
BitcoinGUI *guiref;
|
||||
QSplashScreen *splashref;
|
||||
static BitcoinGUI *guiref;
|
||||
static QSplashScreen *splashref;
|
||||
static WalletModel *walletmodel;
|
||||
static ClientModel *clientmodel;
|
||||
|
||||
int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
|
||||
{
|
||||
// Message from AppInit2(), always in main thread before main window is constructed
|
||||
QMessageBox::critical(0, QString::fromStdString(caption),
|
||||
QString::fromStdString(message),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
|
||||
int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
|
||||
{
|
||||
// Message from network thread
|
||||
if(guiref)
|
||||
{
|
||||
QMetaObject::invokeMethod(guiref, "error", Qt::QueuedConnection,
|
||||
bool modal = (style & wxMODAL);
|
||||
// in case of modal message, use blocking connection to wait for user to click OK
|
||||
QMetaObject::invokeMethod(guiref, "error",
|
||||
modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
|
||||
Q_ARG(QString, QString::fromStdString(caption)),
|
||||
Q_ARG(QString, QString::fromStdString(message)));
|
||||
Q_ARG(QString, QString::fromStdString(message)),
|
||||
Q_ARG(bool, modal));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -51,7 +59,7 @@ int ThreadSafeMessageBox(const std::string& message, const std::string& caption,
|
||||
return 4;
|
||||
}
|
||||
|
||||
bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
|
||||
bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
|
||||
{
|
||||
if(!guiref)
|
||||
return false;
|
||||
@@ -59,51 +67,34 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindo
|
||||
return true;
|
||||
bool payFee = false;
|
||||
|
||||
// Call slot on GUI thread.
|
||||
// If called from another thread, use a blocking QueuedConnection.
|
||||
Qt::ConnectionType connectionType = Qt::DirectConnection;
|
||||
if(QThread::currentThread() != QCoreApplication::instance()->thread())
|
||||
{
|
||||
connectionType = Qt::BlockingQueuedConnection;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(guiref, "askFee", connectionType,
|
||||
QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
|
||||
Q_ARG(qint64, nFeeRequired),
|
||||
Q_ARG(bool*, &payFee));
|
||||
|
||||
return payFee;
|
||||
}
|
||||
|
||||
void ThreadSafeHandleURL(const std::string& strURL)
|
||||
void ThreadSafeHandleURI(const std::string& strURI)
|
||||
{
|
||||
if(!guiref)
|
||||
return;
|
||||
|
||||
// Call slot on GUI thread.
|
||||
// If called from another thread, use a blocking QueuedConnection.
|
||||
Qt::ConnectionType connectionType = Qt::DirectConnection;
|
||||
if(QThread::currentThread() != QCoreApplication::instance()->thread())
|
||||
{
|
||||
connectionType = Qt::BlockingQueuedConnection;
|
||||
}
|
||||
QMetaObject::invokeMethod(guiref, "handleURL", connectionType,
|
||||
Q_ARG(QString, QString::fromStdString(strURL)));
|
||||
}
|
||||
|
||||
void CalledSetStatusBar(const std::string& strText, int nField)
|
||||
{
|
||||
// Only used for built-in mining, which is disabled, simple ignore
|
||||
}
|
||||
|
||||
void UIThreadCall(boost::function0<void> fn)
|
||||
{
|
||||
// Only used for built-in mining, which is disabled, simple ignore
|
||||
QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
|
||||
Q_ARG(QString, QString::fromStdString(strURI)));
|
||||
}
|
||||
|
||||
void MainFrameRepaint()
|
||||
{
|
||||
if(guiref)
|
||||
QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection);
|
||||
if(clientmodel)
|
||||
QMetaObject::invokeMethod(clientmodel, "update", Qt::QueuedConnection);
|
||||
if(walletmodel)
|
||||
QMetaObject::invokeMethod(walletmodel, "update", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void AddressBookRepaint()
|
||||
{
|
||||
if(walletmodel)
|
||||
QMetaObject::invokeMethod(walletmodel, "updateAddressList", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void InitMessage(const std::string &message)
|
||||
@@ -115,6 +106,11 @@ void InitMessage(const std::string &message)
|
||||
}
|
||||
}
|
||||
|
||||
void QueueShutdown()
|
||||
{
|
||||
QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/*
|
||||
Translate string to current locale using Qt.
|
||||
*/
|
||||
@@ -123,6 +119,18 @@ std::string _(const char* psz)
|
||||
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
|
||||
}
|
||||
|
||||
/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
|
||||
*/
|
||||
static void handleRunawayException(std::exception *e)
|
||||
{
|
||||
PrintExceptionContinue(e, "Runaway exception");
|
||||
QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occured. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
#ifndef BITCOIN_QT_TEST
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@@ -134,10 +142,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
|
||||
{
|
||||
const char *strURL = argv[i];
|
||||
const char *strURI = argv[i];
|
||||
try {
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
|
||||
if(mq.try_send(strURL, strlen(strURL), 0))
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
|
||||
if(mq.try_send(strURI, strlen(strURI), 0))
|
||||
exit(0);
|
||||
else
|
||||
break;
|
||||
@@ -160,11 +168,12 @@ int main(int argc, char *argv[])
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
// ... then bitcoin.conf:
|
||||
if (!ReadConfigFile(mapArgs, mapMultiArgs))
|
||||
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
||||
{
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
return 1;
|
||||
}
|
||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||
|
||||
// Application identification (must be set before OptionsModel is initialized,
|
||||
// as it is used to locate QSettings)
|
||||
@@ -218,22 +227,24 @@ int main(int argc, char *argv[])
|
||||
|
||||
try
|
||||
{
|
||||
BitcoinGUI window;
|
||||
guiref = &window;
|
||||
if(AppInit2(argc, argv))
|
||||
{
|
||||
{
|
||||
// Put this in a block, so that BitcoinGUI is cleaned up properly before
|
||||
// calling Shutdown() in case of exceptions.
|
||||
// Put this in a block, so that the Model objects are cleaned up before
|
||||
// calling Shutdown().
|
||||
|
||||
optionsModel.Upgrade(); // Must be done after AppInit2
|
||||
|
||||
BitcoinGUI window;
|
||||
if (splashref)
|
||||
splash.finish(&window);
|
||||
|
||||
ClientModel clientModel(&optionsModel);
|
||||
clientmodel = &clientModel;
|
||||
WalletModel walletModel(pwalletMain, &optionsModel);
|
||||
walletmodel = &walletModel;
|
||||
|
||||
guiref = &window;
|
||||
window.setClientModel(&clientModel);
|
||||
window.setWalletModel(&walletModel);
|
||||
|
||||
@@ -247,21 +258,21 @@ int main(int argc, char *argv[])
|
||||
window.show();
|
||||
}
|
||||
|
||||
// Place this here as guiref has to be defined if we dont want to lose URLs
|
||||
// Place this here as guiref has to be defined if we dont want to lose URIs
|
||||
ipcInit();
|
||||
|
||||
#if !defined(MAC_OSX) && !defined(WIN32)
|
||||
// TODO: implement qtipcserver.cpp for Mac and Windows
|
||||
|
||||
// Check for URL in argv
|
||||
// Check for URI in argv
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
|
||||
{
|
||||
const char *strURL = argv[i];
|
||||
const char *strURI = argv[i];
|
||||
try {
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
|
||||
mq.try_send(strURL, strlen(strURL), 0);
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
|
||||
mq.try_send(strURI, strlen(strURI), 0);
|
||||
}
|
||||
catch (boost::interprocess::interprocess_exception &ex) {
|
||||
}
|
||||
@@ -270,8 +281,14 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
app.exec();
|
||||
|
||||
window.hide();
|
||||
window.setClientModel(0);
|
||||
window.setWalletModel(0);
|
||||
guiref = 0;
|
||||
clientmodel = 0;
|
||||
walletmodel = 0;
|
||||
}
|
||||
// Shutdown the core and it's threads, but don't exit Bitcoin-Qt here
|
||||
Shutdown(NULL);
|
||||
}
|
||||
else
|
||||
@@ -279,9 +296,9 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
PrintException(&e, "Runaway exception");
|
||||
handleRunawayException(&e);
|
||||
} catch (...) {
|
||||
PrintException(NULL, "Runaway exception");
|
||||
handleRunawayException(NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons" lang="edit">
|
||||
<qresource prefix="/icons">
|
||||
<file alias="bitcoin">res/icons/bitcoin.png</file>
|
||||
<file alias="address-book">res/icons/address-book.png</file>
|
||||
<file alias="quit">res/icons/quit.png</file>
|
||||
|
||||
@@ -21,9 +21,12 @@ BitcoinAddressValidator::BitcoinAddressValidator(QObject *parent) :
|
||||
QValidator::State BitcoinAddressValidator::validate(QString &input, int &pos) const
|
||||
{
|
||||
// Correction
|
||||
for(int idx=0; idx<input.size(); ++idx)
|
||||
for(int idx=0; idx<input.size();)
|
||||
{
|
||||
switch(input.at(idx).unicode())
|
||||
bool removeChar = false;
|
||||
QChar ch = input.at(idx);
|
||||
// Transform characters that are visually close
|
||||
switch(ch.unicode())
|
||||
{
|
||||
case 'l':
|
||||
case 'I':
|
||||
@@ -33,9 +36,22 @@ QValidator::State BitcoinAddressValidator::validate(QString &input, int &pos) co
|
||||
case 'O':
|
||||
input[idx] = QChar('o');
|
||||
break;
|
||||
// Qt categorizes these as "Other_Format" not "Separator_Space"
|
||||
case 0x200B: // ZERO WIDTH SPACE
|
||||
case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
|
||||
removeChar = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Remove whitespace
|
||||
if(ch.isSpace())
|
||||
removeChar = true;
|
||||
// To next character
|
||||
if(removeChar)
|
||||
input.remove(idx, 1);
|
||||
else
|
||||
++idx;
|
||||
}
|
||||
|
||||
// Validation
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 20011-2012
|
||||
* The Bitcoin Developers 20011-2012
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2012
|
||||
*/
|
||||
#include "bitcoingui.h"
|
||||
#include "transactiontablemodel.h"
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "guiconstants.h"
|
||||
#include "askpassphrasedialog.h"
|
||||
#include "notificator.h"
|
||||
#include "guiutil.h"
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#include "macdockiconhandler.h"
|
||||
@@ -138,11 +139,11 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
frameBlocksLayout->addWidget(labelBlocksIcon);
|
||||
frameBlocksLayout->addStretch();
|
||||
|
||||
// Progress bar for blocks download
|
||||
progressBarLabel = new QLabel(tr("Synchronizing with network..."));
|
||||
// Progress bar and label for blocks download
|
||||
progressBarLabel = new QLabel();
|
||||
progressBarLabel->setVisible(false);
|
||||
progressBar = new QProgressBar();
|
||||
progressBar->setToolTip(tr("Block chain synchronization in progress"));
|
||||
progressBar->setAlignment(Qt::AlignCenter);
|
||||
progressBar->setVisible(false);
|
||||
|
||||
statusBar()->addWidget(progressBarLabel);
|
||||
@@ -162,8 +163,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
|
||||
BitcoinGUI::~BitcoinGUI()
|
||||
{
|
||||
if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
|
||||
trayIcon->hide();
|
||||
#ifdef Q_WS_MAC
|
||||
delete appMenuBar;
|
||||
#endif
|
||||
@@ -236,8 +235,8 @@ void BitcoinGUI::createActions()
|
||||
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
|
||||
optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
|
||||
optionsAction->setMenuRole(QAction::PreferencesRole);
|
||||
openBitcoinAction = new QAction(QIcon(":/icons/bitcoin"), tr("Open &Bitcoin"), this);
|
||||
openBitcoinAction->setToolTip(tr("Show the Bitcoin window"));
|
||||
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("Show/Hide &Bitcoin"), this);
|
||||
toggleHideAction->setToolTip(tr("Show or hide the Bitcoin window"));
|
||||
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
|
||||
exportAction->setToolTip(tr("Export the data in the current tab to a file"));
|
||||
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this);
|
||||
@@ -252,7 +251,7 @@ void BitcoinGUI::createActions()
|
||||
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
|
||||
connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
|
||||
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
|
||||
connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
|
||||
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
|
||||
connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
|
||||
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
|
||||
@@ -336,7 +335,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
|
||||
|
||||
// Report errors from network/worker thread
|
||||
connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
|
||||
connect(clientModel, SIGNAL(error(QString,QString, bool)), this, SLOT(error(QString,QString,bool)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +345,7 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
|
||||
if(walletModel)
|
||||
{
|
||||
// Report errors from wallet thread
|
||||
connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
|
||||
connect(walletModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool)));
|
||||
|
||||
// Put transaction list in tabs
|
||||
transactionView->setModel(walletModel);
|
||||
@@ -376,7 +375,7 @@ void BitcoinGUI::createTrayIcon()
|
||||
trayIcon = new QSystemTrayIcon(this);
|
||||
trayIconMenu = new QMenu(this);
|
||||
trayIcon->setContextMenu(trayIconMenu);
|
||||
trayIcon->setToolTip("Bitcoin client");
|
||||
trayIcon->setToolTip(tr("Bitcoin client"));
|
||||
trayIcon->setIcon(QIcon(":/icons/toolbar"));
|
||||
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
|
||||
@@ -384,12 +383,11 @@ void BitcoinGUI::createTrayIcon()
|
||||
#else
|
||||
// Note: On Mac, the dock icon is used to provide the tray's functionality.
|
||||
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
|
||||
connect(dockIconHandler, SIGNAL(dockIconClicked()), openBitcoinAction, SLOT(trigger()));
|
||||
trayIconMenu = dockIconHandler->dockMenu();
|
||||
#endif
|
||||
|
||||
// Configuration of the tray icon (or dock icon) icon menu
|
||||
trayIconMenu->addAction(openBitcoinAction);
|
||||
trayIconMenu->addAction(toggleHideAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(messageAction);
|
||||
#ifndef FIRST_CLASS_MESSAGING
|
||||
@@ -412,12 +410,34 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
if(reason == QSystemTrayIcon::Trigger)
|
||||
{
|
||||
// Click on system tray icon triggers "open bitcoin"
|
||||
openBitcoinAction->trigger();
|
||||
// Click on system tray icon triggers "show/hide bitcoin"
|
||||
toggleHideAction->trigger();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BitcoinGUI::toggleHidden()
|
||||
{
|
||||
// activateWindow() (sometimes) helps with keyboard focus on Windows
|
||||
if (isHidden())
|
||||
{
|
||||
show();
|
||||
activateWindow();
|
||||
}
|
||||
else if (isMinimized())
|
||||
{
|
||||
showNormal();
|
||||
activateWindow();
|
||||
}
|
||||
else if (GUIUtil::isObscured(this))
|
||||
{
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
else
|
||||
hide();
|
||||
}
|
||||
|
||||
void BitcoinGUI::optionsClicked()
|
||||
{
|
||||
if(!clientModel || !clientModel->getOptionsModel())
|
||||
@@ -451,20 +471,31 @@ void BitcoinGUI::setNumConnections(int count)
|
||||
|
||||
void BitcoinGUI::setNumBlocks(int count)
|
||||
{
|
||||
if(!clientModel)
|
||||
// don't show / hide progressBar and it's label if we have no connection(s) to the network
|
||||
if (!clientModel || clientModel->getNumConnections() == 0)
|
||||
{
|
||||
progressBarLabel->setVisible(false);
|
||||
progressBar->setVisible(false);
|
||||
|
||||
return;
|
||||
int total = clientModel->getNumBlocksOfPeers();
|
||||
}
|
||||
|
||||
int nTotalBlocks = clientModel->getNumBlocksOfPeers();
|
||||
QString tooltip;
|
||||
|
||||
if(count < total)
|
||||
if(count < nTotalBlocks)
|
||||
{
|
||||
int nRemainingBlocks = nTotalBlocks - count;
|
||||
float nPercentageDone = count / (nTotalBlocks * 0.01f);
|
||||
|
||||
if (clientModel->getStatusBarWarnings() == "")
|
||||
{
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBarLabel->setText(tr("Synchronizing with network..."));
|
||||
progressBar->setVisible(true);
|
||||
progressBar->setMaximum(total);
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBar->setFormat(tr("~%n block(s) remaining", "", nRemainingBlocks));
|
||||
progressBar->setMaximum(nTotalBlocks);
|
||||
progressBar->setValue(count);
|
||||
progressBar->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -472,7 +503,7 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBar->setVisible(false);
|
||||
}
|
||||
tooltip = tr("Downloaded %1 of %2 blocks of transaction history.").arg(count).arg(total);
|
||||
tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -515,10 +546,10 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
}
|
||||
|
||||
// Set icon state: spinning if catching up, tick otherwise
|
||||
if(secs < 30*60)
|
||||
if(secs < 90*60 && count >= nTotalBlocks)
|
||||
{
|
||||
tooltip = tr("Up to date") + QString(".\n") + tooltip;
|
||||
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
|
||||
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -538,23 +569,15 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
progressBar->setToolTip(tooltip);
|
||||
}
|
||||
|
||||
void BitcoinGUI::refreshStatusBar()
|
||||
{
|
||||
/* Might display multiple times in the case of multiple alerts
|
||||
static QString prevStatusBar;
|
||||
QString newStatusBar = clientModel->getStatusBarWarnings();
|
||||
if (prevStatusBar != newStatusBar)
|
||||
{
|
||||
prevStatusBar = newStatusBar;
|
||||
error(tr("Network Alert"), newStatusBar);
|
||||
}*/
|
||||
setNumBlocks(clientModel->getNumBlocks());
|
||||
}
|
||||
|
||||
void BitcoinGUI::error(const QString &title, const QString &message)
|
||||
void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
|
||||
{
|
||||
// Report errors from network/worker thread
|
||||
notificator->notify(Notificator::Critical, title, message);
|
||||
if(modal)
|
||||
{
|
||||
QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok);
|
||||
} else {
|
||||
notificator->notify(Notificator::Critical, title, message);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::changeEvent(QEvent *e)
|
||||
@@ -709,7 +732,7 @@ void BitcoinGUI::gotoMessagePage(QString addr)
|
||||
|
||||
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
// Accept only URLs
|
||||
// Accept only URIs
|
||||
if(event->mimeData()->hasUrls())
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
@@ -719,20 +742,20 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
|
||||
if(event->mimeData()->hasUrls())
|
||||
{
|
||||
gotoSendCoinsPage();
|
||||
QList<QUrl> urls = event->mimeData()->urls();
|
||||
foreach(const QUrl &url, urls)
|
||||
QList<QUrl> uris = event->mimeData()->urls();
|
||||
foreach(const QUrl &uri, uris)
|
||||
{
|
||||
sendCoinsPage->handleURL(url.toString());
|
||||
sendCoinsPage->handleURI(uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void BitcoinGUI::handleURL(QString strURL)
|
||||
void BitcoinGUI::handleURI(QString strURI)
|
||||
{
|
||||
gotoSendCoinsPage();
|
||||
sendCoinsPage->handleURL(strURL);
|
||||
sendCoinsPage->handleURI(strURI);
|
||||
|
||||
if(!isActiveWindow())
|
||||
activateWindow();
|
||||
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
QAction *aboutAction;
|
||||
QAction *receiveCoinsAction;
|
||||
QAction *optionsAction;
|
||||
QAction *openBitcoinAction;
|
||||
QAction *toggleHideAction;
|
||||
QAction *exportAction;
|
||||
QAction *encryptWalletAction;
|
||||
QAction *backupWalletAction;
|
||||
@@ -113,11 +113,9 @@ public slots:
|
||||
@see WalletModel::EncryptionStatus
|
||||
*/
|
||||
void setEncryptionStatus(int status);
|
||||
/** Set the status bar text if there are any warnings (removes sync progress bar if applicable) */
|
||||
void refreshStatusBar();
|
||||
|
||||
/** Notify the user of an error in the network or transaction handling code. */
|
||||
void error(const QString &title, const QString &message);
|
||||
void error(const QString &title, const QString &message, bool modal);
|
||||
/** Asks the user whether to pay the transaction fee or to cancel the transaction.
|
||||
It is currently not possible to pass a return value to another thread through
|
||||
BlockingQueuedConnection, so an indirected pointer is used.
|
||||
@@ -127,7 +125,7 @@ public slots:
|
||||
@param[out] payFee true to pay the fee, false to not pay the fee
|
||||
*/
|
||||
void askFee(qint64 nFeeRequired, bool *payFee);
|
||||
void handleURL(QString strURL);
|
||||
void handleURI(QString strURI);
|
||||
|
||||
void gotoMessagePage();
|
||||
void gotoMessagePage(QString);
|
||||
@@ -168,6 +166,8 @@ private slots:
|
||||
|
||||
/** Show window if hidden, unminimize when minimized */
|
||||
void showNormalIfMinimized();
|
||||
/** Hide window if visible, show if hidden */
|
||||
void toggleHidden();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#include <QtGlobal>
|
||||
// Automatically generated by extract_strings.py
|
||||
static const char *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
static const char UNUSED *bitcoin_strings[] = {QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Unable to bind to port %d on this computer. Bitcoin is probably already "
|
||||
"running."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send command to -server or bitcoind"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "List commands"),
|
||||
@@ -11,25 +20,30 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: bitcoind.pid)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Don't generate coins"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Start minimized"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Show splash screen on startup (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify data directory"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (default: 25)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set database disk log size in megabytes (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify connection timeout (in milliseconds)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect through socks4 proxy"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for addnode and connect"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: 8333 or testnet: 18333)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most <n> connections to peers (default: 125)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Don't accept connections from outside"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Don't bootstrap list of peers using DNS"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using internet relay chat (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set language, for example \"de_DE\" (default: system locale)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Number of seconds to keep misbehaving peers from reconnecting (default: "
|
||||
"86400)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Don't attempt to use UPnP to map the listening port"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to use UPnP to map the listening port"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fee per kB to add to transactions you send"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use Universal Plug and Play to map the listening port (default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use Universal Plug and Play to map the listening port (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"),
|
||||
@@ -42,8 +56,14 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for JSON-RPC connections on <port> (default: 8332)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on <ip> (default: 127.0.0.1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Execute command when the best block changes (%s in cmd is replaced by block "
|
||||
"hash)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to <n> (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 2500, 0 = all)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-6, default: 1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"\n"
|
||||
"SSL options: (see the Bitcoin Wiki for SSL setup instructions)"),
|
||||
@@ -54,9 +74,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:"
|
||||
"@STRENGTH)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "This help message"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Usage"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Cannot obtain a lock on data directory %s. Bitcoin is probably already "
|
||||
"running."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading addr.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."),
|
||||
@@ -66,6 +88,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet corrupted"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires newer version of Bitcoin"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot initialize keypool"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address"),
|
||||
@@ -74,12 +99,36 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Warning: -paytxfee is set very high. This is the transaction fee you will "
|
||||
"pay if you send a transaction."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: CreateThread(StartNode) failed"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Unable to bind to port %d on this computer. Bitcoin is probably already "
|
||||
"running."),
|
||||
"%s, you must set a rpcpassword in the configuration file:\n"
|
||||
" %s\n"
|
||||
"It is recommended you use the following random password:\n"
|
||||
"rpcuser=bitcoinrpc\n"
|
||||
"rpcpassword=%s\n"
|
||||
"(you do not need to remember this password)\n"
|
||||
"If the file does not exist, create it with owner-readable-only file "
|
||||
"permissions.\n"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "An error occured while setting up the RPC port %i for listening: %s"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"You must set rpcpassword=<password> in the configuration file:\n"
|
||||
"%s\n"
|
||||
"If the file does not exist, create it with owner-readable-only file "
|
||||
"permissions."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Warning: Please check that your computer's date and time are correct. If "
|
||||
"your clock is wrong Bitcoin will not work properly."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "beta"),
|
||||
};
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transaction "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error: This transaction requires a transaction fee of at least %s because of "
|
||||
"its amount, complexity, or use of recently received funds "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Transaction creation failed "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Sending..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error: The transaction was rejected. This might happen if some of the coins "
|
||||
"in your wallet were already spent, such as if you used a copy of wallet.dat "
|
||||
"and coins were spent in the copy but not marked as spent here."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
|
||||
};
|
||||
@@ -4,21 +4,14 @@
|
||||
#include "addresstablemodel.h"
|
||||
#include "transactiontablemodel.h"
|
||||
|
||||
#include "headers.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QDateTime>
|
||||
|
||||
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
||||
QObject(parent), optionsModel(optionsModel),
|
||||
cachedNumConnections(0), cachedNumBlocks(0)
|
||||
{
|
||||
// Until signal notifications is built into the bitcoin core,
|
||||
// simply update everything after polling using a timer.
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
|
||||
timer->start(MODEL_UPDATE_DELAY);
|
||||
|
||||
numBlocksAtStartup = -1;
|
||||
}
|
||||
|
||||
@@ -47,14 +40,23 @@ void ClientModel::update()
|
||||
{
|
||||
int newNumConnections = getNumConnections();
|
||||
int newNumBlocks = getNumBlocks();
|
||||
QString newStatusBar = getStatusBarWarnings();
|
||||
|
||||
if(cachedNumConnections != newNumConnections)
|
||||
emit numConnectionsChanged(newNumConnections);
|
||||
if(cachedNumBlocks != newNumBlocks)
|
||||
if(cachedNumBlocks != newNumBlocks || cachedStatusBar != newStatusBar)
|
||||
{
|
||||
// Simply emit a numBlocksChanged for now in case the status message changes,
|
||||
// so that the view updates the status bar.
|
||||
// TODO: It should send a notification.
|
||||
// (However, this might generate looped notifications and needs to be thought through and tested carefully)
|
||||
// error(tr("Network Alert"), newStatusBar);
|
||||
emit numBlocksChanged(newNumBlocks);
|
||||
}
|
||||
|
||||
cachedNumConnections = newNumConnections;
|
||||
cachedNumBlocks = newNumBlocks;
|
||||
cachedStatusBar = newStatusBar;
|
||||
}
|
||||
|
||||
bool ClientModel::isTestNet() const
|
||||
@@ -86,3 +88,8 @@ QString ClientModel::formatFullVersion() const
|
||||
{
|
||||
return QString::fromStdString(FormatFullVersion());
|
||||
}
|
||||
|
||||
QString ClientModel::formatBuildDate() const
|
||||
{
|
||||
return QString::fromStdString(CLIENT_DATE);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,14 @@ public:
|
||||
QString getStatusBarWarnings() const;
|
||||
|
||||
QString formatFullVersion() const;
|
||||
QString formatBuildDate() const;
|
||||
|
||||
private:
|
||||
OptionsModel *optionsModel;
|
||||
|
||||
int cachedNumConnections;
|
||||
int cachedNumBlocks;
|
||||
QString cachedStatusBar;
|
||||
|
||||
int numBlocksAtStartup;
|
||||
|
||||
@@ -51,7 +53,7 @@ signals:
|
||||
void numBlocksChanged(int count);
|
||||
|
||||
//! Asynchronous error notification
|
||||
void error(const QString &title, const QString &message);
|
||||
void error(const QString &title, const QString &message, bool modal);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
CSVModelWriter::CSVModelWriter(const QString &filename, QObject *parent) :
|
||||
QObject(parent),
|
||||
filename(filename)
|
||||
filename(filename), model(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,8 +27,9 @@ void CSVModelWriter::addColumn(const QString &title, int column, int role)
|
||||
|
||||
static void writeValue(QTextStream &f, const QString &value)
|
||||
{
|
||||
// TODO: quoting if " or \n in string
|
||||
f << "\"" << value << "\"";
|
||||
QString escaped = value;
|
||||
escaped.replace('"', "\"\"");
|
||||
f << "\"" << escaped << "\"";
|
||||
}
|
||||
|
||||
static void writeSep(QTextStream &f)
|
||||
|
||||
@@ -106,6 +106,9 @@ void EditAddressDialog::accept()
|
||||
tr("New key generation failed."),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
return;
|
||||
case AddressTableModel::OK:
|
||||
// Failed with unknown reason. Just reject.
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
<property name="text">
|
||||
<string><b>Bitcoin</b> version</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -62,6 +65,9 @@
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -93,6 +99,9 @@ This product includes software developed by the OpenSSL Project for use in the O
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -28,9 +28,6 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="warningLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="signFrom">
|
||||
<property name="toolTip">
|
||||
<string>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
<string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>34</number>
|
||||
@@ -128,7 +128,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="copyToClipboard">
|
||||
<property name="toolTip">
|
||||
<string>Copy the currently selected address to the system clipboard</string>
|
||||
<string>Copy the current signature to the system clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy to Clipboard</string>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="labelBalance">
|
||||
<property name="text">
|
||||
<string>123.456 BTC</string>
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -72,18 +72,20 @@
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="labelUnconfirmed">
|
||||
<property name="text">
|
||||
<string>0 BTC</string>
|
||||
<string notr="true">0 BTC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Wallet</span></p></body></html></string>
|
||||
<string>Wallet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -44,7 +47,7 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chkReq">
|
||||
<widget class="QCheckBox" name="chkReqPayment">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -56,7 +59,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblAm1">
|
||||
<widget class="QLabel" name="lblAmount">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -91,7 +94,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblAm2">
|
||||
<widget class="QLabel" name="lblBTC">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -113,7 +116,7 @@
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="lblLabel">
|
||||
<property name="text">
|
||||
<string>Label:</string>
|
||||
</property>
|
||||
@@ -136,7 +139,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="lblMessage">
|
||||
<property name="text">
|
||||
<string>Message:</string>
|
||||
</property>
|
||||
@@ -194,7 +197,7 @@
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>chkReq</sender>
|
||||
<sender>chkReqPayment</sender>
|
||||
<signal>clicked(bool)</signal>
|
||||
<receiver>lnReqAmount</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#include "walletmodel.h"
|
||||
#include "bitcoinunits.h"
|
||||
|
||||
#include "headers.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QDoubleValidator>
|
||||
@@ -17,32 +15,35 @@
|
||||
#include <QClipboard>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QThread>
|
||||
|
||||
QString GUIUtil::dateTimeStr(qint64 nTime)
|
||||
{
|
||||
return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
|
||||
}
|
||||
namespace GUIUtil {
|
||||
|
||||
QString GUIUtil::dateTimeStr(const QDateTime &date)
|
||||
QString dateTimeStr(const QDateTime &date)
|
||||
{
|
||||
return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
|
||||
}
|
||||
|
||||
QFont GUIUtil::bitcoinAddressFont()
|
||||
QString dateTimeStr(qint64 nTime)
|
||||
{
|
||||
return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
|
||||
}
|
||||
|
||||
QFont bitcoinAddressFont()
|
||||
{
|
||||
QFont font("Monospace");
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
return font;
|
||||
}
|
||||
|
||||
void GUIUtil::setupAddressWidget(QLineEdit *widget, QWidget *parent)
|
||||
void setupAddressWidget(QLineEdit *widget, QWidget *parent)
|
||||
{
|
||||
widget->setMaxLength(BitcoinAddressValidator::MaxAddressLength);
|
||||
widget->setValidator(new BitcoinAddressValidator(parent));
|
||||
widget->setFont(bitcoinAddressFont());
|
||||
}
|
||||
|
||||
void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
||||
void setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
||||
{
|
||||
QDoubleValidator *amountValidator = new QDoubleValidator(parent);
|
||||
amountValidator->setDecimals(8);
|
||||
@@ -51,15 +52,15 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
||||
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||
}
|
||||
|
||||
bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
|
||||
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
|
||||
{
|
||||
if(url.scheme() != QString("bitcoin"))
|
||||
if(uri.scheme() != QString("bitcoin"))
|
||||
return false;
|
||||
|
||||
SendCoinsRecipient rv;
|
||||
rv.address = url.path();
|
||||
rv.address = uri.path();
|
||||
rv.amount = 0;
|
||||
QList<QPair<QString, QString> > items = url.queryItems();
|
||||
QList<QPair<QString, QString> > items = uri.queryItems();
|
||||
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
|
||||
{
|
||||
bool fShouldReturnFalse = false;
|
||||
@@ -96,21 +97,21 @@ bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUIUtil::parseBitcoinURL(QString url, SendCoinsRecipient *out)
|
||||
bool parseBitcoinURI(QString uri, SendCoinsRecipient *out)
|
||||
{
|
||||
// Convert bitcoin:// to bitcoin:
|
||||
//
|
||||
// Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
|
||||
// which will lowercase it (and thus invalidate the address).
|
||||
if(url.startsWith("bitcoin://"))
|
||||
if(uri.startsWith("bitcoin://"))
|
||||
{
|
||||
url.replace(0, 10, "bitcoin:");
|
||||
uri.replace(0, 10, "bitcoin:");
|
||||
}
|
||||
QUrl urlInstance(url);
|
||||
return parseBitcoinURL(urlInstance, out);
|
||||
QUrl uriInstance(uri);
|
||||
return parseBitcoinURI(uriInstance, out);
|
||||
}
|
||||
|
||||
QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
|
||||
QString HtmlEscape(const QString& str, bool fMultiLine)
|
||||
{
|
||||
QString escaped = Qt::escape(str);
|
||||
if(fMultiLine)
|
||||
@@ -120,12 +121,12 @@ QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
|
||||
return escaped;
|
||||
}
|
||||
|
||||
QString GUIUtil::HtmlEscape(const std::string& str, bool fMultiLine)
|
||||
QString HtmlEscape(const std::string& str, bool fMultiLine)
|
||||
{
|
||||
return HtmlEscape(QString::fromStdString(str), fMultiLine);
|
||||
}
|
||||
|
||||
void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
|
||||
void copyEntryData(QAbstractItemView *view, int column, int role)
|
||||
{
|
||||
if(!view || !view->selectionModel())
|
||||
return;
|
||||
@@ -138,7 +139,7 @@ void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
|
||||
}
|
||||
}
|
||||
|
||||
QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
|
||||
QString getSaveFileName(QWidget *parent, const QString &caption,
|
||||
const QString &dir,
|
||||
const QString &filter,
|
||||
QString *selectedSuffixOut)
|
||||
@@ -184,3 +185,34 @@ QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::ConnectionType blockingGUIThreadConnection()
|
||||
{
|
||||
if(QThread::currentThread() != QCoreApplication::instance()->thread())
|
||||
{
|
||||
return Qt::BlockingQueuedConnection;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Qt::DirectConnection;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkPoint(const QPoint &p, const QWidget *w)
|
||||
{
|
||||
QWidget *atW = qApp->widgetAt(w->mapToGlobal(p));
|
||||
if(!atW) return false;
|
||||
return atW->topLevelWidget() == w;
|
||||
}
|
||||
|
||||
bool isObscured(QWidget *w)
|
||||
{
|
||||
|
||||
return !(checkPoint(QPoint(0, 0), w)
|
||||
&& checkPoint(QPoint(w->width() - 1, 0), w)
|
||||
&& checkPoint(QPoint(0, w->height() - 1), w)
|
||||
&& checkPoint(QPoint(w->width() - 1, w->height() - 1), w)
|
||||
&& checkPoint(QPoint(w->width()/2, w->height()/2), w));
|
||||
}
|
||||
|
||||
} // namespace GUIUtil
|
||||
|
||||
|
||||
@@ -13,30 +13,29 @@ class QAbstractItemView;
|
||||
QT_END_NAMESPACE
|
||||
class SendCoinsRecipient;
|
||||
|
||||
/** Static utility functions used by the Bitcoin Qt UI.
|
||||
/** Utility functions used by the Bitcoin Qt UI.
|
||||
*/
|
||||
class GUIUtil
|
||||
namespace GUIUtil
|
||||
{
|
||||
public:
|
||||
// Create human-readable string from date
|
||||
static QString dateTimeStr(qint64 nTime);
|
||||
static QString dateTimeStr(const QDateTime &datetime);
|
||||
QString dateTimeStr(const QDateTime &datetime);
|
||||
QString dateTimeStr(qint64 nTime);
|
||||
|
||||
// Render bitcoin addresses in monospace font
|
||||
static QFont bitcoinAddressFont();
|
||||
QFont bitcoinAddressFont();
|
||||
|
||||
// Set up widgets for address and amounts
|
||||
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
||||
static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
||||
void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
||||
void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
||||
|
||||
// Parse "bitcoin:" URL into recipient object, return true on succesful parsing
|
||||
// See Bitcoin URL definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
|
||||
static bool parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out);
|
||||
static bool parseBitcoinURL(QString url, SendCoinsRecipient *out);
|
||||
// Parse "bitcoin:" URI into recipient object, return true on succesful parsing
|
||||
// See Bitcoin URI definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
|
||||
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out);
|
||||
bool parseBitcoinURI(QString uri, SendCoinsRecipient *out);
|
||||
|
||||
// HTML escaping for rich text controls
|
||||
static QString HtmlEscape(const QString& str, bool fMultiLine=false);
|
||||
static QString HtmlEscape(const std::string& str, bool fMultiLine=false);
|
||||
QString HtmlEscape(const QString& str, bool fMultiLine=false);
|
||||
QString HtmlEscape(const std::string& str, bool fMultiLine=false);
|
||||
|
||||
/** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing
|
||||
is selected.
|
||||
@@ -44,7 +43,7 @@ public:
|
||||
@param[in] role Data role to extract from the model
|
||||
@see TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
|
||||
*/
|
||||
static void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
|
||||
void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
|
||||
|
||||
/** Get save file name, mimics QFileDialog::getSaveFileName, except that it appends a default suffix
|
||||
when no suffix is provided by the user.
|
||||
@@ -56,10 +55,20 @@ public:
|
||||
@param[out] selectedSuffixOut Pointer to return the suffix (file type) that was selected (or 0).
|
||||
Can be useful when choosing the save file format based on suffix.
|
||||
*/
|
||||
static QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(),
|
||||
QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(),
|
||||
const QString &dir=QString(), const QString &filter=QString(),
|
||||
QString *selectedSuffixOut=0);
|
||||
|
||||
};
|
||||
/** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking.
|
||||
|
||||
@returns If called from the GUI thread, return a Qt::DirectConnection.
|
||||
If called from another thread, return a Qt::BlockingQueuedConnection.
|
||||
*/
|
||||
Qt::ConnectionType blockingGUIThreadConnection();
|
||||
|
||||
// Determine whether a widget is hidden behind other windows
|
||||
bool isObscured(QWidget *w);
|
||||
|
||||
} // namespace GUIUtil
|
||||
|
||||
#endif // GUIUTIL_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,7 @@ void MessagePage::on_signMessage_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
CDataStream ss(SER_GETHASH);
|
||||
CDataStream ss(SER_GETHASH, 0);
|
||||
ss << strMessageMagic;
|
||||
ss << ui->message->document()->toPlainText().toStdString();
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ private:
|
||||
QCheckBox *minimize_on_close;
|
||||
#endif
|
||||
QCheckBox *connect_socks4;
|
||||
QCheckBox *detach_database;
|
||||
QLineEdit *proxy_ip;
|
||||
QLineEdit *proxy_port;
|
||||
BitcoinAmountField *fee_edit;
|
||||
@@ -175,18 +176,16 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
|
||||
minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
|
||||
minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
|
||||
layout->addWidget(minimize_to_tray);
|
||||
|
||||
minimize_on_close = new QCheckBox(tr("M&inimize on close"));
|
||||
minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
|
||||
layout->addWidget(minimize_on_close);
|
||||
#endif
|
||||
|
||||
map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
|
||||
map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
|
||||
layout->addWidget(map_port_upnp);
|
||||
|
||||
#ifndef Q_WS_MAC
|
||||
minimize_on_close = new QCheckBox(tr("M&inimize on close"));
|
||||
minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
|
||||
layout->addWidget(minimize_on_close);
|
||||
#endif
|
||||
|
||||
connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
|
||||
connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
|
||||
layout->addWidget(connect_socks4);
|
||||
@@ -214,7 +213,7 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
|
||||
proxy_hbox->addStretch(1);
|
||||
|
||||
layout->addLayout(proxy_hbox);
|
||||
QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
|
||||
QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
|
||||
fee_help->setWordWrap(true);
|
||||
layout->addWidget(fee_help);
|
||||
|
||||
@@ -223,7 +222,6 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
|
||||
QLabel *fee_label = new QLabel(tr("Pay transaction &fee"));
|
||||
fee_hbox->addWidget(fee_label);
|
||||
fee_edit = new BitcoinAmountField();
|
||||
fee_edit->setToolTip(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
|
||||
|
||||
fee_label->setBuddy(fee_edit);
|
||||
fee_hbox->addWidget(fee_edit);
|
||||
@@ -231,6 +229,10 @@ MainOptionsPage::MainOptionsPage(QWidget *parent):
|
||||
|
||||
layout->addLayout(fee_hbox);
|
||||
|
||||
detach_database = new QCheckBox(tr("Detach databases at shutdown"));
|
||||
detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
|
||||
layout->addWidget(detach_database);
|
||||
|
||||
layout->addStretch(1); // Extra space at bottom
|
||||
|
||||
setLayout(layout);
|
||||
@@ -258,6 +260,7 @@ void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
|
||||
mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
|
||||
mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
|
||||
mapper->addMapping(fee_edit, OptionsModel::Fee);
|
||||
mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
|
||||
}
|
||||
|
||||
DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
|
||||
@@ -278,7 +281,8 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
|
||||
|
||||
layout->addLayout(unit_hbox);
|
||||
|
||||
display_addresses = new QCheckBox(tr("Display addresses in transaction list"), this);
|
||||
display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
|
||||
display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
|
||||
layout->addWidget(display_addresses);
|
||||
|
||||
layout->addStretch();
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "bitcoinunits.h"
|
||||
#include <QSettings>
|
||||
|
||||
#include "headers.h"
|
||||
#include "init.h"
|
||||
#include "walletdb.h"
|
||||
|
||||
OptionsModel::OptionsModel(QObject *parent) :
|
||||
QAbstractListModel(parent)
|
||||
@@ -28,6 +28,8 @@ void OptionsModel::Init()
|
||||
SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool());
|
||||
if (settings.contains("addrProxy") && settings.value("fUseProxy").toBool())
|
||||
SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString());
|
||||
if (settings.contains("detachDB"))
|
||||
SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool());
|
||||
}
|
||||
|
||||
bool OptionsModel::Upgrade()
|
||||
@@ -121,6 +123,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
|
||||
return QVariant(nDisplayUnit);
|
||||
case DisplayAddresses:
|
||||
return QVariant(bDisplayAddresses);
|
||||
case DetachDatabases:
|
||||
return QVariant(fDetachDB);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@@ -198,10 +202,17 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
|
||||
settings.setValue("nDisplayUnit", nDisplayUnit);
|
||||
emit displayUnitChanged(unit);
|
||||
}
|
||||
break;
|
||||
case DisplayAddresses: {
|
||||
bDisplayAddresses = value.toBool();
|
||||
settings.setValue("bDisplayAddresses", bDisplayAddresses);
|
||||
}
|
||||
break;
|
||||
case DetachDatabases: {
|
||||
fDetachDB = value.toBool();
|
||||
settings.setValue("detachDB", fDetachDB);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ public:
|
||||
Fee, // qint64
|
||||
DisplayUnit, // BitcoinUnits::Unit
|
||||
DisplayAddresses, // bool
|
||||
OptionIDRowCount
|
||||
DetachDatabases, // bool
|
||||
OptionIDRowCount,
|
||||
};
|
||||
|
||||
void Init();
|
||||
|
||||
@@ -8,21 +8,19 @@
|
||||
|
||||
#include <qrencode.h>
|
||||
|
||||
#define EXPORT_IMAGE_SIZE 256
|
||||
#define EXPORT_IMAGE_SIZE 256
|
||||
|
||||
QRCodeDialog::QRCodeDialog(const QString &title, const QString &addr, const QString &label, bool enableReq, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::QRCodeDialog),
|
||||
address(addr)
|
||||
QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) :
|
||||
QDialog(parent), ui(new Ui::QRCodeDialog), address(addr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(title);
|
||||
setWindowTitle(QString("%1").arg(address));
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->chkReq->setVisible(enableReq);
|
||||
ui->chkReqPayment->setVisible(enableReq);
|
||||
ui->lnReqAmount->setVisible(enableReq);
|
||||
ui->lblAm1->setVisible(enableReq);
|
||||
ui->lblAm2->setVisible(enableReq);
|
||||
ui->lblAmount->setVisible(enableReq);
|
||||
ui->lblBTC->setVisible(enableReq);
|
||||
|
||||
ui->lnLabel->setText(label);
|
||||
|
||||
@@ -37,19 +35,33 @@ QRCodeDialog::~QRCodeDialog()
|
||||
void QRCodeDialog::genCode()
|
||||
{
|
||||
QString uri = getURI();
|
||||
//qDebug() << "Encoding:" << uri.toUtf8().constData();
|
||||
QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
|
||||
myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
|
||||
myImage.fill(0xffffff);
|
||||
unsigned char *p = code->data;
|
||||
for(int y = 0; y < code->width; y++) {
|
||||
for(int x = 0; x < code->width; x++) {
|
||||
myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
|
||||
p++;
|
||||
|
||||
if (uri != "")
|
||||
{
|
||||
ui->lblQRCode->setText("");
|
||||
|
||||
QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
|
||||
if (!code)
|
||||
{
|
||||
ui->lblQRCode->setText(tr("Error encoding URI into QR Code."));
|
||||
return;
|
||||
}
|
||||
myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
|
||||
myImage.fill(0xffffff);
|
||||
unsigned char *p = code->data;
|
||||
for (int y = 0; y < code->width; y++)
|
||||
{
|
||||
for (int x = 0; x < code->width; x++)
|
||||
{
|
||||
myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
|
||||
p++;
|
||||
}
|
||||
}
|
||||
QRcode_free(code);
|
||||
ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
|
||||
}
|
||||
QRcode_free(code);
|
||||
ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
|
||||
else
|
||||
ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
|
||||
}
|
||||
|
||||
QString QRCodeDialog::getURI()
|
||||
@@ -57,41 +69,49 @@ QString QRCodeDialog::getURI()
|
||||
QString ret = QString("bitcoin:%1").arg(address);
|
||||
|
||||
int paramCount = 0;
|
||||
if(ui->chkReq->isChecked() && ui->lnReqAmount->text().isEmpty() == false) {
|
||||
bool ok= false;
|
||||
double amount = ui->lnReqAmount->text().toDouble(&ok);
|
||||
if(ok) {
|
||||
ret += QString("?amount=%1X8").arg(ui->lnReqAmount->text());
|
||||
if (ui->chkReqPayment->isChecked() && !ui->lnReqAmount->text().isEmpty())
|
||||
{
|
||||
bool ok = false;
|
||||
ui->lnReqAmount->text().toDouble(&ok);
|
||||
if (ok)
|
||||
{
|
||||
ret += QString("?amount=%1").arg(ui->lnReqAmount->text());
|
||||
paramCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(ui->lnLabel->text().isEmpty() == false) {
|
||||
if (!ui->lnLabel->text().isEmpty())
|
||||
{
|
||||
QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text()));
|
||||
ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl);
|
||||
paramCount++;
|
||||
}
|
||||
|
||||
if(ui->lnMessage->text().isEmpty() == false) {
|
||||
if (!ui->lnMessage->text().isEmpty())
|
||||
{
|
||||
QString msg(QUrl::toPercentEncoding(ui->lnMessage->text()));
|
||||
ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg);
|
||||
paramCount++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
// limit URI length to 255 chars, to prevent a DoS against the QR-Code dialog
|
||||
if (ret.length() < 256)
|
||||
return ret;
|
||||
else
|
||||
return QString("");
|
||||
}
|
||||
|
||||
void QRCodeDialog::on_lnReqAmount_textChanged(const QString &)
|
||||
void QRCodeDialog::on_lnReqAmount_textChanged(const QString &arg1)
|
||||
{
|
||||
genCode();
|
||||
}
|
||||
|
||||
void QRCodeDialog::on_lnLabel_textChanged(const QString &)
|
||||
void QRCodeDialog::on_lnLabel_textChanged(const QString &arg1)
|
||||
{
|
||||
genCode();
|
||||
}
|
||||
|
||||
void QRCodeDialog::on_lnMessage_textChanged(const QString &)
|
||||
void QRCodeDialog::on_lnMessage_textChanged(const QString &arg1)
|
||||
{
|
||||
genCode();
|
||||
}
|
||||
@@ -99,12 +119,11 @@ void QRCodeDialog::on_lnMessage_textChanged(const QString &)
|
||||
void QRCodeDialog::on_btnSaveAs_clicked()
|
||||
{
|
||||
QString fn = GUIUtil::getSaveFileName(this, tr("Save Image..."), QString(), tr("PNG Images (*.png)"));
|
||||
if(!fn.isEmpty()) {
|
||||
if (!fn.isEmpty())
|
||||
myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn);
|
||||
}
|
||||
}
|
||||
|
||||
void QRCodeDialog::on_chkReq_toggled(bool)
|
||||
void QRCodeDialog::on_chkReqPayment_toggled(bool)
|
||||
{
|
||||
genCode();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class QRCodeDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QRCodeDialog(const QString &title, const QString &address, const QString &label, bool allowReq, QWidget *parent = 0);
|
||||
explicit QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent = 0);
|
||||
~QRCodeDialog();
|
||||
|
||||
private slots:
|
||||
@@ -22,7 +22,7 @@ private slots:
|
||||
void on_lnMessage_textChanged(const QString &arg1);
|
||||
void on_btnSaveAs_clicked();
|
||||
|
||||
void on_chkReq_toggled(bool checked);
|
||||
void on_chkReqPayment_toggled(bool checked);
|
||||
|
||||
private:
|
||||
Ui::QRCodeDialog *ui;
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include "headers.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "qtipcserver.h"
|
||||
|
||||
using namespace boost::interprocess;
|
||||
using namespace boost::posix_time;
|
||||
@@ -16,7 +18,7 @@ using namespace std;
|
||||
|
||||
void ipcShutdown()
|
||||
{
|
||||
message_queue::remove("BitcoinURL");
|
||||
message_queue::remove(BITCOINURI_QUEUE_NAME);
|
||||
}
|
||||
|
||||
void ipcThread(void* parg)
|
||||
@@ -30,7 +32,7 @@ void ipcThread(void* parg)
|
||||
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
|
||||
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
|
||||
{
|
||||
ThreadSafeHandleURL(std::string(strBuf, nSize));
|
||||
ThreadSafeHandleURI(std::string(strBuf, nSize));
|
||||
Sleep(1000);
|
||||
}
|
||||
if (fShutdown)
|
||||
@@ -60,7 +62,7 @@ void ipcInit()
|
||||
size_t nSize;
|
||||
unsigned int nPriority;
|
||||
try {
|
||||
mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
|
||||
mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
|
||||
|
||||
// Make sure we don't lose any bitcoin: URIs
|
||||
for (int i = 0; i < 2; i++)
|
||||
@@ -68,15 +70,15 @@ void ipcInit()
|
||||
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
|
||||
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
|
||||
{
|
||||
ThreadSafeHandleURL(std::string(strBuf, nSize));
|
||||
ThreadSafeHandleURI(std::string(strBuf, nSize));
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure only one bitcoin instance is listening
|
||||
message_queue::remove("BitcoinURL");
|
||||
mq = new message_queue(open_or_create, "BitcoinURL", 2, 256);
|
||||
message_queue::remove(BITCOINURI_QUEUE_NAME);
|
||||
mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
|
||||
}
|
||||
catch (interprocess_exception &ex) {
|
||||
return;
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#define BITCOINURI_QUEUE_NAME "BitcoinURI"
|
||||
|
||||
void ipcInit();
|
||||
void ipcShutdown();
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 611 B After Width: | Height: | Size: 673 B |
@@ -154,6 +154,8 @@ void SendCoinsDialog::on_sendButton_clicked()
|
||||
tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
break;
|
||||
case WalletModel::Aborted: // User aborted, nothing to do
|
||||
break;
|
||||
case WalletModel::OK:
|
||||
accept();
|
||||
break;
|
||||
@@ -265,10 +267,10 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
|
||||
}
|
||||
|
||||
|
||||
void SendCoinsDialog::handleURL(const QString &url)
|
||||
void SendCoinsDialog::handleURI(const QString &uri)
|
||||
{
|
||||
SendCoinsRecipient rv;
|
||||
if(!GUIUtil::parseBitcoinURL(url, &rv))
|
||||
if(!GUIUtil::parseBitcoinURI(uri, &rv))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
QWidget *setupTabChain(QWidget *prev);
|
||||
|
||||
void pasteEntry(const SendCoinsRecipient &rv);
|
||||
void handleURL(const QString &url);
|
||||
void handleURI(const QString &uri);
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
|
||||
@@ -59,9 +59,11 @@ void SendCoinsEntry::on_payTo_textChanged(const QString &address)
|
||||
{
|
||||
if(!model)
|
||||
return;
|
||||
// Fill in label from address book, if no label is filled in yet
|
||||
if(ui->addAsLabel->text().isEmpty())
|
||||
ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));}
|
||||
// Fill in label from address book, if address has an associated label
|
||||
QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
|
||||
if(!associatedLabel.isEmpty())
|
||||
ui->addAsLabel->setText(associatedLabel);
|
||||
}
|
||||
|
||||
void SendCoinsEntry::setModel(WalletModel *model)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <QTest>
|
||||
#include <QObject>
|
||||
|
||||
#include "urltests.h"
|
||||
#include "uritests.h"
|
||||
|
||||
// This is all you need to run all the tests
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
URLTests test1;
|
||||
URITests test1;
|
||||
QTest::qExec(&test1);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user