mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-30 20:06:57 +01:00
Compare commits
1224 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32a928e1d7 | ||
|
|
c3bc50fe56 | ||
|
|
d53af9c729 | ||
|
|
6634e6dc42 | ||
|
|
3a72e91e3a | ||
|
|
72c8166589 | ||
|
|
2a9301b75a | ||
|
|
0dba651def | ||
|
|
0d989a99d0 | ||
|
|
cb44c07349 | ||
|
|
6d3d1b985f | ||
|
|
c3f45b4449 | ||
|
|
506061360a | ||
|
|
6247c53528 | ||
|
|
57af0d8ef0 | ||
|
|
82283aec3d | ||
|
|
c07e181cca | ||
|
|
ab67ec8695 | ||
|
|
9845499fa1 | ||
|
|
0b37038d2b | ||
|
|
c510f571dc | ||
|
|
3ba638b59a | ||
|
|
6d6bf32064 | ||
|
|
2a333587bd | ||
|
|
acbdc05560 | ||
|
|
e4ac5b3e5f | ||
|
|
13b0b1cd3d | ||
|
|
bbd76e0717 | ||
|
|
c6911a9755 | ||
|
|
f1a9aad789 | ||
|
|
8045273a01 | ||
|
|
d9b50a8cfd | ||
|
|
ff31f1fa10 | ||
|
|
65cee0bbbd | ||
|
|
220de9aafb | ||
|
|
deb9f100a0 | ||
|
|
caeafd1bd1 | ||
|
|
8b11b682f1 | ||
|
|
2857d51fea | ||
|
|
2d2e5bdcf4 | ||
|
|
3e72516398 | ||
|
|
207260d0c7 | ||
|
|
71f7ccf1ec | ||
|
|
12f341d253 | ||
|
|
49524859ca | ||
|
|
f9459ef914 | ||
|
|
8a17087795 | ||
|
|
37be168579 | ||
|
|
747b688b54 | ||
|
|
f9d1d13855 | ||
|
|
a9f8791388 | ||
|
|
c87919696d | ||
|
|
8365992f90 | ||
|
|
5dc6be8bba | ||
|
|
38297ba90a | ||
|
|
6ec7ac15ff | ||
|
|
3241935774 | ||
|
|
4cf9b4c6fa | ||
|
|
cef36fad89 | ||
|
|
b3f8f6ab94 | ||
|
|
d37a2fd808 | ||
|
|
638cecee77 | ||
|
|
a7642282f6 | ||
|
|
bced903ae5 | ||
|
|
135bee074d | ||
|
|
cc57473222 | ||
|
|
6a9a280ec7 | ||
|
|
d1b7590911 | ||
|
|
207ef3008c | ||
|
|
e25f0f0e53 | ||
|
|
599ec1e115 | ||
|
|
9769d14f03 | ||
|
|
3d6adbe71a | ||
|
|
eb49457ff2 | ||
|
|
1d1f32d16d | ||
|
|
de038acd96 | ||
|
|
673021410f | ||
|
|
cf64347d70 | ||
|
|
0a5ce30bc1 | ||
|
|
de2b9459bd | ||
|
|
b855abb8db | ||
|
|
56caa38a67 | ||
|
|
d0b3e77a08 | ||
|
|
eed1785f70 | ||
|
|
8d5f461cb6 | ||
|
|
c2bb42168b | ||
|
|
e4954b1297 | ||
|
|
ada2a39691 | ||
|
|
43de64949c | ||
|
|
ee0b648536 | ||
|
|
a6be58d536 | ||
|
|
39930ca6ae | ||
|
|
cac6b389d1 | ||
|
|
285746d3db | ||
|
|
738835d7b8 | ||
|
|
61fd72695f | ||
|
|
c0b130b79b | ||
|
|
81bbef2609 | ||
|
|
366944431b | ||
|
|
f1e262c8e1 | ||
|
|
bb353618f1 | ||
|
|
0547b02af7 | ||
|
|
d2cc6f489c | ||
|
|
da6e9fe634 | ||
|
|
827d8c2e0c | ||
|
|
d210f4f5b8 | ||
|
|
bcc292b22d | ||
|
|
00a757375c | ||
|
|
02247490f6 | ||
|
|
d6b13283d1 | ||
|
|
1bf66fcc0a | ||
|
|
31a8b70ee3 | ||
|
|
2a739598b1 | ||
|
|
9c8dc7caf1 | ||
|
|
c8bf315188 | ||
|
|
018ec85ff7 | ||
|
|
f72fd0e792 | ||
|
|
a5ba586669 | ||
|
|
552af52b45 | ||
|
|
3b2eb49db9 | ||
|
|
3e37e7eca4 | ||
|
|
2e3ffb2d82 | ||
|
|
842a31ad1b | ||
|
|
50e01ee620 | ||
|
|
035cb4781d | ||
|
|
fee10d800e | ||
|
|
14ac0adcc7 | ||
|
|
189eb6a989 | ||
|
|
5a1a362215 | ||
|
|
95d7f00295 | ||
|
|
1381ad2b21 | ||
|
|
26809acbf9 | ||
|
|
4d369ec30c | ||
|
|
f5cb3488be | ||
|
|
dc2a68dc43 | ||
|
|
6a34def27e | ||
|
|
1a52dd10a7 | ||
|
|
6ca5ee6211 | ||
|
|
b202d43076 | ||
|
|
22f9b06903 | ||
|
|
52c90a2b2b | ||
|
|
93dd68e924 | ||
|
|
feec18e329 | ||
|
|
49b09ec04f | ||
|
|
3731f5788e | ||
|
|
ea9eaf9dec | ||
|
|
2f91373a0a | ||
|
|
807f3e83ba | ||
|
|
bb86cffa56 | ||
|
|
e1eb3d4451 | ||
|
|
f394f21594 | ||
|
|
0eaaa83ba5 | ||
|
|
38682648c2 | ||
|
|
1da09ab062 | ||
|
|
d6c4400d57 | ||
|
|
da9413d913 | ||
|
|
81605d90f5 | ||
|
|
e96a8c7d86 | ||
|
|
3ccbaa56f4 | ||
|
|
1ba4925755 | ||
|
|
2dca98511f | ||
|
|
f2b066da70 | ||
|
|
bfc24bd4ce | ||
|
|
6cbae37667 | ||
|
|
b1d3e95a0a | ||
|
|
ea0796bde3 | ||
|
|
8b371316c5 | ||
|
|
8f09e4cac4 | ||
|
|
f8c449b5c8 | ||
|
|
085d9c75f4 | ||
|
|
a0971337d0 | ||
|
|
5add0b0d0f | ||
|
|
fe26948b79 | ||
|
|
e7770992ab | ||
|
|
3a9899f6a8 | ||
|
|
1d89225320 | ||
|
|
a53b07313f | ||
|
|
7fddf1210e | ||
|
|
463a1cab43 | ||
|
|
0a4e67afad | ||
|
|
b3295cd283 | ||
|
|
c1d79812f4 | ||
|
|
d078739965 | ||
|
|
8b1eb5687d | ||
|
|
a21bdda7ad | ||
|
|
6047902934 | ||
|
|
be2e2845ec | ||
|
|
ea3e34dc3d | ||
|
|
894ce6d88d | ||
|
|
6d7b6681b6 | ||
|
|
cae8742130 | ||
|
|
82bcb7bf80 | ||
|
|
2ff8456c11 | ||
|
|
4c1bc22013 | ||
|
|
7648cd46a4 | ||
|
|
cfa880f8e3 | ||
|
|
9c82c574a0 | ||
|
|
6321b515f2 | ||
|
|
4ad495c243 | ||
|
|
1ce15535f0 | ||
|
|
3b3d999618 | ||
|
|
ac4e7f6269 | ||
|
|
ab91bf39b7 | ||
|
|
17f8d6e400 | ||
|
|
76970091f1 | ||
|
|
62904b33f3 | ||
|
|
0e08efc54a | ||
|
|
b019ea17ec | ||
|
|
963af6449f | ||
|
|
b0a90fbb0c | ||
|
|
eabc8f2c81 | ||
|
|
d8ecd21ff7 | ||
|
|
23a44a7ad6 | ||
|
|
85eb1e7e56 | ||
|
|
31fac119dc | ||
|
|
4ee706243c | ||
|
|
da7b8c1260 | ||
|
|
5cb01b5714 | ||
|
|
2dc953274d | ||
|
|
db1967957d | ||
|
|
7b1504ccb8 | ||
|
|
f875921176 | ||
|
|
af8c050bff | ||
|
|
b9a4aaad1e | ||
|
|
f106491fa2 | ||
|
|
8b11bff10a | ||
|
|
423cece29d | ||
|
|
3b5c5b817f | ||
|
|
fc1cd74b86 | ||
|
|
f210c74398 | ||
|
|
dd2c101336 | ||
|
|
c1124277c5 | ||
|
|
1913b6e2fc | ||
|
|
3c28b335af | ||
|
|
004fa1441c | ||
|
|
17c94ea886 | ||
|
|
9631ac1214 | ||
|
|
4dc89fa875 | ||
|
|
97e02a8d52 | ||
|
|
65786afb05 | ||
|
|
1fcebc16c5 | ||
|
|
ace35a1997 | ||
|
|
4bd34b4966 | ||
|
|
2387944782 | ||
|
|
8788221761 | ||
|
|
aeea5e2a2d | ||
|
|
91c218a1cb | ||
|
|
21327ebe93 | ||
|
|
32416e380b | ||
|
|
4f76be1dc5 | ||
|
|
e271c1d3d0 | ||
|
|
b930a2a6be | ||
|
|
274b7ab123 | ||
|
|
8d367c7e66 | ||
|
|
42613c97d5 | ||
|
|
dcb14198bb | ||
|
|
38e8f282d2 | ||
|
|
2fd6f067db | ||
|
|
bec02998b4 | ||
|
|
8c7b6c05db | ||
|
|
9d7da11458 | ||
|
|
acbe4a1f32 | ||
|
|
89fbd1f11c | ||
|
|
9c80909452 | ||
|
|
eaf00a3a5d | ||
|
|
4d0c2b6cf4 | ||
|
|
ddb709e9de | ||
|
|
0e1be81a4a | ||
|
|
016178132e | ||
|
|
0689a7eb9c | ||
|
|
90489ae977 | ||
|
|
9c94bdac06 | ||
|
|
ddbddcb31e | ||
|
|
b5c1467a7d | ||
|
|
576b5efe93 | ||
|
|
c2cd13faa4 | ||
|
|
d93e5986d7 | ||
|
|
f78fd6f397 | ||
|
|
a65b53bf06 | ||
|
|
c3856bb011 | ||
|
|
a4d4403a75 | ||
|
|
4d1d94c56c | ||
|
|
4445434a2d | ||
|
|
61d8507140 | ||
|
|
382e9e25ff | ||
|
|
74d36d44f2 | ||
|
|
5fc3a0f707 | ||
|
|
6117afeeaa | ||
|
|
c7df832d7a | ||
|
|
1b4bd4c976 | ||
|
|
fc52af2736 | ||
|
|
29316f7bd0 | ||
|
|
3f37f20ddc | ||
|
|
e273c51287 | ||
|
|
6a60c64c6b | ||
|
|
3595b18793 | ||
|
|
5f38875807 | ||
|
|
af4da4be3d | ||
|
|
392d30f0de | ||
|
|
367f2873bc | ||
|
|
3588c91c7e | ||
|
|
7355f00756 | ||
|
|
286dbba2d2 | ||
|
|
f35c6c4fb9 | ||
|
|
9eb7fc5842 | ||
|
|
06707dd610 | ||
|
|
9c63fd8e76 | ||
|
|
8ef51cf15c | ||
|
|
41b2856bd4 | ||
|
|
e598b5b5c2 | ||
|
|
7181bda15d | ||
|
|
4c93f17e9e | ||
|
|
d011dc270a | ||
|
|
0d9556f948 | ||
|
|
4f6a85b3bd | ||
|
|
0eeb54cb89 | ||
|
|
ba7ba84f07 | ||
|
|
3dbe71bd35 | ||
|
|
661ca4136c | ||
|
|
f08ad34e0c | ||
|
|
d31e24aeaa | ||
|
|
b9b15578bb | ||
|
|
f29eaee30a | ||
|
|
e0adf13897 | ||
|
|
7b66ece1e5 | ||
|
|
e1c2163fb7 | ||
|
|
03fa53a640 | ||
|
|
a1755ec426 | ||
|
|
fde5c34bd8 | ||
|
|
ef8e821cf2 | ||
|
|
8cd98a9a26 | ||
|
|
ea2fda46c3 | ||
|
|
028ec224b8 | ||
|
|
d0377a70e2 | ||
|
|
1837696580 | ||
|
|
802bc904ba | ||
|
|
2eaeb17fe1 | ||
|
|
01cc7bf0c5 | ||
|
|
f31f7770d9 | ||
|
|
12217fb61d | ||
|
|
cd76166b4b | ||
|
|
680c3c8565 | ||
|
|
4c063c11ff | ||
|
|
0eca21c5fa | ||
|
|
cd24f37092 | ||
|
|
7c08c1a5df | ||
|
|
f498701444 | ||
|
|
bfd2ddfc47 | ||
|
|
bfe7cc638d | ||
|
|
52153a6e08 | ||
|
|
689b878c33 | ||
|
|
d5a52d9b3e | ||
|
|
2d57b561c2 | ||
|
|
9adab76e0a | ||
|
|
d710ed5b63 | ||
|
|
b958999af1 | ||
|
|
a259baa955 | ||
|
|
772351b0d5 | ||
|
|
9db9642db4 | ||
|
|
b9c078ea96 | ||
|
|
8f3f554053 | ||
|
|
12324c1693 | ||
|
|
bc8d832335 | ||
|
|
382b75f528 | ||
|
|
af1c6b93b7 | ||
|
|
9fd537965d | ||
|
|
65ce215641 | ||
|
|
c68c4bc7a4 | ||
|
|
b1093efa83 | ||
|
|
f09e8fcd33 | ||
|
|
bdab0cf58c | ||
|
|
5ebc168006 | ||
|
|
0050cf21ce | ||
|
|
e07c8e9123 | ||
|
|
1bcd3f26c0 | ||
|
|
9655d73f49 | ||
|
|
45beb88966 | ||
|
|
e422bebbdc | ||
|
|
579d011738 | ||
|
|
05fa0de6d8 | ||
|
|
92735bca31 | ||
|
|
22dfd73598 | ||
|
|
47753fa369 | ||
|
|
c3f95ef13f | ||
|
|
bdbfd2329a | ||
|
|
9c7722b7c5 | ||
|
|
cf78183fad | ||
|
|
de363e73ea | ||
|
|
331544bc37 | ||
|
|
b765385a3e | ||
|
|
0b886ad1bd | ||
|
|
e95568b78d | ||
|
|
fedd060d81 | ||
|
|
f51b175e3c | ||
|
|
a159d6caf0 | ||
|
|
4942b21203 | ||
|
|
ba1cdb6883 | ||
|
|
d9725378b0 | ||
|
|
f161a2c211 | ||
|
|
1a3dcca8f4 | ||
|
|
80cfc3a485 | ||
|
|
f39ab4c8d0 | ||
|
|
5c88e3c108 | ||
|
|
1954d40691 | ||
|
|
0e1d3551da | ||
|
|
cd58f05894 | ||
|
|
b4b7ed1915 | ||
|
|
5f2b41d54d | ||
|
|
c625ae04d2 | ||
|
|
e3bc569865 | ||
|
|
143acc7672 | ||
|
|
4a4a0c1196 | ||
|
|
a483c27704 | ||
|
|
a2168d94c0 | ||
|
|
7600e7fc39 | ||
|
|
ddd1ffb4f1 | ||
|
|
79f2525ab6 | ||
|
|
cc6dfd1f4b | ||
|
|
b86da2abe8 | ||
|
|
af3b5ea569 | ||
|
|
d5e7b61173 | ||
|
|
da9e86c3b6 | ||
|
|
fc4743faa8 | ||
|
|
336a0abbbb | ||
|
|
4d51be1cf3 | ||
|
|
d18f2fd9d6 | ||
|
|
de237cbfa4 | ||
|
|
3fcec0d4a0 | ||
|
|
b3a570d158 | ||
|
|
89a7bd644f | ||
|
|
30c8a40847 | ||
|
|
221497c61b | ||
|
|
8e2ebc0106 | ||
|
|
8765d20b1e | ||
|
|
10ffb45667 | ||
|
|
8555a3e3cc | ||
|
|
a108d3defb | ||
|
|
dabb95b892 | ||
|
|
63046fcf62 | ||
|
|
2d914f89fe | ||
|
|
1e7027b41e | ||
|
|
746f502a79 | ||
|
|
4b94f4e0ed | ||
|
|
0825aee8f4 | ||
|
|
a55ed9d5bb | ||
|
|
14486dc0e2 | ||
|
|
b2ce93fe16 | ||
|
|
c23b6fd688 | ||
|
|
82b0646988 | ||
|
|
94db8f97d4 | ||
|
|
4e56a62f72 | ||
|
|
d3bde4126c | ||
|
|
08344c735f | ||
|
|
1a85c0f506 | ||
|
|
c195ef0b5c | ||
|
|
06f4e33677 | ||
|
|
4fb6e53968 | ||
|
|
566f556c40 | ||
|
|
8ddc257a4b | ||
|
|
448f6b3d9b | ||
|
|
8911ac0b27 | ||
|
|
50bbdd4a1d | ||
|
|
92dfcea0e9 | ||
|
|
3171daef6c | ||
|
|
cafa8f2879 | ||
|
|
89c5c381b7 | ||
|
|
982f4fd301 | ||
|
|
797d0b231b | ||
|
|
9e98fe6f58 | ||
|
|
5951d9fe32 | ||
|
|
9b1b1a06a1 | ||
|
|
ae8ccfd24b | ||
|
|
198947c19f | ||
|
|
765654dae8 | ||
|
|
2c006b0b3e | ||
|
|
c5f90cd88b | ||
|
|
3a50cd2193 | ||
|
|
c995995eb8 | ||
|
|
2bc15836be | ||
|
|
319236afa2 | ||
|
|
026594e269 | ||
|
|
dc1e5ad191 | ||
|
|
3557f99cf5 | ||
|
|
3d88c9b4d3 | ||
|
|
44427fa833 | ||
|
|
3390014fd0 | ||
|
|
dd199d0ebd | ||
|
|
88bd012003 | ||
|
|
efdcf94174 | ||
|
|
381e87cbd2 | ||
|
|
4aaa4313e7 | ||
|
|
75578d60f3 | ||
|
|
68acc1b4cb | ||
|
|
8ce7915aad | ||
|
|
1be064190e | ||
|
|
f81e6f779b | ||
|
|
ffe47d6d5d | ||
|
|
0f460644e3 | ||
|
|
b49f1398a1 | ||
|
|
3c726dd3c0 | ||
|
|
814efd6f1f | ||
|
|
e6bc9c35f3 | ||
|
|
06e0e1c853 | ||
|
|
b5029b87c8 | ||
|
|
a823faecf1 | ||
|
|
0ecbd46fe7 | ||
|
|
05a85b2b38 | ||
|
|
3c83387c29 | ||
|
|
c1aed4eff4 | ||
|
|
6986c779f0 | ||
|
|
2e53709f17 | ||
|
|
a9d811a976 | ||
|
|
e0e54740b1 | ||
|
|
c555400ca1 | ||
|
|
29c8fb0d93 | ||
|
|
986a78979e | ||
|
|
7543a5611b | ||
|
|
701e1f5254 | ||
|
|
ebeafe5b0b | ||
|
|
c32ad4594e | ||
|
|
6892cb056d | ||
|
|
50c85be6fc | ||
|
|
0a9972bf1b | ||
|
|
895191b9a8 | ||
|
|
b8dcb38b4e | ||
|
|
f00ffc6c00 | ||
|
|
f5a3dbea40 | ||
|
|
2acfa219aa | ||
|
|
64c0020ff8 | ||
|
|
6fe375c3bd | ||
|
|
12e5881c09 | ||
|
|
26227db843 | ||
|
|
951f7d35d6 | ||
|
|
fb4dbbd188 | ||
|
|
0bf30d2b33 | ||
|
|
23cdae18f0 | ||
|
|
ff4be740b5 | ||
|
|
4f620dd0f0 | ||
|
|
ec9a3c04ed | ||
|
|
222ac2b12a | ||
|
|
5dc6e7067c | ||
|
|
90d95b6323 | ||
|
|
63f319353c | ||
|
|
b2848bf08a | ||
|
|
bb583e3c11 | ||
|
|
7a161e4847 | ||
|
|
3bd1d6645e | ||
|
|
339eb29a87 | ||
|
|
1376a542b4 | ||
|
|
fa914f1dda | ||
|
|
a7f82808c4 | ||
|
|
a76552ce47 | ||
|
|
134cb634b1 | ||
|
|
1d915d0237 | ||
|
|
e3132693fa | ||
|
|
100f189c25 | ||
|
|
4b76541c25 | ||
|
|
f00a0dcfed | ||
|
|
07becec31c | ||
|
|
1854433829 | ||
|
|
5f2e4b0565 | ||
|
|
e47bd0195c | ||
|
|
c93236b564 | ||
|
|
3c3666d67e | ||
|
|
18871d4785 | ||
|
|
ce2f66d9bf | ||
|
|
d67badd9ce | ||
|
|
ab0d6428b1 | ||
|
|
d47afc7f4c | ||
|
|
c95d9a9482 | ||
|
|
41c938eede | ||
|
|
ce652affe0 | ||
|
|
14ad993895 | ||
|
|
92f6fb4cfa | ||
|
|
36fe96581f | ||
|
|
b277b0f100 | ||
|
|
304ca95508 | ||
|
|
9f46ab62b1 | ||
|
|
96931d6f78 | ||
|
|
f04f24503d | ||
|
|
1c009d622d | ||
|
|
6cc409c24b | ||
|
|
07f1bb0d60 | ||
|
|
1f915e418c | ||
|
|
1290914b37 | ||
|
|
d0c0706042 | ||
|
|
dbb0a12366 | ||
|
|
916b11fba5 | ||
|
|
b9a33a61a0 | ||
|
|
56d673675d | ||
|
|
81ccec4042 | ||
|
|
771ffb5e28 | ||
|
|
639b61d78e | ||
|
|
4a7d53ee23 | ||
|
|
144bfd9c53 | ||
|
|
a04030d30f | ||
|
|
45aa01fe89 | ||
|
|
3dbca25b69 | ||
|
|
dae7fff12e | ||
|
|
ff20f32338 | ||
|
|
e4b4f2d532 | ||
|
|
fd28283707 | ||
|
|
bc4fb165ea | ||
|
|
8e66454df9 | ||
|
|
b42adfe052 | ||
|
|
30d509c12e | ||
|
|
2e00b8fbd9 | ||
|
|
148e107da6 | ||
|
|
fbf99a9cdc | ||
|
|
232393e3bd | ||
|
|
4060d64fc9 | ||
|
|
ddadf791f1 | ||
|
|
7bf9a64538 | ||
|
|
ea53f183fc | ||
|
|
6ece1d747e | ||
|
|
c7441658da | ||
|
|
9af3c3c824 | ||
|
|
0e3947ef32 | ||
|
|
0ba5bacd0c | ||
|
|
b19811d5f4 | ||
|
|
249856d557 | ||
|
|
520198138a | ||
|
|
08492c952b | ||
|
|
9502ee3b5f | ||
|
|
5c83f797c5 | ||
|
|
2a919e396d | ||
|
|
dae3e10a5a | ||
|
|
47894585ae | ||
|
|
a75b45fcd3 | ||
|
|
e65f25d54e | ||
|
|
33a656c4ae | ||
|
|
e3a9bc79a0 | ||
|
|
59d0486f2f | ||
|
|
000f217369 | ||
|
|
7083cc3083 | ||
|
|
f1830a9a22 | ||
|
|
927c00255b | ||
|
|
580f7cd731 | ||
|
|
fb7ca33178 | ||
|
|
cf6ab20d8b | ||
|
|
a1816267e6 | ||
|
|
d477028247 | ||
|
|
46761b339c | ||
|
|
26199789ed | ||
|
|
ee29ad27b3 | ||
|
|
19920202cc | ||
|
|
46dbdebb59 | ||
|
|
a0cbcfd6ed | ||
|
|
ccf2e853a1 | ||
|
|
04ae8e1a1b | ||
|
|
971a6e53a1 | ||
|
|
04d4c0e444 | ||
|
|
3edb53eeed | ||
|
|
90712378a7 | ||
|
|
6d6995bc83 | ||
|
|
d2ee96d88f | ||
|
|
34709a786c | ||
|
|
6e3a1a3742 | ||
|
|
698b9f3095 | ||
|
|
50fc02d063 | ||
|
|
dab9fa7f91 | ||
|
|
b47d2bc164 | ||
|
|
6c83a8419b | ||
|
|
a2709fad7f | ||
|
|
899d373b3c | ||
|
|
34420d655d | ||
|
|
9a6ab7f142 | ||
|
|
fe70b09c42 | ||
|
|
8a05341cf5 | ||
|
|
24154ed64b | ||
|
|
31b581bcac | ||
|
|
f77654a0e9 | ||
|
|
96929a5515 | ||
|
|
c729dbb6d2 | ||
|
|
613389019e | ||
|
|
c6494d82fa | ||
|
|
3898609304 | ||
|
|
3ee48ba20a | ||
|
|
4d9c55da72 | ||
|
|
b7506b302d | ||
|
|
90c838da9f | ||
|
|
812392d325 | ||
|
|
467b79391f | ||
|
|
da1103f4f8 | ||
|
|
19521acfa4 | ||
|
|
18e8e43715 | ||
|
|
6d6c2afb2b | ||
|
|
3c3cb60a90 | ||
|
|
eca96d7118 | ||
|
|
7790f391ab | ||
|
|
b5ec1da9e9 | ||
|
|
eb9a21afed | ||
|
|
3a906d45dc | ||
|
|
ac8d2b1df7 | ||
|
|
0f5d4c6e88 | ||
|
|
1006f0707e | ||
|
|
a590aae017 | ||
|
|
e749405297 | ||
|
|
70ab73a008 | ||
|
|
5fa83965f2 | ||
|
|
1b71f82e38 | ||
|
|
460d878613 | ||
|
|
4e97a9d9eb | ||
|
|
7cf3d2ccb9 | ||
|
|
18c4beb05b | ||
|
|
7f1de3fec8 | ||
|
|
e75acc006e | ||
|
|
abbb9a829c | ||
|
|
6c88568fef | ||
|
|
4a52c187d3 | ||
|
|
9d6cd04b3b | ||
|
|
bcf0f41171 | ||
|
|
a95a0ab569 | ||
|
|
2943f60811 | ||
|
|
8a6ea5d687 | ||
|
|
3563824c60 | ||
|
|
82ec7d5542 | ||
|
|
2849d0661d | ||
|
|
1282c8653e | ||
|
|
160eb23b0e | ||
|
|
e4ebe82ee2 | ||
|
|
6cef700203 | ||
|
|
a8c20ea946 | ||
|
|
d887f54494 | ||
|
|
5b14622110 | ||
|
|
ad25804feb | ||
|
|
415a87ef36 | ||
|
|
817ee0d826 | ||
|
|
0ae2ac5431 | ||
|
|
983e4bdef0 | ||
|
|
3948eb0c54 | ||
|
|
d789a3f140 | ||
|
|
863e995b79 | ||
|
|
54ce3bad64 | ||
|
|
d077dd2a6e | ||
|
|
70f7f00385 | ||
|
|
d62a1947be | ||
|
|
d07eaba195 | ||
|
|
cb1fcde2f4 | ||
|
|
e6332751c6 | ||
|
|
25d5c19522 | ||
|
|
a3869547e5 | ||
|
|
e0be8da392 | ||
|
|
c4c99ade65 | ||
|
|
d89f06c1ae | ||
|
|
a08e182698 | ||
|
|
9700f212ad | ||
|
|
fdfdb5cd7d | ||
|
|
a3d12f445a | ||
|
|
13829c6c99 | ||
|
|
b768a38b76 | ||
|
|
fad2231f86 | ||
|
|
3023e782bd | ||
|
|
b199f7547f | ||
|
|
01473c3f40 | ||
|
|
ce1a071f6d | ||
|
|
c3def40293 | ||
|
|
0783bcceef | ||
|
|
d65e959bae | ||
|
|
219abac227 | ||
|
|
70f6049f71 | ||
|
|
703db97d80 | ||
|
|
229c34f818 | ||
|
|
c283b3c569 | ||
|
|
451c3957fe | ||
|
|
16d5671943 | ||
|
|
4c6b210af0 | ||
|
|
0f5a2a82d9 | ||
|
|
b0d9f41cd2 | ||
|
|
7ff54e08aa | ||
|
|
c5532e188e | ||
|
|
7596a030c6 | ||
|
|
506bf85de5 | ||
|
|
0969343320 | ||
|
|
fa57170187 | ||
|
|
550c73f4c8 | ||
|
|
baf814f3da | ||
|
|
8b7b3be765 | ||
|
|
5204ca87e2 | ||
|
|
2bbfcd2d02 | ||
|
|
432d28d3bb | ||
|
|
896899e0d6 | ||
|
|
a54d2118be | ||
|
|
8ce04527f9 | ||
|
|
6062de265a | ||
|
|
3bbb49de55 | ||
|
|
e0873dafc5 | ||
|
|
07368a9e3c | ||
|
|
ad5f29b743 | ||
|
|
1d42878adb | ||
|
|
39471861d5 | ||
|
|
d354f94241 | ||
|
|
fab7858a35 | ||
|
|
133bc2e5f0 | ||
|
|
0ce74bfaa5 | ||
|
|
b0e508a0c0 | ||
|
|
5cd2a640a5 | ||
|
|
194ea3186a | ||
|
|
c971112dfa | ||
|
|
c4971e24f9 | ||
|
|
1e8aeae15a | ||
|
|
7d72a8c36a | ||
|
|
d59bce21e5 | ||
|
|
641cfb1456 | ||
|
|
64d46e7c6a | ||
|
|
0f10b21719 | ||
|
|
f5f2d7410d | ||
|
|
93b7af3099 | ||
|
|
7a98f19fb6 | ||
|
|
d518e444f8 | ||
|
|
b5782531ad | ||
|
|
7d1490576d | ||
|
|
1bdc992a59 | ||
|
|
15094f7654 | ||
|
|
66654ab02e | ||
|
|
44c89996c8 | ||
|
|
c4443c2be1 | ||
|
|
c4879a0c2f | ||
|
|
609046df6a | ||
|
|
c17e60e270 | ||
|
|
992a2e2e79 | ||
|
|
d2e6dd6c99 | ||
|
|
d4b2f3c45b | ||
|
|
9b1732baae | ||
|
|
12718ce767 | ||
|
|
de29f9b444 | ||
|
|
e5ad8de2d9 | ||
|
|
2842fe4aa3 | ||
|
|
b6ef8d5a40 | ||
|
|
9247134eab | ||
|
|
993928cfcc | ||
|
|
59e0f445ce | ||
|
|
883a310904 | ||
|
|
b065976007 | ||
|
|
40d23dafb7 | ||
|
|
11f73c728a | ||
|
|
0ed0806bb4 | ||
|
|
1b7cd74a49 | ||
|
|
31ac53fbdc | ||
|
|
43346904e1 | ||
|
|
afdd59416e | ||
|
|
4d009243cb | ||
|
|
45268208ae | ||
|
|
618b250e34 | ||
|
|
b69dd08ae7 | ||
|
|
4e16306ae3 | ||
|
|
46e06b875d | ||
|
|
831f59ce8b | ||
|
|
d650f96d5f | ||
|
|
4ce190a015 | ||
|
|
e333ab56d5 | ||
|
|
9b0369c773 | ||
|
|
9f46a3e32a | ||
|
|
371f9616e9 | ||
|
|
2976a52222 | ||
|
|
8f6111bb9c | ||
|
|
882ba0e752 | ||
|
|
88d7bc930a | ||
|
|
1c85a7f3eb | ||
|
|
5d6b30271f | ||
|
|
8103b0bb62 | ||
|
|
98474d3d6f | ||
|
|
ea7582bb41 | ||
|
|
10b45b4c2e | ||
|
|
78e851f94f | ||
|
|
587f929c64 | ||
|
|
50fac68654 | ||
|
|
407e20c11a | ||
|
|
10ed8178fc | ||
|
|
e69a797990 | ||
|
|
f6521b66f7 | ||
|
|
a2bd31432f | ||
|
|
20cb17e1f9 | ||
|
|
3cd01fdf0e | ||
|
|
a52c7a1b65 | ||
|
|
1e07068adf | ||
|
|
c87c8cd163 | ||
|
|
248bceb30c | ||
|
|
feeb761ba0 | ||
|
|
4e6e3293ff | ||
|
|
325e5c3ef0 | ||
|
|
787f5e9949 | ||
|
|
8fdb7e108f | ||
|
|
fbf9df2ea3 | ||
|
|
7cc2ceae09 | ||
|
|
a0780ba08a | ||
|
|
43b6dafa6e | ||
|
|
c1ecab818c | ||
|
|
914dc01222 | ||
|
|
6b8a17119e | ||
|
|
1025440184 | ||
|
|
fd61d6f506 | ||
|
|
f04017f702 | ||
|
|
b92095f18c | ||
|
|
2ae4ad004a | ||
|
|
ec9c902133 | ||
|
|
bd09334d1a | ||
|
|
8e154e4d74 | ||
|
|
480d44bd0b | ||
|
|
429039d45d | ||
|
|
8956453c0d | ||
|
|
976c08b68a | ||
|
|
dbd9c486bb | ||
|
|
33d7d93298 | ||
|
|
41c6b8abc6 | ||
|
|
9ac282ca0c | ||
|
|
7a99821377 | ||
|
|
f9189543bf | ||
|
|
f29f242758 | ||
|
|
0134a1c08c | ||
|
|
5d0f7c4f47 | ||
|
|
fa638ec8af | ||
|
|
78eb2789b2 | ||
|
|
8fe791e4e2 | ||
|
|
f94b64c2f3 | ||
|
|
acf513cfe7 | ||
|
|
d1edab602a | ||
|
|
b06f9c1364 | ||
|
|
43d16f0361 | ||
|
|
d0e4051cd8 | ||
|
|
09cec19e2f | ||
|
|
eef7c4a773 | ||
|
|
ea591ead85 | ||
|
|
7b671f52e0 | ||
|
|
63407fd6e2 | ||
|
|
bc5053d93e | ||
|
|
ce7896070c | ||
|
|
25047eb3e9 | ||
|
|
7d80d2e3d7 | ||
|
|
3b9473afa2 | ||
|
|
ce4cc630c2 | ||
|
|
9c137aaccf | ||
|
|
46784d0826 | ||
|
|
6e86c4700b | ||
|
|
4dfbc78a88 | ||
|
|
5a8398e55a | ||
|
|
239c11d0dd | ||
|
|
0832c0d166 | ||
|
|
ab1b288fa7 | ||
|
|
fe4a655042 | ||
|
|
563f3efda3 | ||
|
|
6f3b919ae1 | ||
|
|
01ecb074a7 | ||
|
|
ffe8b77a61 | ||
|
|
94e34fa0ad | ||
|
|
8b1202c52c | ||
|
|
24b57e3c6a | ||
|
|
cd9696fc97 | ||
|
|
b52a270538 | ||
|
|
00fb08158d | ||
|
|
cde87ee75c | ||
|
|
bd795bd543 | ||
|
|
973ca019bc | ||
|
|
23e5c5b11a | ||
|
|
e3f72a3555 | ||
|
|
8a6a35e9d9 | ||
|
|
394b9298fa | ||
|
|
29875dcb4b | ||
|
|
9af080c351 | ||
|
|
fea25712ca | ||
|
|
ff0ee876bb | ||
|
|
d6615a54c6 | ||
|
|
660ff174f2 | ||
|
|
62922c8ab0 | ||
|
|
4add41a2a6 | ||
|
|
7a15109c04 | ||
|
|
77b99cf7ad | ||
|
|
3a25a2b9b0 | ||
|
|
a3b4caac38 | ||
|
|
4a9130aca2 | ||
|
|
320fe1015a | ||
|
|
47f48a658d | ||
|
|
6d64a0bfed | ||
|
|
6c513a45d5 | ||
|
|
f9dd136a09 | ||
|
|
c0a360ce49 | ||
|
|
757cec9ddd | ||
|
|
53d0e6dd6a | ||
|
|
f4ac41806a | ||
|
|
f0fc95a143 | ||
|
|
83e047eaa7 | ||
|
|
f718aedd9f | ||
|
|
096e06dbb5 | ||
|
|
c26f3a9bd1 | ||
|
|
f1e7570755 | ||
|
|
8ece75aee1 | ||
|
|
985302c7cc | ||
|
|
7563424f32 | ||
|
|
ae2fe472c3 | ||
|
|
0ec6e88048 | ||
|
|
1d764d631f | ||
|
|
8c35bfbadf | ||
|
|
1844b2fdb4 | ||
|
|
0c7fd94585 | ||
|
|
5f9861953e | ||
|
|
cf2f7c30a3 | ||
|
|
d17ac27a72 | ||
|
|
b56843b253 | ||
|
|
e54f330239 | ||
|
|
8b4d653663 | ||
|
|
928d3a011c | ||
|
|
768e5d52fb | ||
|
|
49232d1abf | ||
|
|
5026891d75 | ||
|
|
adc704563c | ||
|
|
d44ac73925 | ||
|
|
746ea6bd86 | ||
|
|
462f5d98a2 | ||
|
|
cd8c905dfe | ||
|
|
a7d45c5a7a | ||
|
|
385f730f31 | ||
|
|
790fe2e558 | ||
|
|
34aa3112c8 | ||
|
|
2643ce97ae | ||
|
|
20f19893cb | ||
|
|
8892579f8b | ||
|
|
5849bd472a | ||
|
|
62e0453ce0 | ||
|
|
bb361cc644 | ||
|
|
7dc04f4091 | ||
|
|
29b79e4c0e | ||
|
|
a6f18e4686 | ||
|
|
5a060b8dc8 | ||
|
|
91dace35a1 | ||
|
|
55bb0cfbb6 | ||
|
|
0f1707de67 | ||
|
|
966ae00fe4 | ||
|
|
0071a540d4 | ||
|
|
0fb78eae34 | ||
|
|
fe78c9ae8b | ||
|
|
ca81464697 | ||
|
|
09b4e26a44 | ||
|
|
524843af01 | ||
|
|
4843b55fd1 | ||
|
|
a3957d089a | ||
|
|
5b36c0336f | ||
|
|
28d257da11 | ||
|
|
51ce20d5da | ||
|
|
9f5b11e6fd | ||
|
|
5e794a9ab7 | ||
|
|
1653f97c8f | ||
|
|
8f737d28a6 | ||
|
|
9fc0a15cd4 | ||
|
|
0985816bf6 | ||
|
|
af4006b3f5 | ||
|
|
b07ea7c74b | ||
|
|
ac7c7ab99a | ||
|
|
67d4cbab46 | ||
|
|
82f66082b9 | ||
|
|
3986a05c62 | ||
|
|
6da3b29e37 | ||
|
|
99fdc1d829 | ||
|
|
df1a110d2e | ||
|
|
80af836ce0 | ||
|
|
6f7d45a323 | ||
|
|
22db3f2c77 | ||
|
|
5a3cb32e59 | ||
|
|
ea933b03b4 | ||
|
|
139d2f7c29 | ||
|
|
89b5616d10 | ||
|
|
45dcf63a62 | ||
|
|
a6cd0b08f6 | ||
|
|
85a2229264 | ||
|
|
5e19030aa1 | ||
|
|
4dca553e66 | ||
|
|
ae744c8b78 | ||
|
|
c6aa86afc2 | ||
|
|
839c4e7966 | ||
|
|
d960a335f8 | ||
|
|
3ef1f41550 | ||
|
|
97ec4e50b1 | ||
|
|
591b5c0f41 | ||
|
|
55f19cb809 | ||
|
|
a24ea3dab7 | ||
|
|
bc05562730 | ||
|
|
4830ff923e | ||
|
|
ffd8060a98 | ||
|
|
661834d02b | ||
|
|
9dfa3c3e04 | ||
|
|
46667ba3e4 | ||
|
|
8bb9660baa | ||
|
|
a3878873f3 | ||
|
|
c05271901a | ||
|
|
d2f7778cc7 | ||
|
|
875f71d4ef | ||
|
|
b34c5f3c0f | ||
|
|
7f3ccb59da | ||
|
|
eb793429f1 | ||
|
|
5456ef3092 | ||
|
|
c59abe2589 | ||
|
|
271f9faf9e | ||
|
|
0c587936c7 | ||
|
|
2692ed3f01 | ||
|
|
23f59e7023 | ||
|
|
37244c2f7f | ||
|
|
8f10a28890 | ||
|
|
7fa4443f77 | ||
|
|
457754d2c2 | ||
|
|
c5b3ffd8d5 | ||
|
|
623b987813 | ||
|
|
090e5b40f1 | ||
|
|
d32148567f | ||
|
|
23aa78c405 | ||
|
|
97521b5257 | ||
|
|
66331f2b51 | ||
|
|
1f5a7cef6f | ||
|
|
a8fef7f569 | ||
|
|
5e7c4f3be8 | ||
|
|
58b01afc50 | ||
|
|
508471bbc0 | ||
|
|
4d3dda5d9f | ||
|
|
b66737e6df | ||
|
|
b8a5e30d91 | ||
|
|
f93727aa56 | ||
|
|
c485a0636e | ||
|
|
e0feedd7ac | ||
|
|
33a53bc13b | ||
|
|
133dce6a37 | ||
|
|
81c45c0a94 | ||
|
|
840470ec79 | ||
|
|
5d21ffe16b | ||
|
|
037a8daee6 | ||
|
|
a2de039ec4 | ||
|
|
5d53f48acb | ||
|
|
e6fd96f054 | ||
|
|
5146599b01 | ||
|
|
b354251f1a | ||
|
|
9245ff5705 | ||
|
|
1eb2d8e0bf | ||
|
|
0981b80c29 | ||
|
|
bfbfb53ed4 | ||
|
|
b84172434d | ||
|
|
9d9aae0396 | ||
|
|
11b729d8a2 | ||
|
|
d54e6e8359 | ||
|
|
2abbe5fc88 | ||
|
|
1ad3b7d5c0 | ||
|
|
d285c7bf2c | ||
|
|
2e767410b8 | ||
|
|
c164396ddc | ||
|
|
92dca80975 | ||
|
|
11353b0c57 | ||
|
|
3e468840bd | ||
|
|
e17018adcd | ||
|
|
3b6ed2294b | ||
|
|
50a3855082 | ||
|
|
9e11cb53dd | ||
|
|
5ac114c756 | ||
|
|
6ddf861078 | ||
|
|
6bdb06a7b1 | ||
|
|
2ea78ec7fd | ||
|
|
09570add5f | ||
|
|
f621326c24 | ||
|
|
781fc2c8c0 | ||
|
|
1302257e5d | ||
|
|
96c5269511 | ||
|
|
e9205293bd | ||
|
|
203f9e6c00 | ||
|
|
82ab06b849 | ||
|
|
ab89d75daf | ||
|
|
2387a7a969 | ||
|
|
7e63dc3615 | ||
|
|
74335bd32a | ||
|
|
d4e09300f3 | ||
|
|
a2ea797593 | ||
|
|
2f1dca645b | ||
|
|
f1ae31d8af | ||
|
|
fa8cc47c4f | ||
|
|
a5f95d75a1 | ||
|
|
1f7e0e51aa | ||
|
|
1ef3a48c03 | ||
|
|
356c3cad1a | ||
|
|
28bddf4590 | ||
|
|
3d0a83aeb2 | ||
|
|
f49d4f0e93 | ||
|
|
7d5bb42946 | ||
|
|
46692fc929 | ||
|
|
6860133373 | ||
|
|
52d4975825 | ||
|
|
4295311da3 | ||
|
|
0e69fc6e84 | ||
|
|
46f552a9fe | ||
|
|
4fdc8a62d0 | ||
|
|
5b8def797c | ||
|
|
bd1aabe941 | ||
|
|
56f1e91239 | ||
|
|
29a86a1735 | ||
|
|
82e6b92b0a | ||
|
|
46c08874aa | ||
|
|
7b74bd4928 | ||
|
|
dd62ca1b29 | ||
|
|
d7d7d81a6a | ||
|
|
6ad47ddf40 | ||
|
|
092522af6c | ||
|
|
bdef43dde7 | ||
|
|
e400258bf0 | ||
|
|
460c51fdad | ||
|
|
3793fa09ff | ||
|
|
c8a3917089 | ||
|
|
4c9183e8bb | ||
|
|
6672400206 | ||
|
|
1f6f261ace | ||
|
|
393a0edc51 | ||
|
|
3118d11d88 | ||
|
|
d0ccf0c755 | ||
|
|
19b6958cfd | ||
|
|
39857190de | ||
|
|
478b01d9a7 | ||
|
|
9bab521df8 | ||
|
|
a012e2db59 | ||
|
|
933f2715d8 | ||
|
|
60a87bce87 | ||
|
|
dab7acdf45 | ||
|
|
86c47a5636 | ||
|
|
65c2ad687f | ||
|
|
234db30d66 | ||
|
|
024fa1cb44 | ||
|
|
061a001590 | ||
|
|
10ab9c2f42 | ||
|
|
24de922636 | ||
|
|
aab1f950aa | ||
|
|
1d740055da | ||
|
|
c73ba23eb5 | ||
|
|
75b6323200 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,7 +2,6 @@ src/*.exe
|
||||
src/bitcoin
|
||||
src/bitcoind
|
||||
src/test_bitcoin
|
||||
src/build.h
|
||||
.*.swp
|
||||
*.*~*
|
||||
*.bak
|
||||
|
||||
4
INSTALL
4
INSTALL
@@ -1,9 +1,9 @@
|
||||
Building Bitcoin
|
||||
|
||||
See doc/readme-qt.rst for instructions on building Bitcoin QT,
|
||||
See doc/readme-qt.rst for instructions on building Bitcoin-Qt,
|
||||
the intended-for-end-users, nice-graphical-interface, reference
|
||||
implementation of Bitcoin.
|
||||
|
||||
See doc/build-*.txt for instructions on building bitcoind,
|
||||
the intended-for-services, no-graphical-interface, reference
|
||||
implementation of Bitcoin.
|
||||
implementation of Bitcoin.
|
||||
103
bitcoin-qt.pro
103
bitcoin-qt.pro
@@ -1,19 +1,20 @@
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
VERSION = 0.6.3.0
|
||||
TARGET = bitcoin-qt
|
||||
VERSION = 0.7.2
|
||||
INCLUDEPATH += src src/json src/qt
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
|
||||
CONFIG += no_include_pwd
|
||||
CONFIG += thread
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
# use: qmake BOOST_LIB_SUFFIX=-mt
|
||||
# for boost thread win32 with _win32 sufix
|
||||
# use: BOOST_THREAD_LIB_SUFFIX=_win32-...
|
||||
# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-4.8
|
||||
|
||||
# Dependency library locations can be customized with BOOST_INCLUDE_PATH,
|
||||
# BOOST_LIB_PATH, BDB_INCLUDE_PATH, BDB_LIB_PATH
|
||||
# OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively
|
||||
# Dependency library locations can be customized with:
|
||||
# BOOST_INCLUDE_PATH, BOOST_LIB_PATH, BDB_INCLUDE_PATH,
|
||||
# BDB_LIB_PATH, OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively
|
||||
|
||||
OBJECTS_DIR = build
|
||||
MOC_DIR = build
|
||||
@@ -30,6 +31,16 @@ contains(RELEASE, 1) {
|
||||
}
|
||||
}
|
||||
|
||||
!win32 {
|
||||
# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection
|
||||
QMAKE_CXXFLAGS *= -fstack-protector-all --param ssp-buffer-size=1
|
||||
QMAKE_LFLAGS *= -fstack-protector-all --param ssp-buffer-size=1
|
||||
# We need to exclude this for Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable!
|
||||
# This can be enabled for Windows, when we switch to MinGW >= 4.4.x.
|
||||
}
|
||||
# for extra security on Windows: enable ASLR and DEP via GCC linker flags
|
||||
win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat
|
||||
|
||||
# use: qmake "USE_QRCODE=1"
|
||||
# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
|
||||
contains(USE_QRCODE, 1) {
|
||||
@@ -62,10 +73,16 @@ contains(USE_DBUS, 1) {
|
||||
QT += dbus
|
||||
}
|
||||
|
||||
# use: qmake "FIRST_CLASS_MESSAGING=1"
|
||||
contains(FIRST_CLASS_MESSAGING, 1) {
|
||||
message(Building with first-class messaging)
|
||||
DEFINES += FIRST_CLASS_MESSAGING
|
||||
# use: qmake "USE_IPV6=1" ( enabled by default; default)
|
||||
# or: qmake "USE_IPV6=0" (disabled by default)
|
||||
# or: qmake "USE_IPV6=-" (not supported)
|
||||
contains(USE_IPV6, -) {
|
||||
message(Building without IPv6 support)
|
||||
} else {
|
||||
count(USE_IPV6, 0) {
|
||||
USE_IPV6=1
|
||||
}
|
||||
DEFINES += USE_IPV6=$$USE_IPV6
|
||||
}
|
||||
|
||||
contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
@@ -73,24 +90,18 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
|
||||
}
|
||||
|
||||
!windows {
|
||||
# for extra security against potential buffer overflows
|
||||
QMAKE_CXXFLAGS += -fstack-protector
|
||||
QMAKE_LFLAGS += -fstack-protector
|
||||
# do not enable this on windows, as it will result in a non-working executable!
|
||||
}
|
||||
|
||||
# regenerate src/build.h
|
||||
!windows || contains(USE_BUILD_INFO, 1) {
|
||||
!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
|
||||
genbuild.target = $$OUT_PWD/build/build.h
|
||||
PRE_TARGETDEPS += $$OUT_PWD/build/build.h
|
||||
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
|
||||
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector
|
||||
|
||||
# Input
|
||||
DEPENDPATH += src src/json src/qt
|
||||
@@ -100,15 +111,17 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/optionsdialog.h \
|
||||
src/qt/sendcoinsdialog.h \
|
||||
src/qt/addressbookpage.h \
|
||||
src/qt/messagepage.h \
|
||||
src/qt/signverifymessagedialog.h \
|
||||
src/qt/aboutdialog.h \
|
||||
src/qt/editaddressdialog.h \
|
||||
src/qt/bitcoinaddressvalidator.h \
|
||||
src/alert.h \
|
||||
src/addrman.h \
|
||||
src/base58.h \
|
||||
src/bignum.h \
|
||||
src/checkpoints.h \
|
||||
src/compat.h \
|
||||
src/sync.h \
|
||||
src/util.h \
|
||||
src/uint256.h \
|
||||
src/serialize.h \
|
||||
@@ -158,7 +171,11 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/notificator.h \
|
||||
src/qt/qtipcserver.h \
|
||||
src/allocators.h \
|
||||
src/ui_interface.h
|
||||
src/ui_interface.h \
|
||||
src/qt/rpcconsole.h \
|
||||
src/version.h \
|
||||
src/netbase.h \
|
||||
src/clientversion.h
|
||||
|
||||
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/transactiontablemodel.cpp \
|
||||
@@ -166,11 +183,13 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/optionsdialog.cpp \
|
||||
src/qt/sendcoinsdialog.cpp \
|
||||
src/qt/addressbookpage.cpp \
|
||||
src/qt/messagepage.cpp \
|
||||
src/qt/signverifymessagedialog.cpp \
|
||||
src/qt/aboutdialog.cpp \
|
||||
src/qt/editaddressdialog.cpp \
|
||||
src/qt/bitcoinaddressvalidator.cpp \
|
||||
src/alert.cpp \
|
||||
src/version.cpp \
|
||||
src/sync.cpp \
|
||||
src/util.cpp \
|
||||
src/netbase.cpp \
|
||||
src/key.cpp \
|
||||
@@ -183,9 +202,6 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.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 \
|
||||
src/qt/clientmodel.cpp \
|
||||
src/qt/guiutil.cpp \
|
||||
src/qt/transactionrecord.cpp \
|
||||
@@ -202,6 +218,11 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/walletmodel.cpp \
|
||||
src/bitcoinrpc.cpp \
|
||||
src/rpcdump.cpp \
|
||||
src/rpcnet.cpp \
|
||||
src/rpcmining.cpp \
|
||||
src/rpcwallet.cpp \
|
||||
src/rpcblockchain.cpp \
|
||||
src/rpcrawtransaction.cpp \
|
||||
src/qt/overviewpage.cpp \
|
||||
src/qt/csvmodelwriter.cpp \
|
||||
src/crypter.cpp \
|
||||
@@ -212,7 +233,9 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/askpassphrasedialog.cpp \
|
||||
src/protocol.cpp \
|
||||
src/qt/notificator.cpp \
|
||||
src/qt/qtipcserver.cpp
|
||||
src/qt/qtipcserver.cpp \
|
||||
src/qt/rpcconsole.cpp \
|
||||
src/noui.cpp
|
||||
|
||||
RESOURCES += \
|
||||
src/qt/bitcoin.qrc
|
||||
@@ -220,13 +243,15 @@ RESOURCES += \
|
||||
FORMS += \
|
||||
src/qt/forms/sendcoinsdialog.ui \
|
||||
src/qt/forms/addressbookpage.ui \
|
||||
src/qt/forms/messagepage.ui \
|
||||
src/qt/forms/signverifymessagedialog.ui \
|
||||
src/qt/forms/aboutdialog.ui \
|
||||
src/qt/forms/editaddressdialog.ui \
|
||||
src/qt/forms/transactiondescdialog.ui \
|
||||
src/qt/forms/overviewpage.ui \
|
||||
src/qt/forms/sendcoinsentry.ui \
|
||||
src/qt/forms/askpassphrasedialog.ui
|
||||
src/qt/forms/askpassphrasedialog.ui \
|
||||
src/qt/forms/rpcconsole.ui \
|
||||
src/qt/forms/optionsdialog.ui
|
||||
|
||||
contains(USE_QRCODE, 1) {
|
||||
HEADERS += src/qt/qrcodedialog.h
|
||||
@@ -254,24 +279,23 @@ isEmpty(QMAKE_LRELEASE) {
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
}
|
||||
isEmpty(TS_DIR):TS_DIR = src/qt/locale
|
||||
isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale
|
||||
# automatically build translations, so they can be included in resource file
|
||||
TSQM.name = lrelease ${QMAKE_FILE_IN}
|
||||
TSQM.input = TRANSLATIONS
|
||||
TSQM.output = $$TS_DIR/${QMAKE_FILE_BASE}.qm
|
||||
TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN}
|
||||
TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm
|
||||
TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
|
||||
TSQM.CONFIG = no_link
|
||||
QMAKE_EXTRA_COMPILERS += TSQM
|
||||
PRE_TARGETDEPS += compiler_TSQM_make_all
|
||||
|
||||
# "Other files" to show in Qt Creator
|
||||
OTHER_FILES += \
|
||||
doc/*.rst doc/*.txt doc/README README.md res/bitcoin-qt.rc
|
||||
doc/*.rst doc/*.txt doc/README README.md res/bitcoin-qt.rc src/test/*.cpp src/test/*.h src/qt/test/*.cpp src/qt/test/*.h
|
||||
|
||||
# platform specific defaults, if not overridden on command line
|
||||
isEmpty(BOOST_LIB_SUFFIX) {
|
||||
macx:BOOST_LIB_SUFFIX = -mt
|
||||
windows:BOOST_LIB_SUFFIX = -mgw44-mt-1_43
|
||||
windows:BOOST_LIB_SUFFIX = -mgw44-mt-s-1_50
|
||||
}
|
||||
|
||||
isEmpty(BOOST_THREAD_LIB_SUFFIX) {
|
||||
@@ -298,7 +322,6 @@ isEmpty(BOOST_INCLUDE_PATH) {
|
||||
macx:BOOST_INCLUDE_PATH = /opt/local/include
|
||||
}
|
||||
|
||||
windows:LIBS += -lws2_32 -lshlwapi
|
||||
windows:DEFINES += WIN32
|
||||
windows:RC_FILE = src/qt/res/bitcoin-qt.rc
|
||||
|
||||
@@ -313,7 +336,7 @@ windows:!contains(MINGW_THREAD_BUGFIX, 0) {
|
||||
QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY
|
||||
}
|
||||
|
||||
!windows:!mac {
|
||||
!windows:!macx {
|
||||
DEFINES += LINUX
|
||||
LIBS += -lrt
|
||||
}
|
||||
@@ -324,14 +347,18 @@ macx:LIBS += -framework Foundation -framework ApplicationServices -framework App
|
||||
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
|
||||
macx:ICON = src/qt/res/icons/bitcoin.icns
|
||||
macx:TARGET = "Bitcoin-Qt"
|
||||
macx:QMAKE_CFLAGS_THREAD += -pthread
|
||||
macx:QMAKE_LFLAGS_THREAD += -pthread
|
||||
macx:QMAKE_CXXFLAGS_THREAD += -pthread
|
||||
|
||||
# Set libraries and includes at end, to use platform-defined defaults if not overridden
|
||||
INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
|
||||
LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
|
||||
LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX
|
||||
# -lgdi32 has to happen after -lcrypto (see #681)
|
||||
windows:LIBS += -lole32 -luuid -lgdi32
|
||||
windows:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32
|
||||
LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
|
||||
windows:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
|
||||
|
||||
contains(RELEASE, 1) {
|
||||
!windows:!macx {
|
||||
|
||||
115
contrib/bitcoind.bash-completion
Normal file
115
contrib/bitcoind.bash-completion
Normal file
@@ -0,0 +1,115 @@
|
||||
# bash programmable completion for bitcoind(1)
|
||||
# Copyright (c) 2012 Christian von Roques <roques@mti.ag>
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
have bitcoind && {
|
||||
|
||||
# call $bitcoind for RPC
|
||||
_bitcoin_rpc() {
|
||||
# determine already specified args necessary for RPC
|
||||
local rpcargs=()
|
||||
for i in ${COMP_LINE}; do
|
||||
case "$i" in
|
||||
-conf=*|-proxy*|-rpc*)
|
||||
rpcargs=( "${rpcargs[@]}" "$i" )
|
||||
;;
|
||||
esac
|
||||
done
|
||||
$bitcoind "${rpcargs[@]}" "$@"
|
||||
}
|
||||
|
||||
# Add bitcoin accounts to COMPREPLY
|
||||
_bitcoin_accounts() {
|
||||
local accounts
|
||||
accounts=$(_bitcoin_rpc listaccounts | awk '/".*"/ { a=$1; gsub(/"/, "", a); print a}')
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) )
|
||||
}
|
||||
|
||||
_bitcoind() {
|
||||
local cur prev words=() cword
|
||||
local bitcoind
|
||||
|
||||
# save and use original argument to invoke bitcoind
|
||||
# bitcoind might not be in $PATH
|
||||
bitcoind="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_get_comp_words_by_ref -n = cur prev words cword
|
||||
|
||||
if ((cword > 2)); then
|
||||
case ${words[cword-2]} in
|
||||
listreceivedbyaccount|listreceivedbyaddress)
|
||||
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
|
||||
return 0
|
||||
;;
|
||||
move|setaccount)
|
||||
_bitcoin_accounts
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
case "$prev" in
|
||||
backupwallet)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
setgenerate)
|
||||
COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
|
||||
return 0
|
||||
;;
|
||||
getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany)
|
||||
_bitcoin_accounts
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$cur" in
|
||||
-conf=*|-pid=*|-rpcsslcertificatechainfile=*|-rpcsslprivatekeyfile=*)
|
||||
cur="${cur#*=}"
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
-datadir=*)
|
||||
cur="${cur#*=}"
|
||||
_filedir -d
|
||||
return 0
|
||||
;;
|
||||
-*=*) # prevent nonsense completions
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
local helpopts commands
|
||||
|
||||
# only parse --help if senseful
|
||||
if [[ -z "$cur" || "$cur" =~ ^- ]]; then
|
||||
helpopts=$($bitcoind --help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' )
|
||||
fi
|
||||
|
||||
# only parse help if senseful
|
||||
if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then
|
||||
commands=$(_bitcoin_rpc help 2>/dev/null | awk '{ print $1; }')
|
||||
fi
|
||||
|
||||
COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) )
|
||||
|
||||
# Prevent space if an argument is desired
|
||||
if [[ $COMPREPLY == *= ]]; then
|
||||
compopt -o nospace
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _bitcoind bitcoind
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# mode: shell-script
|
||||
# sh-basic-offset: 4
|
||||
# sh-indent-comment: t
|
||||
# indent-tabs-mode: nil
|
||||
# End:
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
umask 077
|
||||
|
||||
basedir=~/.bitcoin
|
||||
dbfile="$basedir/DB_CONFIG"
|
||||
cfgfile="$basedir/bitcoin.conf"
|
||||
|
||||
[ -e "$basedir" ] || mkdir "$basedir"
|
||||
|
||||
# Bitcoin does not clean up DB log files by default
|
||||
[ -e "$dbfile" ] || echo 'set_flags DB_LOG_AUTOREMOVE' > "$dbfile"
|
||||
|
||||
exec /usr/lib/bitcoin/bitcoin-qt "$@"
|
||||
@@ -5,14 +5,10 @@ set -e
|
||||
umask 077
|
||||
|
||||
basedir=~/.bitcoin
|
||||
dbfile="$basedir/DB_CONFIG"
|
||||
cfgfile="$basedir/bitcoin.conf"
|
||||
|
||||
[ -e "$basedir" ] || mkdir "$basedir"
|
||||
|
||||
[ -e "$cfgfile" ] || perl -le 'print"rpcpassword=",map{(a..z,A..Z,0..9)[rand 62]}0..9' > "$cfgfile"
|
||||
|
||||
# Bitcoin does not clean up DB log files by default
|
||||
[ -e "$dbfile" ] || echo 'set_flags DB_LOG_AUTOREMOVE' > "$dbfile"
|
||||
|
||||
exec /usr/lib/bitcoin/bitcoind "$@"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
debian/bin/bitcoin-qt usr/bin
|
||||
bitcoin-qt usr/lib/bitcoin
|
||||
bitcoin-qt usr/bin
|
||||
share/pixmaps/bitcoin32.xpm usr/share/pixmaps
|
||||
share/pixmaps/bitcoin80.xpm usr/share/pixmaps
|
||||
debian/bitcoin-qt.desktop usr/share/applications
|
||||
|
||||
1
contrib/debian/bitcoind.bash-completion
Normal file
1
contrib/debian/bitcoind.bash-completion
Normal file
@@ -0,0 +1 @@
|
||||
contrib/bitcoind.bash-completion bitcoind
|
||||
@@ -1,13 +1,61 @@
|
||||
bitcoin (0.5.1-natty1) natty; urgency=low
|
||||
bitcoin (0.6.3-natty1) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Mon, 25 Jun 2012 23:47:00 +0200
|
||||
|
||||
bitcoin (0.6.2-natty1) natty; urgency=low
|
||||
|
||||
* Update package description and launch scripts.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Sat, 2 Jun 2012 16:41:00 +0200
|
||||
|
||||
bitcoin (0.6.2-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Tue, 8 May 2012 16:27:00 -0500
|
||||
|
||||
bitcoin (0.6.1-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Sun, 6 May 2012 20:09:00 -0500
|
||||
|
||||
bitcoin (0.6.0-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Add GNOME/KDE support for bitcoin-qt's bitcoin: URI support.
|
||||
Thanks to luke-jr for the KDE .protocol file.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Sat, 31 Mar 2012 15:35:00 -0500
|
||||
|
||||
bitcoin (0.5.3-natty1) natty; urgency=low
|
||||
|
||||
* Mark for upload to PPA.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Wed, 14 Mar 2012 23:06:00 -0400
|
||||
|
||||
bitcoin (0.5.3-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Tue, 10 Jan 2012 15:57:00 -0500
|
||||
|
||||
bitcoin (0.5.2-natty1) natty; urgency=low
|
||||
|
||||
* Remove mentions on anonymity in package descriptions and manpage.
|
||||
These should never have been there, bitcoin isnt anonymous without
|
||||
a ton of work that virtually no users will ever be willing and
|
||||
capable of doing
|
||||
* Add GNOME/KDE support for bitcoin-qt's bitcoin: URI support.
|
||||
Thanks to luke-jr for the KDE .protocol file.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Fri, 23 Dec 2011 20:25:00 -0500
|
||||
-- Matt Corallo <matt@bluematt.me> Sat, 7 Jan 2012 13:37:00 -0500
|
||||
|
||||
bitcoin (0.5.2-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Luke Dashjr <luke+bitcoin+deb@dashjr.org> Fri, 16 Dec 2011 17:57:00 -0500
|
||||
|
||||
bitcoin (0.5.1-natty0) natty; urgency=low
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ Maintainer: Jonas Smedegaard <dr@jones.dk>
|
||||
Uploaders: Micah Anderson <micah@debian.org>
|
||||
Build-Depends: debhelper,
|
||||
devscripts,
|
||||
bash-completion,
|
||||
libboost-system-dev (>> 1.35) | libboost-system1.35-dev,
|
||||
libdb4.8++-dev,
|
||||
libssl-dev,
|
||||
@@ -43,7 +44,7 @@ Description: peer-to-peer network based digital currency - daemon
|
||||
Package: bitcoin-qt
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: peer-to-peer network based digital currency - QT GUI
|
||||
Description: peer-to-peer network based digital currency - Qt GUI
|
||||
Bitcoin is a free open source peer-to-peer electronic cash system that
|
||||
is completely decentralized, without the need for a central server or
|
||||
trusted parties. Users hold the crypto keys to their own money and
|
||||
@@ -55,4 +56,4 @@ Description: peer-to-peer network based digital currency - QT GUI
|
||||
Full transaction history is stored locally at each client. This
|
||||
requires 2+ GB of space, slowly growing.
|
||||
.
|
||||
This package provides bitcoin-qt, a GUI for Bitcoin based on QT.
|
||||
This package provides Bitcoin-Qt, a GUI for Bitcoin based on Qt.
|
||||
|
||||
@@ -6,7 +6,7 @@ Source: http://sourceforge.net/projects/bitcoin/files/
|
||||
https://github.com/bitcoin/bitcoin
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2011, Bitcoin Developers
|
||||
Copyright: 2009-2012, Bitcoin Developers
|
||||
License: Expat
|
||||
Comment: The Bitcoin Developers encompasses the current developers listed on bitcoin.org,
|
||||
as well as the numerous contributors to the project.
|
||||
@@ -55,9 +55,8 @@ Comment: Icon Pack: Human-O2
|
||||
|
||||
Files: src/qt/res/icons/transaction*.png
|
||||
Copyright: md2k7
|
||||
License: You are free to do with these icons as you wish, including selling,
|
||||
copying, modifying etc.
|
||||
Comment: Site: https://forum.bitcoin.org/index.php?topic=15276.0
|
||||
License: Expat
|
||||
Comment: Site: https://bitcointalk.org/index.php?topic=15276.0
|
||||
|
||||
Files: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png,
|
||||
src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png,
|
||||
@@ -70,7 +69,7 @@ Comment: Icon Pack: Crystal SVG
|
||||
Files: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png
|
||||
Copyright: Bitboy (optimized for 16x16 by Wladimir van der Laan)
|
||||
License: PUB-DOM
|
||||
Comment: Site: http://forum.bitcoin.org/?topic=1756.0
|
||||
Comment: Site: https://bitcointalk.org/?topic=1756.0
|
||||
|
||||
Files: scripts/img/reload.xcf, src/qt/res/movies/update_spinner.mng
|
||||
Copyright: Everaldo (Everaldo Coelho)
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
Description: Use system JSON Spirit library
|
||||
Author: Jonas Smedegaard <dr@jones.dk>
|
||||
Last-Update: 2011-05-17
|
||||
--- a/src/rpc.cpp
|
||||
+++ b/src/rpc.cpp
|
||||
@@ -12,9 +12,7 @@
|
||||
#include <boost/asio/ssl.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"
|
||||
+#include <json_spirit.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
|
||||
--- a/src/makefile.unix
|
||||
+++ b/src/makefile.unix
|
||||
@@ -23,6 +23,7 @@
|
||||
-l boost_thread \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
+ -l json_spirit \
|
||||
-l crypto
|
||||
|
||||
ifdef USE_UPNP
|
||||
@@ -1 +1 @@
|
||||
#1001_use_system_json-spirit.patch
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ DEB_INSTALL_EXAMPLES_bitcoind += debian/examples/*
|
||||
DEB_INSTALL_MANPAGES_bitcoind += debian/manpages/*
|
||||
|
||||
%:
|
||||
dh $@
|
||||
dh --with bash-completion $@
|
||||
|
||||
override_dh_auto_build:
|
||||
cd src; $(MAKE) -f makefile.unix bitcoind
|
||||
|
||||
@@ -1,31 +1,86 @@
|
||||
Gavin's notes on getting gitian builds up and running:
|
||||
Gavin's notes on getting gitian builds up and running using KVM:
|
||||
|
||||
These instructions distilled from:
|
||||
https://help.ubuntu.com/community/KVM/Installation
|
||||
... see there for complete details.
|
||||
|
||||
You need the right hardware: you need a 64-bit-capable CPU with hardware virtualization support (Intel VT-x or AMD-V). Not all modern CPUs support hardware virtualization.
|
||||
|
||||
You probably need to enable hardware virtualization in your machine's BIOS.
|
||||
|
||||
You need to be running a recent version of 64-bit-Ubuntu, and you need to install several prerequisites:
|
||||
sudo apt-get install apache2 git apt-cacher-ng python-vm-builder qemu-kvm
|
||||
sudo apt-get install ruby apache2 git apt-cacher-ng python-vm-builder qemu-kvm
|
||||
|
||||
Sanity checks:
|
||||
sudo service apt-cacher-ng status # Should return apt-cacher-ng is running
|
||||
ls -l /dev/kvm # Should show a /dev/kvm device
|
||||
|
||||
|
||||
Once you've got the right hardware and software:
|
||||
|
||||
git clone git://github.com/bitcoin/bitcoin.git
|
||||
git clone git://github.com/devrandom/gitian-builder.git
|
||||
mkdir gitian-builder/inputs
|
||||
wget 'http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.6.tar.gz' -O gitian-builder/inputs/miniupnpc-1.6.tar.gz
|
||||
cd gitian-builder/inputs
|
||||
# Inputs for Linux and Win32:
|
||||
wget -O miniupnpc-1.6.tar.gz 'http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.6.tar.gz'
|
||||
wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
|
||||
# Inputs for Win32: (Linux has packages for these)
|
||||
wget 'https://downloads.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2'
|
||||
wget 'http://www.openssl.org/source/openssl-1.0.1c.tar.gz'
|
||||
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
|
||||
wget 'https://downloads.sourceforge.net/project/libpng/zlib/1.2.6/zlib-1.2.6.tar.gz'
|
||||
wget 'https://downloads.sourceforge.net/project/libpng/libpng15/older-releases/1.5.9/libpng-1.5.9.tar.gz'
|
||||
wget 'http://releases.qt-project.org/qt4/source/qt-everywhere-opensource-src-4.8.2.tar.gz'
|
||||
cd ../..
|
||||
|
||||
cd gitian-builder
|
||||
bin/make-base-vm --arch i386
|
||||
bin/make-base-vm --arch amd64
|
||||
cd ..
|
||||
|
||||
# To build
|
||||
# Build Linux release:
|
||||
cd bitcoin
|
||||
git pull
|
||||
cd ../gitian-builder
|
||||
git pull
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian.yml
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
|
||||
# Build Win32 dependencies: (only needs to be done once, or when dependency versions change)
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian-descriptors/boost-win32.yml
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian-descriptors/deps-win32.yml
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
|
||||
|
||||
# Build Win32 release:
|
||||
./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
|
||||
|
||||
---------------------
|
||||
|
||||
gitian-builder now also supports building using LXC. See
|
||||
https://help.ubuntu.com/12.04/serverguide/lxc.html
|
||||
... for how to get LXC up and running under Ubuntu.
|
||||
|
||||
If your main machine is a 64-bit Mac or PC with a few gigabytes of memory
|
||||
and at least 10 gigabytes of free disk space, you can gitian-build using
|
||||
LXC running inside a virtual machine.
|
||||
|
||||
Here's a description of Gavin's setup on OSX 10.6:
|
||||
|
||||
1. Download and install VirtualBox from https://www.virtualbox.org/
|
||||
|
||||
2. Download the 64-bit Ubuntu Desktop 12.04 LTS .iso CD image from
|
||||
http://www.ubuntu.com/
|
||||
|
||||
3. Run VirtualBox and create a new virtual machine, using the
|
||||
Ubuntu .iso (see the VirtualBox documentation for details).
|
||||
Create it with at least 2 gigabytes of memory and a disk
|
||||
that is at least 20 gigabytes big.
|
||||
|
||||
4. Inside the running Ubuntu desktop, install:
|
||||
sudo apt-get install debootstrap lxc ruby apache2 git apt-cacher-ng python-vm-builder
|
||||
|
||||
5. Still inside Ubuntu, tell gitian-builder to use LXC, then follow the "Once you've got the right
|
||||
hardware and software" instructions above:
|
||||
export USE_LXC=1
|
||||
git clone git://github.com/bitcoin/bitcoin.git
|
||||
... etc
|
||||
|
||||
@@ -11,12 +11,12 @@ packages:
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes: []
|
||||
files:
|
||||
- "boost_1_47_0.tar.bz2"
|
||||
- "boost_1_50_0.tar.bz2"
|
||||
script: |
|
||||
TMPDIR="$HOME/tmpdir"
|
||||
mkdir -p $TMPDIR/bin/$GBUILD_BITS $TMPDIR/include
|
||||
tar xjf boost_1_47_0.tar.bz2
|
||||
cd boost_1_47_0
|
||||
tar xjf boost_1_50_0.tar.bz2
|
||||
cd boost_1_50_0
|
||||
echo "using gcc : 4.4 : i586-mingw32msvc-g++
|
||||
:
|
||||
<rc>i586-mingw32msvc-windres
|
||||
@@ -34,5 +34,5 @@ script: |
|
||||
cd $TMPDIR
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
zip -r boost-win32-1.47.0-gitian.zip *
|
||||
cp boost-win32-1.47.0-gitian.zip $OUTDIR
|
||||
zip -r boost-win32-1.50.0-gitian2.zip *
|
||||
cp boost-win32-1.50.0-gitian2.zip $OUTDIR
|
||||
|
||||
@@ -4,7 +4,7 @@ suites:
|
||||
- "lucid"
|
||||
architectures:
|
||||
- "i386"
|
||||
packages:
|
||||
packages:
|
||||
- "mingw32"
|
||||
- "git-core"
|
||||
- "zip"
|
||||
@@ -13,7 +13,7 @@ packages:
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes: []
|
||||
files:
|
||||
- "openssl-1.0.1b.tar.gz"
|
||||
- "openssl-1.0.1c.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.1b.tar.gz
|
||||
cd openssl-1.0.1b
|
||||
tar xzf openssl-1.0.1c.tar.gz
|
||||
cd openssl-1.0.1c
|
||||
./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
|
||||
make
|
||||
cd ..
|
||||
@@ -62,7 +62,7 @@ script: |
|
||||
make $MAKEOPTS
|
||||
cd ..
|
||||
#
|
||||
zip -r $OUTDIR/bitcoin-deps-0.0.4.zip \
|
||||
zip -r $OUTDIR/bitcoin-deps-0.0.5.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) \
|
||||
|
||||
@@ -4,7 +4,7 @@ suites:
|
||||
- "lucid"
|
||||
architectures:
|
||||
- "i386"
|
||||
packages:
|
||||
packages:
|
||||
- "mingw32"
|
||||
- "git-core"
|
||||
- "unzip"
|
||||
@@ -15,21 +15,21 @@ remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
"dir": "bitcoin"
|
||||
files:
|
||||
- "qt-win32-4.7.4-gitian.zip"
|
||||
- "boost-win32-1.47.0-gitian.zip"
|
||||
- "bitcoin-deps-0.0.4.zip"
|
||||
- "qt-win32-4.8.2-gitian-r1.zip"
|
||||
- "boost-win32-1.50.0-gitian2.zip"
|
||||
- "bitcoin-deps-0.0.5.zip"
|
||||
script: |
|
||||
#
|
||||
mkdir $HOME/qt
|
||||
cd $HOME/qt
|
||||
unzip ../build/qt-win32-4.7.4-gitian.zip
|
||||
unzip ../build/qt-win32-4.8.2-gitian-r1.zip
|
||||
cd $HOME/build/
|
||||
export PATH=$PATH:$HOME/qt/bin/
|
||||
#
|
||||
mkdir boost_1_47_0
|
||||
cd boost_1_47_0
|
||||
mkdir boost_1_50_0
|
||||
cd boost_1_50_0
|
||||
mkdir -p stage/lib
|
||||
unzip ../boost-win32-1.47.0-gitian.zip
|
||||
unzip ../boost-win32-1.50.0-gitian2.zip
|
||||
cd bin/$GBUILD_BITS
|
||||
for lib in *; do
|
||||
i586-mingw32msvc-ar rc ../../stage/lib/libboost_${lib}-mt-s.a $lib/*.o
|
||||
@@ -39,7 +39,7 @@ script: |
|
||||
mv include/boost .
|
||||
cd ..
|
||||
#
|
||||
unzip bitcoin-deps-0.0.4.zip
|
||||
unzip bitcoin-deps-0.0.5.zip
|
||||
#
|
||||
find -type f | xargs touch --date="$REFERENCE_DATETIME"
|
||||
#
|
||||
@@ -47,11 +47,11 @@ script: |
|
||||
mkdir -p $OUTDIR/src
|
||||
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
|
||||
cp $OUTDIR/src/COPYING $OUTDIR/COPYING.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 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
|
||||
$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_50_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_50_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1c OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1c/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/
|
||||
#
|
||||
|
||||
@@ -11,15 +11,15 @@ packages:
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes: []
|
||||
files:
|
||||
- "qt-everywhere-opensource-src-4.7.4.tar.gz"
|
||||
- "qt-everywhere-opensource-src-4.8.2.tar.gz"
|
||||
script: |
|
||||
INSTDIR="$HOME/qt/"
|
||||
mkdir $INSTDIR
|
||||
SRCDIR="$INSTDIR/src/"
|
||||
mkdir $SRCDIR
|
||||
#
|
||||
tar xzf qt-everywhere-opensource-src-4.7.4.tar.gz
|
||||
cd qt-everywhere-opensource-src-4.7.4
|
||||
tar xzf qt-everywhere-opensource-src-4.8.2.tar.gz
|
||||
cd qt-everywhere-opensource-src-4.8.2
|
||||
sed 's/$TODAY/2011-01-30/' -i configure
|
||||
sed 's/i686-pc-mingw32-/i586-mingw32msvc-/' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
|
||||
sed --posix 's|QMAKE_CFLAGS\t\t= -pipe|QMAKE_CFLAGS\t\t= -pipe -isystem /usr/i586-mingw32msvc/include/ -frandom-seed=qtbuild|' -i mkspecs/unsupported/win32-g++-cross/qmake.conf
|
||||
@@ -40,7 +40,7 @@ script: |
|
||||
#export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
./configure -prefix $INSTDIR -confirm-license -release -opensource -static -no-qt3support -xplatform unsupported/win32-g++-cross -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -opengl no -nomake examples -nomake demos -nomake docs
|
||||
./configure -prefix $INSTDIR -confirm-license -release -opensource -static -no-qt3support -xplatform unsupported/win32-g++-cross -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -no-opengl -nomake examples -nomake demos -nomake docs -no-feature-style-plastique -no-feature-style-cleanlooks -no-feature-style-motif -no-feature-style-cde -no-feature-style-windowsce -no-feature-style-windowsmobile -no-feature-style-s60
|
||||
find . -name *.prl | xargs -l sed 's|/\.||' -i
|
||||
find . -name *.prl | xargs -l sed 's|/$||' -i
|
||||
make $MAKEOPTS install
|
||||
@@ -51,4 +51,4 @@ script: |
|
||||
|
||||
# as zip stores file timestamps, use faketime to intercept stat calls to set dates for all files to reference date
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
zip -r $OUTDIR/qt-win32-4.7.4-gitian.zip *
|
||||
zip -r $OUTDIR/qt-win32-4.8.2-gitian-r1.zip *
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -169,6 +169,9 @@ class DeploymentInfo(object):
|
||||
elif os.path.exists(os.path.join(parentDir, "share", "qt4", "translations")):
|
||||
# MacPorts layout, e.g. "/opt/local/share/qt4"
|
||||
self.qtPath = os.path.join(parentDir, "share", "qt4")
|
||||
elif os.path.exists(os.path.join(os.path.dirname(parentDir), "share", "qt4", "translations")):
|
||||
# Newer Macports layout
|
||||
self.qtPath = os.path.join(os.path.dirname(parentDir), "share", "qt4")
|
||||
|
||||
if self.qtPath is not None:
|
||||
pluginPath = os.path.join(self.qtPath, "plugins")
|
||||
@@ -725,7 +728,7 @@ if config.dmg is not None:
|
||||
disk.close()
|
||||
if bg_path is not None:
|
||||
subprocess.call(["SetFile", "-a", "V", bg_path])
|
||||
disk.update(registering_applications=False)
|
||||
# disk.update(registering_applications=False)
|
||||
sleep(2)
|
||||
disk.eject()
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Copyright (c) 2011 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.
|
||||
#
|
||||
|
||||
import time
|
||||
|
||||
1
contrib/testgen/README
Normal file
1
contrib/testgen/README
Normal file
@@ -0,0 +1 @@
|
||||
Utilities to generate test vectors for the data-driven Bitcoin tests
|
||||
104
contrib/testgen/base58.py
Normal file
104
contrib/testgen/base58.py
Normal file
@@ -0,0 +1,104 @@
|
||||
'''
|
||||
Bitcoin base58 encoding and decoding.
|
||||
|
||||
Based on https://bitcointalk.org/index.php?topic=1026.0 (public domain)
|
||||
'''
|
||||
import hashlib
|
||||
|
||||
# for compatibility with following code...
|
||||
class SHA256:
|
||||
new = hashlib.sha256
|
||||
|
||||
if str != bytes:
|
||||
# Python 3.x
|
||||
def ord(c):
|
||||
return c
|
||||
def chr(n):
|
||||
return bytes( (n,) )
|
||||
|
||||
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
__b58base = len(__b58chars)
|
||||
b58chars = __b58chars
|
||||
|
||||
def b58encode(v):
|
||||
""" encode v, which is a string of bytes, to base58.
|
||||
"""
|
||||
long_value = 0
|
||||
for (i, c) in enumerate(v[::-1]):
|
||||
long_value += (256**i) * ord(c)
|
||||
|
||||
result = ''
|
||||
while long_value >= __b58base:
|
||||
div, mod = divmod(long_value, __b58base)
|
||||
result = __b58chars[mod] + result
|
||||
long_value = div
|
||||
result = __b58chars[long_value] + result
|
||||
|
||||
# Bitcoin does a little leading-zero-compression:
|
||||
# leading 0-bytes in the input become leading-1s
|
||||
nPad = 0
|
||||
for c in v:
|
||||
if c == '\0': nPad += 1
|
||||
else: break
|
||||
|
||||
return (__b58chars[0]*nPad) + result
|
||||
|
||||
def b58decode(v, length = None):
|
||||
""" decode v into a string of len bytes
|
||||
"""
|
||||
long_value = 0
|
||||
for (i, c) in enumerate(v[::-1]):
|
||||
long_value += __b58chars.find(c) * (__b58base**i)
|
||||
|
||||
result = bytes()
|
||||
while long_value >= 256:
|
||||
div, mod = divmod(long_value, 256)
|
||||
result = chr(mod) + result
|
||||
long_value = div
|
||||
result = chr(long_value) + result
|
||||
|
||||
nPad = 0
|
||||
for c in v:
|
||||
if c == __b58chars[0]: nPad += 1
|
||||
else: break
|
||||
|
||||
result = chr(0)*nPad + result
|
||||
if length is not None and len(result) != length:
|
||||
return None
|
||||
|
||||
return result
|
||||
|
||||
def checksum(v):
|
||||
"""Return 32-bit checksum based on SHA256"""
|
||||
return SHA256.new(SHA256.new(v).digest()).digest()[0:4]
|
||||
|
||||
def b58encode_chk(v):
|
||||
"""b58encode a string, with 32-bit checksum"""
|
||||
return b58encode(v + checksum(v))
|
||||
|
||||
def b58decode_chk(v):
|
||||
"""decode a base58 string, check and remove checksum"""
|
||||
result = b58decode(v)
|
||||
if result is None:
|
||||
return None
|
||||
h3 = checksum(result[:-4])
|
||||
if result[-4:] == checksum(result[:-4]):
|
||||
return result[:-4]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_bcaddress_version(strAddress):
|
||||
""" Returns None if strAddress is invalid. Otherwise returns integer version of address. """
|
||||
addr = b58decode_chk(strAddress)
|
||||
if addr is None or len(addr)!=21: return None
|
||||
version = addr[0]
|
||||
return ord(version)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Test case (from http://gitorious.org/bitcoin/python-base58.git)
|
||||
assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') is 0
|
||||
_ohai = 'o hai'.encode('ascii')
|
||||
_tmp = b58encode(_ohai)
|
||||
assert _tmp == 'DYB3oMS'
|
||||
assert b58decode(_tmp, 5) == _ohai
|
||||
print("Tests passed")
|
||||
126
contrib/testgen/gen_base58_test_vectors.py
Executable file
126
contrib/testgen/gen_base58_test_vectors.py
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Generate valid and invalid base58 address and private key test vectors.
|
||||
|
||||
Usage:
|
||||
gen_base58_test_vectors.py valid 50 > ../../src/test/data/base58_keys_valid.json
|
||||
gen_base58_test_vectors.py invalid 50 > ../../src/test/data/base58_keys_invalid.json
|
||||
'''
|
||||
# 2012 Wladimir J. van der Laan
|
||||
# Released under MIT License
|
||||
import os
|
||||
from itertools import islice
|
||||
from base58 import b58encode, b58decode, b58encode_chk, b58decode_chk, b58chars
|
||||
import random
|
||||
from binascii import b2a_hex
|
||||
|
||||
# key types
|
||||
PUBKEY_ADDRESS = 0
|
||||
SCRIPT_ADDRESS = 5
|
||||
PUBKEY_ADDRESS_TEST = 111
|
||||
SCRIPT_ADDRESS_TEST = 196
|
||||
PRIVKEY = 128
|
||||
PRIVKEY_TEST = 239
|
||||
|
||||
metadata_keys = ['isPrivkey', 'isTestnet', 'addrType', 'isCompressed']
|
||||
# templates for valid sequences
|
||||
templates = [
|
||||
# prefix, payload_size, suffix, metadata
|
||||
# None = N/A
|
||||
((PUBKEY_ADDRESS,), 20, (), (False, False, 'pubkey', None)),
|
||||
((SCRIPT_ADDRESS,), 20, (), (False, False, 'script', None)),
|
||||
((PUBKEY_ADDRESS_TEST,), 20, (), (False, True, 'pubkey', None)),
|
||||
((SCRIPT_ADDRESS_TEST,), 20, (), (False, True, 'script', None)),
|
||||
((PRIVKEY,), 32, (), (True, False, None, False)),
|
||||
((PRIVKEY,), 32, (1,), (True, False, None, True)),
|
||||
((PRIVKEY_TEST,), 32, (), (True, True, None, False)),
|
||||
((PRIVKEY_TEST,), 32, (1,), (True, True, None, True))
|
||||
]
|
||||
|
||||
def is_valid(v):
|
||||
'''Check vector v for validity'''
|
||||
result = b58decode_chk(v)
|
||||
if result is None:
|
||||
return False
|
||||
valid = False
|
||||
for template in templates:
|
||||
prefix = str(bytearray(template[0]))
|
||||
suffix = str(bytearray(template[2]))
|
||||
if result.startswith(prefix) and result.endswith(suffix):
|
||||
if (len(result) - len(prefix) - len(suffix)) == template[1]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def gen_valid_vectors():
|
||||
'''Generate valid test vectors'''
|
||||
while True:
|
||||
for template in templates:
|
||||
prefix = str(bytearray(template[0]))
|
||||
payload = os.urandom(template[1])
|
||||
suffix = str(bytearray(template[2]))
|
||||
rv = b58encode_chk(prefix + payload + suffix)
|
||||
assert is_valid(rv)
|
||||
metadata = dict([(x,y) for (x,y) in zip(metadata_keys,template[3]) if y is not None])
|
||||
yield (rv, b2a_hex(payload), metadata)
|
||||
|
||||
def gen_invalid_vector(template, corrupt_prefix, randomize_payload_size, corrupt_suffix):
|
||||
'''Generate possibly invalid vector'''
|
||||
if corrupt_prefix:
|
||||
prefix = os.urandom(1)
|
||||
else:
|
||||
prefix = str(bytearray(template[0]))
|
||||
|
||||
if randomize_payload_size:
|
||||
payload = os.urandom(max(int(random.expovariate(0.5)), 50))
|
||||
else:
|
||||
payload = os.urandom(template[1])
|
||||
|
||||
if corrupt_suffix:
|
||||
suffix = os.urandom(len(template[2]))
|
||||
else:
|
||||
suffix = str(bytearray(template[2]))
|
||||
|
||||
return b58encode_chk(prefix + payload + suffix)
|
||||
|
||||
def randbool(p = 0.5):
|
||||
'''Return True with P(p)'''
|
||||
return random.random() < p
|
||||
|
||||
def gen_invalid_vectors():
|
||||
'''Generate invalid test vectors'''
|
||||
# start with some manual edge-cases
|
||||
yield "",
|
||||
yield "x",
|
||||
while True:
|
||||
# kinds of invalid vectors:
|
||||
# invalid prefix
|
||||
# invalid payload length
|
||||
# invalid (randomized) suffix (add random data)
|
||||
# corrupt checksum
|
||||
for template in templates:
|
||||
val = gen_invalid_vector(template, randbool(0.2), randbool(0.2), randbool(0.2))
|
||||
if random.randint(0,10)<1: # line corruption
|
||||
if randbool(): # add random character to end
|
||||
val += random.choice(b58chars)
|
||||
else: # replace random character in the middle
|
||||
n = random.randint(0, len(val))
|
||||
val = val[0:n] + random.choice(b58chars) + val[n+1:]
|
||||
if not is_valid(val):
|
||||
yield val,
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys, json
|
||||
iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors}
|
||||
try:
|
||||
uiter = iters[sys.argv[1]]
|
||||
except IndexError:
|
||||
uiter = gen_valid_vectors
|
||||
try:
|
||||
count = int(sys.argv[2])
|
||||
except IndexError:
|
||||
count = 0
|
||||
|
||||
data = list(islice(uiter(), count))
|
||||
json.dump(data, sys.stdout, sort_keys=True, indent=4)
|
||||
sys.stdout.write('\n')
|
||||
|
||||
@@ -203,7 +203,7 @@ TAB_SIZE = 8
|
||||
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
|
||||
# put the command \sideeffect (or @sideeffect) in the documentation, which
|
||||
# will result in a user-defined paragraph with heading "Side Effects:".
|
||||
# You can put \n's in the value part of an alias to insert newlines.
|
||||
# You can put \n in the value part of an alias to insert newlines.
|
||||
|
||||
ALIASES =
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Bitcoin 0.6.3 BETA
|
||||
Bitcoin 0.7.2 BETA
|
||||
|
||||
Copyright (c) 2009-2012 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.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com).
|
||||
@@ -18,7 +18,7 @@ with each other, with the help of a P2P network to check for double-spending.
|
||||
|
||||
Setup
|
||||
-----
|
||||
You need the Qt4 run-time libraries to run bitcoin-qt. On Debian or Ubuntu:
|
||||
You need the Qt4 run-time libraries to run Bitcoin-Qt. On Debian or Ubuntu:
|
||||
sudo apt-get install libqtgui4
|
||||
|
||||
Unpack the files into a directory and run:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Bitcoin 0.6.3 BETA
|
||||
Bitcoin 0.7.2 BETA
|
||||
|
||||
Copyright (c) 2009-2012 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.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com).
|
||||
|
||||
92
doc/Tor.txt
Normal file
92
doc/Tor.txt
Normal file
@@ -0,0 +1,92 @@
|
||||
TOR SUPPORT IN BITCOIN
|
||||
======================
|
||||
|
||||
It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
|
||||
|
||||
The following assumes you have a Tor proxy running on port 9050. Many distributions
|
||||
default to having a SOCKS proxy listening on port 9050, but others may not.
|
||||
In particular, the Tor Browser Bundle defaults to listening on a random port. See
|
||||
https://www.torproject.org/docs/faq.html.en#TBBSocksPort for how to properly
|
||||
configure Tor.
|
||||
|
||||
|
||||
1. Run bitcoin behind a Tor proxy
|
||||
---------------------------------
|
||||
|
||||
The first step is running Bitcoin behind a Tor proxy. This will already make all
|
||||
outgoing connections be anonimized, but more is possible.
|
||||
|
||||
-socks=5 SOCKS5 supports connecting-to-hostname, which can be used instead
|
||||
of doing a (leaking) local DNS lookup. SOCKS5 is the default,
|
||||
but SOCKS4 does not support this. (SOCKS4a does, but isn't
|
||||
implemented).
|
||||
|
||||
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
|
||||
server will be used to try to reach .onion addresses as well.
|
||||
|
||||
-tor=ip:port Set the proxy server to use for tor hidden services. You do not
|
||||
need to set this if it's the same as -proxy. You can use -notor
|
||||
to explicitly disable access to hidden service.
|
||||
|
||||
-listen When using -proxy, listening is disabled by default. If you want
|
||||
to run a hidden service (see next section), you'll need to enable
|
||||
it explicitly.
|
||||
|
||||
-connect=X When behind a Tor proxy, you can specify .onion addresses instead
|
||||
-addnode=X of IP addresses or hostnames in these parameters. It requires
|
||||
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
|
||||
other P2P nodes.
|
||||
|
||||
In a typical situation, this suffices to run behind a Tor proxy:
|
||||
|
||||
./bitcoin -proxy=127.0.0.1:9050
|
||||
|
||||
|
||||
2. Run a bitcoin hidden server
|
||||
------------------------------
|
||||
|
||||
If you configure your Tor system accordingly, it is possible to make your node also
|
||||
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
|
||||
config file):
|
||||
|
||||
HiddenServiceDir /var/lib/tor/bitcoin-service/
|
||||
HiddenServicePort 8333 127.0.0.1:8333
|
||||
|
||||
The directory can be different of course, but (both) port numbers should be equal to
|
||||
your bitcoind's P2P listen port (8333 by default).
|
||||
|
||||
-externalip=X You can tell bitcoin about its publicly reachable address using
|
||||
this option, and this can be a .onion address. Given the above
|
||||
configuration, you can find your onion address in
|
||||
/var/lib/tor/bitcoin-service/hostname. Onion addresses are given
|
||||
preference for your node to advertize itself with, for connections
|
||||
coming from unroutable addresses (such as 127.0.0.1, where the
|
||||
Tor proxy typically runs).
|
||||
|
||||
-listen You'll need to enable listening for incoming connections, as this
|
||||
is off by default behind a proxy.
|
||||
|
||||
-discover When -externalip is specified, no attempt is made to discover local
|
||||
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
|
||||
from both Tor and IPv4 (or IPv6), you'll need to either pass your
|
||||
other addresses using -externalip, or explicitly enable -discover.
|
||||
Note that both addresses of a dual-stack system may be easily
|
||||
linkable using traffic analysis.
|
||||
|
||||
In a typical situation, where you're only reachable via Tor, this should suffice:
|
||||
|
||||
./bitcoind -proxy=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -listen
|
||||
|
||||
(obviously replace the Onion address with your own). If you don't care too much
|
||||
about hiding your node, and want to be reachable on IPv4 as well, additionally
|
||||
specify:
|
||||
|
||||
./bitcoind ... -discover
|
||||
|
||||
and open port 8333 on your firewall (or use -upnp).
|
||||
|
||||
If you only want to use Tor to reach onion addresses, but not use it as a proxy
|
||||
for normal IPv4/IPv6 communication, use:
|
||||
|
||||
./bitcoin -tor=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover
|
||||
|
||||
@@ -26,9 +26,10 @@ Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0
|
||||
|
||||
Icon: src/qt/res/icons/transaction*.png
|
||||
Designer: md2k7
|
||||
Site: https://forum.bitcoin.org/index.php?topic=15276.0
|
||||
Site: https://bitcointalk.org/index.php?topic=15276.0
|
||||
License: You are free to do with these icons as you wish, including selling,
|
||||
copying, modifying etc.
|
||||
License: MIT
|
||||
|
||||
Icon: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png,
|
||||
src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png,
|
||||
@@ -41,7 +42,7 @@ License: LGPL
|
||||
Icon: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png
|
||||
Designer: Bitboy (optimized for 16x16 by Wladimir van der Laan)
|
||||
License: Public Domain
|
||||
Site: http://forum.bitcoin.org/?topic=1756.0
|
||||
Site: https://bitcointalk.org/?topic=1756.0
|
||||
|
||||
Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng
|
||||
Icon Pack: Kids
|
||||
@@ -54,3 +55,7 @@ Designer: Crobbo (forum)
|
||||
Site: https://bitcointalk.org/index.php?topic=32273.0
|
||||
License: Public domain
|
||||
|
||||
Icon: src/qt/res/icons/debugwindow.png
|
||||
Designer: Vignoni David
|
||||
Site: http://www.oxygen-icons.org/
|
||||
License: Oxygen icon theme is dual licensed. You may copy it under the Creative Common Attribution-ShareAlike 3.0 License or the GNU Library General Public License.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Copyright (c) 2009-2012 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.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
|
||||
software written by Thomas Bernard.
|
||||
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT, the
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt, the
|
||||
graphical user interface.
|
||||
|
||||
WINDOWS BUILD NOTES
|
||||
@@ -24,9 +24,9 @@ Dependencies
|
||||
Libraries you need to download separately and build:
|
||||
|
||||
default path download
|
||||
OpenSSL \openssl-1.0.1b-mgw http://www.openssl.org/source/
|
||||
OpenSSL \openssl-1.0.1c-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/
|
||||
Boost \boost-1.50.0-mgw http://www.boost.org/users/download/
|
||||
miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/
|
||||
|
||||
Their licenses:
|
||||
@@ -36,9 +36,9 @@ Boost MIT-like license
|
||||
miniupnpc New (3-clause) BSD license
|
||||
|
||||
Versions used in this release:
|
||||
OpenSSL 1.0.1b
|
||||
OpenSSL 1.0.1c
|
||||
Berkeley DB 4.8.30.NC
|
||||
Boost 1.47.0
|
||||
Boost 1.50.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.1b-mgw
|
||||
cd /c/openssl-1.0.1c-mgw
|
||||
./config
|
||||
make
|
||||
|
||||
@@ -63,7 +63,7 @@ Boost
|
||||
-----
|
||||
DOS prompt:
|
||||
downloaded boost jam 3.1.18
|
||||
cd \boost-1.47.0-mgw
|
||||
cd \boost-1.50.0-mgw
|
||||
bjam toolset=gcc --build-type=complete stage
|
||||
|
||||
MiniUPnPc
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Copyright (c) 2009-2012 Bitcoin Developers
|
||||
Distributed under the MIT/X11 software license, see the accompanying file
|
||||
license.txt or http://www.opensource.org/licenses/mit-license.php. This
|
||||
product includes software developed by the OpenSSL Project for use in the
|
||||
OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic
|
||||
software written by Eric Young (eay@cryptsoft.com) and UPnP software written by
|
||||
Thomas Bernard.
|
||||
Distributed under the MIT/X11 software license, see the accompanying
|
||||
file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
|
||||
software written by Thomas Bernard.
|
||||
|
||||
|
||||
Mac OS X bitcoind build instructions
|
||||
@@ -12,17 +12,17 @@ Laszlo Hanyecz <solar@heliacal.net>
|
||||
Douglas Huff <dhuff@jrbobdobbs.org>
|
||||
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT, the
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt, the
|
||||
graphical user interface.
|
||||
|
||||
Tested on 10.5 and 10.6 intel. PPC is not supported because it's big-endian.
|
||||
Tested on 10.5, 10.6 and 10.7 intel. PPC is not supported because it's big-endian.
|
||||
|
||||
All of the commands should be executed in Terminal.app.. it's in
|
||||
/Applications/Utilities
|
||||
|
||||
You need to install XCode with all the options checked so that the compiler and
|
||||
everything is available in /usr not just /Developer I think it comes on the DVD
|
||||
but you can get the current version from http://developer.apple.com
|
||||
everything is available in /usr not just /Developer. XCode should be available on your OS X
|
||||
install DVD, but if not, you can get the current version from https://developer.apple.com/xcode/
|
||||
|
||||
|
||||
1. Clone the github tree to get the source code:
|
||||
@@ -44,7 +44,7 @@ sudo port install qrencode
|
||||
4. Now you should be able to build bitcoind:
|
||||
|
||||
cd bitcoin/src
|
||||
make -f makefile.osx
|
||||
make -f makefile.osx USE_IPV6=1
|
||||
|
||||
Run:
|
||||
./bitcoind --help # for a list of command-line options.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Copyright (c) 2009-2012 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.
|
||||
This product includes software developed by the OpenSSL Project for use in
|
||||
the OpenSSL Toolkit (http://www.openssl.org/). This product includes
|
||||
cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP
|
||||
@@ -16,8 +16,8 @@ To Build
|
||||
cd src/
|
||||
make -f makefile.unix # Headless bitcoin
|
||||
|
||||
See readme-qt.rst for instructions on building Bitcoin QT,
|
||||
the graphical bitcoin.
|
||||
See readme-qt.rst for instructions on building Bitcoin-Qt,
|
||||
the graphical user interface.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
@@ -28,7 +28,6 @@ Dependencies
|
||||
libdb4.8 Berkeley DB Blockchain & wallet storage
|
||||
libboost Boost C++ Library
|
||||
miniupnpc UPnP Support Optional firewall-jumping support
|
||||
libqrencode QRCode generation Optional QRCode generation
|
||||
|
||||
miniupnpc may be used for UPnP port mapping. It can be downloaded from
|
||||
http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and
|
||||
@@ -37,11 +36,8 @@ turned off by default. Set USE_UPNP to a different value to control this:
|
||||
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 - libqrcode not required
|
||||
USE_QRCODE=1 QRCode support enabled
|
||||
IPv6 support may be enabled by setting:
|
||||
USE_IPV6=1 Enable IPv6 support
|
||||
|
||||
Licenses of statically linked libraries:
|
||||
Berkeley DB New BSD license with additional requirement that linked
|
||||
@@ -51,22 +47,34 @@ Licenses of statically linked libraries:
|
||||
|
||||
Versions used in this release:
|
||||
GCC 4.3.3
|
||||
OpenSSL 0.9.8g
|
||||
OpenSSL 1.0.1c
|
||||
Berkeley DB 4.8.30.NC
|
||||
Boost 1.37
|
||||
miniupnpc 1.6
|
||||
|
||||
Dependency Build Instructions: Ubuntu & Debian
|
||||
----------------------------------------------
|
||||
sudo apt-get install build-essential
|
||||
sudo apt-get install libssl-dev
|
||||
sudo apt-get install libdb4.8-dev
|
||||
sudo apt-get install libdb4.8++-dev
|
||||
Boost 1.40+: sudo apt-get install libboost-all-dev
|
||||
or Boost 1.37: sudo apt-get install libboost1.37-dev
|
||||
sudo apt-get install libqrencode-dev
|
||||
Build requirements:
|
||||
sudo apt-get install build-essential
|
||||
sudo apt-get install libssl-dev
|
||||
|
||||
If using Boost 1.37, append -mt to the boost libraries in the makefile.
|
||||
for Ubuntu 12.04:
|
||||
sudo apt-get install libboost-all-dev
|
||||
|
||||
db4.8 packages are available at:
|
||||
https://launchpad.net/~bitcoin/+archive/bitcoin
|
||||
|
||||
Ubuntu precise has packages for libdb5.1-dev and libdb5.1++-dev,
|
||||
but using these will break binary wallet compatibility, and is not recommended.
|
||||
|
||||
for other Ubuntu & Debian:
|
||||
sudo apt-get install libdb4.8-dev
|
||||
sudo apt-get install libdb4.8++-dev
|
||||
sudo apt-get install libboost1.37-dev
|
||||
(If using Boost 1.37, append -mt to the boost libraries in the makefile)
|
||||
|
||||
Optional:
|
||||
sudo apt-get install libminiupnpc-dev (see USE_UPNP compile flag)
|
||||
|
||||
|
||||
Dependency Build Instructions: Gentoo
|
||||
@@ -80,7 +88,7 @@ emerge -av1 --noreplace boost glib openssl sys-libs/db:4.8
|
||||
|
||||
Take the following steps to build (no UPnP support):
|
||||
cd ${BITCOIN_DIR}/src
|
||||
make -f makefile.unix USE_UPNP= BDB_INCLUDE_PATH='/usr/include/db4.8'
|
||||
make -f makefile.unix USE_UPNP= USE_IPV6=1 BDB_INCLUDE_PATH='/usr/include/db4.8'
|
||||
strip bitcoind
|
||||
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ bn CBigNum
|
||||
Locking/mutex usage notes
|
||||
|
||||
The code is multi-threaded, and uses mutexes and the
|
||||
CRITICAL_BLOCK/TRY_CRITICAL_BLOCK macros to protect data structures.
|
||||
LOCK/TRY_LOCK macros to protect data structures.
|
||||
|
||||
Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main
|
||||
and then cs_wallet, while thread 2 locks them in the opposite order:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bitcoin-qt: Qt4 GUI for Bitcoin
|
||||
Bitcoin-Qt: Qt4 GUI for Bitcoin
|
||||
===============================
|
||||
|
||||
Build instructions
|
||||
@@ -23,25 +23,26 @@ then execute the following:
|
||||
qmake
|
||||
make
|
||||
|
||||
Alternatively, install Qt Creator and open the `bitcoin-qt.pro` file.
|
||||
Alternatively, install `Qt Creator`_ and open the `bitcoin-qt.pro` file.
|
||||
|
||||
An executable named `bitcoin-qt` will be built.
|
||||
|
||||
.. _`Qt Creator`: http://qt-project.org/downloads/
|
||||
|
||||
Windows
|
||||
--------
|
||||
|
||||
Windows build instructions:
|
||||
|
||||
- Download the `QT Windows SDK`_ and install it. You don't need the Symbian stuff, just the desktop Qt.
|
||||
- Download the `Qt Windows SDK`_ and install it. You don't need the Symbian stuff, just the desktop Qt.
|
||||
|
||||
- Download and extract the `dependencies archive`_ [#]_, or compile openssl, boost and dbcxx yourself.
|
||||
|
||||
- Copy the contents of the folder "deps" to "X:\\QtSDK\\mingw", replace X:\\ with the location where you installed the Qt SDK. Make sure that the contents of "deps\\include" end up in the current "include" directory.
|
||||
|
||||
- Open the .pro file in QT creator and build as normal (ctrl-B)
|
||||
- Open the bitcoin-qt.pro file in Qt Creator and build as normal (ctrl-B)
|
||||
|
||||
.. _`QT Windows SDK`: http://qt.nokia.com/downloads/sdk-windows-cpp
|
||||
.. _`Qt Windows SDK`: http://qt-project.org/downloads/
|
||||
.. _`dependencies archive`: https://download.visucore.com/bitcoin/qtgui_deps_1.zip
|
||||
.. [#] PGP signature: https://download.visucore.com/bitcoin/qtgui_deps_1.zip.sig (signed with RSA key ID `610945D0`_)
|
||||
.. _`610945D0`: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x610945D0
|
||||
@@ -61,16 +62,16 @@ Mac OS X
|
||||
sudo port selfupdate
|
||||
sudo port install boost db48 miniupnpc
|
||||
|
||||
- Open the .pro file in Qt Creator and build as normal (cmd-B)
|
||||
- Open the bitcoin-qt.pro file in Qt Creator and build as normal (cmd-B)
|
||||
|
||||
.. _`Qt Mac OS X SDK`: http://qt.nokia.com/downloads/sdk-mac-os-cpp
|
||||
.. _`Qt Mac OS X SDK`: http://qt-project.org/downloads/
|
||||
.. _`MacPorts`: http://www.macports.org/install.php
|
||||
|
||||
|
||||
Build configuration options
|
||||
============================
|
||||
|
||||
UPNnP port forwarding
|
||||
UPnP port forwarding
|
||||
---------------------
|
||||
|
||||
To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable bitcoin experience), pass the following argument to qmake:
|
||||
@@ -107,8 +108,8 @@ FreeDesktop notification interface through DBUS using the following qmake option
|
||||
Generation of QR codes
|
||||
-----------------------
|
||||
|
||||
libqrencode may be used to generate QRCode images for payment requests.
|
||||
It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Pass the USE_QRCODE
|
||||
libqrencode may be used to generate QRCode images for payment requests.
|
||||
It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Pass the USE_QRCODE
|
||||
flag to qmake to control this:
|
||||
|
||||
+--------------+--------------------------------------------------------------------------+
|
||||
|
||||
51
doc/release-notes.txt
Normal file
51
doc/release-notes.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
(note: this is a temporary file, to be added-to by anybody, and deleted at
|
||||
release time)
|
||||
|
||||
Building this from
|
||||
|
||||
$ git shortlog --no-merges 8a17087..
|
||||
|
||||
How to Upgrade
|
||||
--------------
|
||||
|
||||
If you are running an older version, shut it down. Wait
|
||||
until it has completely shut down (which might take a few minutes for older
|
||||
versions), then run the installer (on Windows) or just copy over
|
||||
/Applications/Bitcoin-Qt (on Mac) or bitcoind/bitcoin-qt (on Linux).
|
||||
|
||||
If you were running on Linux with a version that might have been compiled
|
||||
with a different version of Berkeley DB (for example, if you were using an
|
||||
Ubuntu PPA version), then run the old version again with the -detachdb
|
||||
argument and shut it down; if you do not, then the new version will not
|
||||
be able to read the database files and will exit with an error.
|
||||
|
||||
Explanation of -detachdb (and the new "stop true" RPC command):
|
||||
The Berkeley DB database library stores data in both ".dat" and
|
||||
"log" files, so the database is always in a consistent state,
|
||||
even in case of power failure or other sudden shutdown. The
|
||||
format of the ".dat" files is portable between different
|
||||
versions of Berkeley DB, but the "log" files are not-- even minor
|
||||
version differences may have incompatible "log" files. The
|
||||
-detachdb option moves any pending changes from the "log" files
|
||||
to the "blkindex.dat" file for maximum compatibility, but makes
|
||||
shutdown much slower. Note that the "wallet.dat" file is always
|
||||
detached, and versions prior to 0.6.0 detached all databases
|
||||
at shutdown.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Prevent RPC 'move' from deadlocking. This was caused by trying to lock the
|
||||
database twice.
|
||||
|
||||
* Fix use-after-free problems in initialization and shutdown, the latter of
|
||||
which caused Bitcoin-Qt to crash on Windows when exiting.
|
||||
|
||||
* Correct library linking so building on Windows natively works.
|
||||
|
||||
* Avoid a race condition and out-of-bounds read in block creation/mining code.
|
||||
|
||||
* Improve platform compatibility quirks, including fix for 100% CPU utilization
|
||||
on FreeBSD 9.
|
||||
|
||||
* A few minor corrections to error handling, and updated translations.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
* update (commit) version in sources
|
||||
bitcoin-qt.pro
|
||||
src/version.h
|
||||
src/clientversion.h
|
||||
share/setup.nsi
|
||||
doc/README*
|
||||
|
||||
@@ -21,23 +21,23 @@
|
||||
export VERSION=0.5.1
|
||||
cd ./gitian-builder
|
||||
|
||||
* Fetch and build inputs:
|
||||
* Fetch and build inputs: (first time, or when dependency versions change)
|
||||
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.1b.tar.gz'
|
||||
wget 'http://www.openssl.org/source/openssl-1.0.1c.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'
|
||||
wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
|
||||
wget 'http://downloads.sourceforge.net/project/boost/boost/1.47.0/boost_1_47_0.tar.bz2'
|
||||
wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.tar.gz'
|
||||
wget 'http://downloads.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2'
|
||||
wget 'http://releases.qt-project.org/qt4/source/qt-everywhere-opensource-src-4.8.2.tar.gz'
|
||||
cd ..
|
||||
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml
|
||||
cp build/out/boost-win32-1.47.0-gitian.zip inputs/
|
||||
mv build/out/boost-win32-1.50.0-gitian2.zip inputs/
|
||||
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
|
||||
cp build/out/qt-win32-4.7.4-gitian.zip inputs/
|
||||
mv build/out/qt-win32-4.8.2-gitian-r1.zip inputs/
|
||||
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-win32.yml
|
||||
cp build/out/bitcoin-deps-0.0.3.zip inputs/
|
||||
mv build/out/bitcoin-deps-0.0.5.zip inputs/
|
||||
|
||||
* Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32:
|
||||
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
@@ -93,6 +93,7 @@
|
||||
* create SHA256SUMS for builds, and PGP-sign it
|
||||
|
||||
* update bitcoin.org version
|
||||
make sure all OS download links go to the right versions
|
||||
|
||||
* update forum version
|
||||
|
||||
|
||||
@@ -28,32 +28,57 @@ This directory contains all translations. Filenames must adhere to this format:
|
||||
|
||||
bitcoin_xx_YY.ts or bitcoin_xx.ts
|
||||
|
||||
#### Source file
|
||||
#### bitcoin_en.ts (Source file)
|
||||
|
||||
`src/qt/locale/bitcoin_en.ts` is treated in a special way. It is used as the
|
||||
source for all other translations. Whenever a string in the code is changed
|
||||
this file must be updated to reflect those changes. Usually, this can be
|
||||
accomplished by running `lupdate` (included in the Qt SDK).
|
||||
this file must be updated to reflect those changes. This can be accomplished
|
||||
by running `lupdate` (included in the Qt SDK). Also, a custom script is used
|
||||
to extract strings from the non-Qt parts. This script makes use of `gettext`,
|
||||
so make sure that utility is installed (ie, `apt-get install gettext` on
|
||||
Ubuntu/Debian):
|
||||
|
||||
An updated source file should be merged to github and transifex will pick it
|
||||
up from there. Afterwards the new strings show up as "Remaining" in transifex
|
||||
and can be translated.
|
||||
python share/qt/extract_strings_qt.py
|
||||
lupdate bitcoin-qt.pro -no-obsolete -locations relative -ts src/qt/locale/bitcoin_en.ts
|
||||
|
||||
##### Handling of plurals in the source file
|
||||
|
||||
Syncing with transifex
|
||||
When new plurals are added to the source file, it's important to do the following steps:
|
||||
|
||||
1. Open bitcoin_en.ts in Qt Linguist (also included in the Qt SDK)
|
||||
2. Search for `%n`, which will take you to the parts in the translation that use plurals
|
||||
3. Look for empty `English Translation (Singular)` and `English Translation (Plural)` fields
|
||||
4. Add the appropriate strings for the singular and plural form of the base string
|
||||
5. Mark the item as done (via the green arrow symbol in the toolbar)
|
||||
6. Repeat from step 2. until all singular and plural forms are in the source file
|
||||
7. Save the source file
|
||||
|
||||
##### Creating the pull-request
|
||||
|
||||
An updated source file should be merged to github and Transifex will pick it
|
||||
up from there (can take some hours). Afterwards the new strings show up as "Remaining"
|
||||
in Transifex and can be translated.
|
||||
|
||||
To create the pull-request you have to do:
|
||||
|
||||
git add src/qt/bitcoinstrings.cpp src/qt/locale/bitcoin_en.ts
|
||||
git commit
|
||||
|
||||
Syncing with Transifex
|
||||
----------------------
|
||||
|
||||
We are using http://transifex.net as a frontend for translating the client.
|
||||
We are using https://transifex.com as a frontend for translating the client.
|
||||
|
||||
https://www.transifex.net/projects/p/bitcoin/resource/tx/
|
||||
https://www.transifex.com/projects/p/bitcoin/resource/tx/
|
||||
|
||||
The "transifex client" (see: http://help.transifex.net/features/client/)
|
||||
will help with fetching new translations from transifex. Use the following
|
||||
config to be able to connect with the client.
|
||||
The "Transifex client" (see: http://help.transifex.com/features/client/)
|
||||
will help with fetching new translations from Transifex. Use the following
|
||||
config to be able to connect with the client:
|
||||
|
||||
### .tx/config
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.net
|
||||
host = https://www.transifex.com
|
||||
|
||||
[bitcoin.tx]
|
||||
file_filter = src/qt/locale/bitcoin_<lang>.ts
|
||||
@@ -63,14 +88,14 @@ config to be able to connect with the client.
|
||||
### .tx/config (for Windows)
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.net
|
||||
host = https://www.transifex.com
|
||||
|
||||
[bitcoin.tx]
|
||||
file_filter = src\qt\locale\bitcoin_<lang>.ts
|
||||
source_file = src\qt\locale\bitcoin_en.ts
|
||||
source_lang = en
|
||||
|
||||
It is also possible to directly download new translations one by one from transifex.
|
||||
It is also possible to directly download new translations one by one from the Transifex website.
|
||||
|
||||
### Fetching new translations
|
||||
|
||||
|
||||
33
doc/unit-tests.txt
Normal file
33
doc/unit-tests.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
Compiling/running bitcoind unit tests
|
||||
------------------------------------
|
||||
|
||||
bitcoind unit tests are in the src/test/ directory; they
|
||||
use the Boost::Test unit-testing framework.
|
||||
|
||||
To compile and run the tests:
|
||||
cd src
|
||||
make -f makefile.unix test_bitcoin # Replace makefile.unix if you're not on unix
|
||||
./test_bitcoin # Runs the unit tests
|
||||
|
||||
If all tests succeed the last line of output will be:
|
||||
*** No errors detected
|
||||
|
||||
To add more tests, add BOOST_AUTO_TEST_CASE functions to the existing
|
||||
.cpp files in the test/ directory or add new .cpp files that
|
||||
implement new BOOST_AUTO_TEST_SUITE sections (the makefiles are
|
||||
set up to add test/*.cpp to test_bitcoin automatically).
|
||||
|
||||
|
||||
Compiling/running Bitcoin-Qt unit tests
|
||||
---------------------------------------
|
||||
|
||||
Bitcoin-Qt unit tests are in the src/qt/test/ directory; they
|
||||
use the Qt unit-testing framework.
|
||||
|
||||
To compile and run the tests:
|
||||
qmake bitcoin-qt.pro BITCOIN_QT_TEST=1
|
||||
make
|
||||
./bitcoin-qt_test
|
||||
|
||||
To add more tests, add them to the src/qt/test/ directory,
|
||||
the src/qt/test/test_main.cpp file, and bitcoin-qt.pro.
|
||||
@@ -5,6 +5,7 @@ they can be picked up by Qt linguist.
|
||||
'''
|
||||
from subprocess import Popen, PIPE
|
||||
import glob
|
||||
import operator
|
||||
|
||||
OUT_CPP="src/qt/bitcoinstrings.cpp"
|
||||
EMPTY=['""']
|
||||
@@ -62,7 +63,8 @@ f.write("""#include <QtGlobal>
|
||||
#define UNUSED
|
||||
#endif
|
||||
""")
|
||||
f.write('static const char UNUSED *bitcoin_strings[] = {')
|
||||
f.write('static const char UNUSED *bitcoin_strings[] = {\n')
|
||||
messages.sort(key=operator.itemgetter(0))
|
||||
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.3
|
||||
!define VERSION 0.7.2
|
||||
!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.3-win32-setup.exe
|
||||
OutFile bitcoin-0.7.2-win32-setup.exe
|
||||
InstallDir $PROGRAMFILES\Bitcoin
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
BrandingText " "
|
||||
ShowInstDetails show
|
||||
VIProductVersion 0.6.3.0
|
||||
VIProductVersion 0.7.2.0
|
||||
VIAddVersionKey ProductName Bitcoin
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey CompanyName "${COMPANY}"
|
||||
@@ -67,7 +67,7 @@ Section -Main SEC0000
|
||||
SetOutPath $INSTDIR
|
||||
SetOverwrite on
|
||||
File ../release/bitcoin-qt.exe
|
||||
File /oname=license.txt ../COPYING
|
||||
File /oname=COPYING.txt ../COPYING
|
||||
File /oname=readme.txt ../doc/README_windows.txt
|
||||
SetOutPath $INSTDIR\daemon
|
||||
File ../src/bitcoind.exe
|
||||
@@ -98,12 +98,10 @@ Section -post SEC0001
|
||||
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
|
||||
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
|
||||
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
|
||||
|
||||
# bitcoin: URI handling disabled for 0.6.0
|
||||
# WriteRegStr HKCR "bitcoin" "URL Protocol" ""
|
||||
# WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
|
||||
# WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
|
||||
# WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "$$1"'
|
||||
WriteRegStr HKCR "bitcoin" "URL Protocol" ""
|
||||
WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
|
||||
WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
|
||||
WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"'
|
||||
SectionEnd
|
||||
|
||||
# Macro for selecting uninstaller sections
|
||||
@@ -122,7 +120,7 @@ done${UNSECTION_ID}:
|
||||
# Uninstaller sections
|
||||
Section /o -un.Main UNSEC0000
|
||||
Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe
|
||||
Delete /REBOOTOK $INSTDIR\license.txt
|
||||
Delete /REBOOTOK $INSTDIR\COPYING.txt
|
||||
Delete /REBOOTOK $INSTDIR\readme.txt
|
||||
RMDir /r /REBOOTOK $INSTDIR\daemon
|
||||
RMDir /r /REBOOTOK $INSTDIR\src
|
||||
|
||||
@@ -102,12 +102,11 @@ CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, in
|
||||
return &mapInfo[nId];
|
||||
}
|
||||
|
||||
void CAddrMan::SwapRandom(int nRndPos1, int nRndPos2)
|
||||
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
||||
{
|
||||
if (nRndPos1 == nRndPos2)
|
||||
return;
|
||||
|
||||
assert(nRndPos1 >= 0 && nRndPos2 >= 0);
|
||||
assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
|
||||
|
||||
int nId1 = vRandom[nRndPos1];
|
||||
@@ -149,7 +148,7 @@ int CAddrMan::SelectTried(int nKBucket)
|
||||
|
||||
int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
assert(nUBucket >= 0 && nUBucket < vvNew.size());
|
||||
assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// first look for deletable items
|
||||
@@ -188,7 +187,7 @@ int CAddrMan::ShrinkNew(int nUBucket)
|
||||
}
|
||||
assert(mapInfo.count(nOldest) == 1);
|
||||
CAddrInfo &info = mapInfo[nOldest];
|
||||
if (--info.nRefCount == 0)
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
SwapRandom(info.nRandomPos, vRandom.size()-1);
|
||||
vRandom.pop_back();
|
||||
@@ -242,7 +241,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
infoOld.nRefCount = 1;
|
||||
// do not update nTried, as we are going to move something else there immediately
|
||||
|
||||
// check whether there is place in that one,
|
||||
// check whether there is place in that one,
|
||||
if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE)
|
||||
{
|
||||
// if so, move it back there
|
||||
@@ -411,7 +410,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
} else {
|
||||
// use an new node
|
||||
// use a new node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "sync.h"
|
||||
|
||||
|
||||
#include <map>
|
||||
@@ -22,13 +23,13 @@ private:
|
||||
// where knowledge about this address first came from
|
||||
CNetAddr source;
|
||||
|
||||
// last succesfull connection by us
|
||||
// last successful connection by us
|
||||
int64 nLastSuccess;
|
||||
|
||||
// last try whatsoever by us:
|
||||
// int64 CAddress::nLastTry
|
||||
|
||||
// connection attempts since last succesful attempt
|
||||
// connection attempts since last successful attempt
|
||||
int nAttempts;
|
||||
|
||||
// reference count in new sets (memory only)
|
||||
@@ -116,7 +117,7 @@ public:
|
||||
// * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
|
||||
// be observable by adversaries.
|
||||
// * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
|
||||
// consistency checks for the entire datastructure.
|
||||
// consistency checks for the entire data structure.
|
||||
|
||||
// total number of buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_COUNT 64
|
||||
@@ -173,13 +174,13 @@ private:
|
||||
// last used nId
|
||||
int nIdCount;
|
||||
|
||||
// table with information about all nId's
|
||||
// table with information about all nIds
|
||||
std::map<int, CAddrInfo> mapInfo;
|
||||
|
||||
// find an nId based on its network address
|
||||
std::map<CNetAddr, int> mapAddr;
|
||||
|
||||
// randomly-ordered vector of all nId's
|
||||
// randomly-ordered vector of all nIds
|
||||
std::vector<int> vRandom;
|
||||
|
||||
// number of "tried" entries
|
||||
@@ -204,7 +205,7 @@ protected:
|
||||
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
|
||||
|
||||
// Swap two elements in vRandom.
|
||||
void SwapRandom(int nRandomPos1, int nRandomPos2);
|
||||
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
|
||||
|
||||
// Return position in given bucket to replace.
|
||||
int SelectTried(int nKBucket);
|
||||
@@ -213,7 +214,7 @@ protected:
|
||||
// This is the only place where actual deletes occur.
|
||||
// They are never deleted while in the "tried" table, only possibly evicted back to the "new" table.
|
||||
int ShrinkNew(int nUBucket);
|
||||
|
||||
|
||||
// Move an entry from the "new" table(s) to the "tried" table
|
||||
// @pre vvUnkown[nOrigin].count(nId) != 0
|
||||
void MakeTried(CAddrInfo& info, int nId, int nOrigin);
|
||||
@@ -252,8 +253,8 @@ public:
|
||||
// * nNew
|
||||
// * nTried
|
||||
// * number of "new" buckets
|
||||
// * all nNew addrinfo's in vvNew
|
||||
// * all nTried addrinfo's in vvTried
|
||||
// * all nNew addrinfos in vvNew
|
||||
// * all nTried addrinfos in vvTried
|
||||
// * for each bucket:
|
||||
// * number of elements
|
||||
// * for each element: index
|
||||
|
||||
239
src/alert.cpp
Normal file
239
src/alert.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// Alert system
|
||||
//
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <map>
|
||||
|
||||
#include "alert.h"
|
||||
#include "key.h"
|
||||
#include "net.h"
|
||||
#include "sync.h"
|
||||
#include "ui_interface.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
map<uint256, CAlert> mapAlerts;
|
||||
CCriticalSection cs_mapAlerts;
|
||||
|
||||
static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284";
|
||||
static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a";
|
||||
|
||||
void CUnsignedAlert::SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nRelayUntil = 0;
|
||||
nExpiration = 0;
|
||||
nID = 0;
|
||||
nCancel = 0;
|
||||
setCancel.clear();
|
||||
nMinVer = 0;
|
||||
nMaxVer = 0;
|
||||
setSubVer.clear();
|
||||
nPriority = 0;
|
||||
|
||||
strComment.clear();
|
||||
strStatusBar.clear();
|
||||
strReserved.clear();
|
||||
}
|
||||
|
||||
std::string CUnsignedAlert::ToString() const
|
||||
{
|
||||
std::string strSetCancel;
|
||||
BOOST_FOREACH(int n, setCancel)
|
||||
strSetCancel += strprintf("%d ", n);
|
||||
std::string strSetSubVer;
|
||||
BOOST_FOREACH(std::string str, setSubVer)
|
||||
strSetSubVer += "\"" + str + "\" ";
|
||||
return strprintf(
|
||||
"CAlert(\n"
|
||||
" nVersion = %d\n"
|
||||
" nRelayUntil = %"PRI64d"\n"
|
||||
" nExpiration = %"PRI64d"\n"
|
||||
" nID = %d\n"
|
||||
" nCancel = %d\n"
|
||||
" setCancel = %s\n"
|
||||
" nMinVer = %d\n"
|
||||
" nMaxVer = %d\n"
|
||||
" setSubVer = %s\n"
|
||||
" nPriority = %d\n"
|
||||
" strComment = \"%s\"\n"
|
||||
" strStatusBar = \"%s\"\n"
|
||||
")\n",
|
||||
nVersion,
|
||||
nRelayUntil,
|
||||
nExpiration,
|
||||
nID,
|
||||
nCancel,
|
||||
strSetCancel.c_str(),
|
||||
nMinVer,
|
||||
nMaxVer,
|
||||
strSetSubVer.c_str(),
|
||||
nPriority,
|
||||
strComment.c_str(),
|
||||
strStatusBar.c_str());
|
||||
}
|
||||
|
||||
void CUnsignedAlert::print() const
|
||||
{
|
||||
printf("%s", ToString().c_str());
|
||||
}
|
||||
|
||||
void CAlert::SetNull()
|
||||
{
|
||||
CUnsignedAlert::SetNull();
|
||||
vchMsg.clear();
|
||||
vchSig.clear();
|
||||
}
|
||||
|
||||
bool CAlert::IsNull() const
|
||||
{
|
||||
return (nExpiration == 0);
|
||||
}
|
||||
|
||||
uint256 CAlert::GetHash() const
|
||||
{
|
||||
return Hash(this->vchMsg.begin(), this->vchMsg.end());
|
||||
}
|
||||
|
||||
bool CAlert::IsInEffect() const
|
||||
{
|
||||
return (GetAdjustedTime() < nExpiration);
|
||||
}
|
||||
|
||||
bool CAlert::Cancels(const CAlert& alert) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false; // this was a no-op before 31403
|
||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
|
||||
{
|
||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
||||
return (IsInEffect() &&
|
||||
nMinVer <= nVersion && nVersion <= nMaxVer &&
|
||||
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesToMe() const
|
||||
{
|
||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
|
||||
}
|
||||
|
||||
bool CAlert::RelayTo(CNode* pnode) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
// returns true if wasn't already contained in the set
|
||||
if (pnode->setKnown.insert(GetHash()).second)
|
||||
{
|
||||
if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
|
||||
AppliesToMe() ||
|
||||
GetAdjustedTime() < nRelayUntil)
|
||||
{
|
||||
pnode->PushMessage("alert", *this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAlert::CheckSignature() const
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
|
||||
return error("CAlert::CheckSignature() : SetPubKey failed");
|
||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||
return error("CAlert::CheckSignature() : verify signature failed");
|
||||
|
||||
// Now unserialize the data
|
||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||
sMsg >> *(CUnsignedAlert*)this;
|
||||
return true;
|
||||
}
|
||||
|
||||
CAlert CAlert::getAlertByHash(const uint256 &hash)
|
||||
{
|
||||
CAlert retval;
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
|
||||
if(mi != mapAlerts.end())
|
||||
retval = mi->second;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CAlert::ProcessAlert()
|
||||
{
|
||||
if (!CheckSignature())
|
||||
return false;
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
|
||||
// alert.nID=max is reserved for if the alert key is
|
||||
// compromised. It must have a pre-defined message,
|
||||
// must never expire, must apply to all versions,
|
||||
// and must cancel all previous
|
||||
// alerts or it will be ignored (so an attacker can't
|
||||
// send an "everything is OK, don't panic" version that
|
||||
// cannot be overridden):
|
||||
int maxInt = std::numeric_limits<int>::max();
|
||||
if (nID == maxInt)
|
||||
{
|
||||
if (!(
|
||||
nExpiration == maxInt &&
|
||||
nCancel == (maxInt-1) &&
|
||||
nMinVer == 0 &&
|
||||
nMaxVer == maxInt &&
|
||||
setSubVer.empty() &&
|
||||
nPriority == maxInt &&
|
||||
strStatusBar == "URGENT: Alert key compromised, upgrade required"
|
||||
))
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
// Cancel previous alerts
|
||||
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
|
||||
{
|
||||
const CAlert& alert = (*mi).second;
|
||||
if (Cancels(alert))
|
||||
{
|
||||
printf("cancelling alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else if (!alert.IsInEffect())
|
||||
{
|
||||
printf("expiring alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
|
||||
// Check if this alert has been cancelled
|
||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
||||
{
|
||||
const CAlert& alert = item.second;
|
||||
if (alert.Cancels(*this))
|
||||
{
|
||||
printf("alert already cancelled by %d\n", alert.nID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mapAlerts
|
||||
mapAlerts.insert(make_pair(GetHash(), *this));
|
||||
// Notify UI if it applies to me
|
||||
if(AppliesToMe())
|
||||
uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
|
||||
}
|
||||
|
||||
printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
|
||||
return true;
|
||||
}
|
||||
102
src/alert.h
Normal file
102
src/alert.h
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _BITCOINALERT_H_
|
||||
#define _BITCOINALERT_H_ 1
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
class CNode;
|
||||
|
||||
/** Alerts are for notifying old versions if they become too obsolete and
|
||||
* need to upgrade. The message is displayed in the status bar.
|
||||
* Alert messages are broadcast as a vector of signed data. Unserializing may
|
||||
* not read the entire buffer if the alert is for a newer version, but older
|
||||
* versions can still relay the original data.
|
||||
*/
|
||||
class CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
int nVersion;
|
||||
int64 nRelayUntil; // when newer nodes stop relaying to newer nodes
|
||||
int64 nExpiration;
|
||||
int nID;
|
||||
int nCancel;
|
||||
std::set<int> setCancel;
|
||||
int nMinVer; // lowest version inclusive
|
||||
int nMaxVer; // highest version inclusive
|
||||
std::set<std::string> setSubVer; // empty matches all
|
||||
int nPriority;
|
||||
|
||||
// Actions
|
||||
std::string strComment;
|
||||
std::string strStatusBar;
|
||||
std::string strReserved;
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(nRelayUntil);
|
||||
READWRITE(nExpiration);
|
||||
READWRITE(nID);
|
||||
READWRITE(nCancel);
|
||||
READWRITE(setCancel);
|
||||
READWRITE(nMinVer);
|
||||
READWRITE(nMaxVer);
|
||||
READWRITE(setSubVer);
|
||||
READWRITE(nPriority);
|
||||
|
||||
READWRITE(strComment);
|
||||
READWRITE(strStatusBar);
|
||||
READWRITE(strReserved);
|
||||
)
|
||||
|
||||
void SetNull();
|
||||
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
};
|
||||
|
||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
||||
class CAlert : public CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
std::vector<unsigned char> vchMsg;
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CAlert()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(vchMsg);
|
||||
READWRITE(vchSig);
|
||||
)
|
||||
|
||||
void SetNull();
|
||||
bool IsNull() const;
|
||||
uint256 GetHash() const;
|
||||
bool IsInEffect() const;
|
||||
bool Cancels(const CAlert& alert) const;
|
||||
bool AppliesTo(int nVersion, std::string strSubVerIn) const;
|
||||
bool AppliesToMe() const;
|
||||
bool RelayTo(CNode* pnode) const;
|
||||
bool CheckSignature() const;
|
||||
bool ProcessAlert();
|
||||
|
||||
/*
|
||||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found.
|
||||
*/
|
||||
static CAlert getAlertByHash(const uint256 &hash);
|
||||
};
|
||||
|
||||
#endif
|
||||
165
src/allocators.h
165
src/allocators.h
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <map>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
@@ -22,23 +24,156 @@
|
||||
// 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)
|
||||
#include <limits.h> // for PAGESIZE
|
||||
#include <unistd.h> // for sysconf
|
||||
#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))))
|
||||
|
||||
/**
|
||||
* Thread-safe class to keep track of locked (ie, non-swappable) memory pages.
|
||||
*
|
||||
* Memory locks do not stack, that is, pages which have been locked several times by calls to mlock()
|
||||
* will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when
|
||||
* those functions are used naively. This class simulates stacking memory locks by keeping a counter per page.
|
||||
*
|
||||
* @note By using a map from each page base address to lock count, this class is optimized for
|
||||
* small objects that span up to a few pages, mostly smaller than a page. To support large allocations,
|
||||
* something like an interval tree would be the preferred data structure.
|
||||
*/
|
||||
template <class Locker> class LockedPageManagerBase
|
||||
{
|
||||
public:
|
||||
LockedPageManagerBase(size_t page_size):
|
||||
page_size(page_size)
|
||||
{
|
||||
// Determine bitmask for extracting page from address
|
||||
assert(!(page_size & (page_size-1))); // size must be power of two
|
||||
page_mask = ~(page_size - 1);
|
||||
}
|
||||
|
||||
// For all pages in affected range, increase lock count
|
||||
void LockRange(void *p, size_t size)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
if(!size) return;
|
||||
const size_t base_addr = reinterpret_cast<size_t>(p);
|
||||
const size_t start_page = base_addr & page_mask;
|
||||
const size_t end_page = (base_addr + size - 1) & page_mask;
|
||||
for(size_t page = start_page; page <= end_page; page += page_size)
|
||||
{
|
||||
Histogram::iterator it = histogram.find(page);
|
||||
if(it == histogram.end()) // Newly locked page
|
||||
{
|
||||
locker.Lock(reinterpret_cast<void*>(page), page_size);
|
||||
histogram.insert(std::make_pair(page, 1));
|
||||
}
|
||||
else // Page was already locked; increase counter
|
||||
{
|
||||
it->second += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For all pages in affected range, decrease lock count
|
||||
void UnlockRange(void *p, size_t size)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
if(!size) return;
|
||||
const size_t base_addr = reinterpret_cast<size_t>(p);
|
||||
const size_t start_page = base_addr & page_mask;
|
||||
const size_t end_page = (base_addr + size - 1) & page_mask;
|
||||
for(size_t page = start_page; page <= end_page; page += page_size)
|
||||
{
|
||||
Histogram::iterator it = histogram.find(page);
|
||||
assert(it != histogram.end()); // Cannot unlock an area that was not locked
|
||||
// Decrease counter for page, when it is zero, the page will be unlocked
|
||||
it->second -= 1;
|
||||
if(it->second == 0) // Nothing on the page anymore that keeps it locked
|
||||
{
|
||||
// Unlock page and remove the count from histogram
|
||||
locker.Unlock(reinterpret_cast<void*>(page), page_size);
|
||||
histogram.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get number of locked pages for diagnostics
|
||||
int GetLockedPageCount()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
return histogram.size();
|
||||
}
|
||||
|
||||
private:
|
||||
Locker locker;
|
||||
boost::mutex mutex;
|
||||
size_t page_size, page_mask;
|
||||
// map of page base address to lock count
|
||||
typedef std::map<size_t,int> Histogram;
|
||||
Histogram histogram;
|
||||
};
|
||||
|
||||
/** Determine system page size in bytes */
|
||||
static inline size_t GetSystemPageSize()
|
||||
{
|
||||
size_t page_size;
|
||||
#if defined(WIN32)
|
||||
SYSTEM_INFO sSysInfo;
|
||||
GetSystemInfo(&sSysInfo);
|
||||
page_size = sSysInfo.dwPageSize;
|
||||
#elif defined(PAGESIZE) // defined in limits.h
|
||||
page_size = PAGESIZE;
|
||||
#else // assume some POSIX OS
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
return page_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* OS-dependent memory page locking/unlocking.
|
||||
* Defined as policy class to make stubbing for test possible.
|
||||
*/
|
||||
class MemoryPageLocker
|
||||
{
|
||||
public:
|
||||
/** Lock memory pages.
|
||||
* addr and len must be a multiple of the system page size
|
||||
*/
|
||||
bool Lock(const void *addr, size_t len)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return VirtualLock(const_cast<void*>(addr), len);
|
||||
#else
|
||||
return mlock(addr, len) == 0;
|
||||
#endif
|
||||
}
|
||||
/** Unlock memory pages.
|
||||
* addr and len must be a multiple of the system page size
|
||||
*/
|
||||
bool Unlock(const void *addr, size_t len)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return VirtualUnlock(const_cast<void*>(addr), len);
|
||||
#else
|
||||
return munlock(addr, len) == 0;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
|
||||
* std::allocator templates.
|
||||
*/
|
||||
class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
|
||||
{
|
||||
public:
|
||||
static LockedPageManager instance; // instantiated in util.cpp
|
||||
private:
|
||||
LockedPageManager():
|
||||
LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
|
||||
{}
|
||||
};
|
||||
|
||||
//
|
||||
// Allocator that locks its contents from being paged
|
||||
@@ -69,7 +204,7 @@ struct secure_allocator : public std::allocator<T>
|
||||
T *p;
|
||||
p = std::allocator<T>::allocate(n, hint);
|
||||
if (p != NULL)
|
||||
mlock(p, sizeof(T) * n);
|
||||
LockedPageManager::instance.LockRange(p, sizeof(T) * n);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -78,7 +213,7 @@ struct secure_allocator : public std::allocator<T>
|
||||
if (p != NULL)
|
||||
{
|
||||
memset(p, 0, sizeof(T) * n);
|
||||
munlock(p, sizeof(T) * n);
|
||||
LockedPageManager::instance.UnlockRange(p, sizeof(T) * n);
|
||||
}
|
||||
std::allocator<T>::deallocate(p, n);
|
||||
}
|
||||
|
||||
115
src/base58.h
115
src/base58.h
@@ -10,7 +10,7 @@
|
||||
// could be used to create visually identical looking account numbers.
|
||||
// - A string with non-alphanumeric characters is not as easily accepted as an account number.
|
||||
// - E-mail usually won't line-break if there's no punctuation to break at.
|
||||
// - Doubleclicking selects the whole number as one word if it's all alphanumeric.
|
||||
// - Double-clicking selects the whole number as one word if it's all alphanumeric.
|
||||
//
|
||||
#ifndef BITCOIN_BASE58_H
|
||||
#define BITCOIN_BASE58_H
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
#include "bignum.h"
|
||||
#include "key.h"
|
||||
#include "script.h"
|
||||
|
||||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
@@ -70,7 +71,7 @@ inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string psz into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
// returns true if decoding is successful
|
||||
inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
@@ -118,7 +119,7 @@ inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string str into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
// returns true if decoding is successful
|
||||
inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58(str.c_str(), vchRet);
|
||||
@@ -138,7 +139,7 @@ inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
// returns true if decoding is successful
|
||||
inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
if (!DecodeBase58(psz, vchRet))
|
||||
@@ -159,7 +160,7 @@ inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRe
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
// returns true if decoding is successful
|
||||
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58Check(str.c_str(), vchRet);
|
||||
@@ -252,12 +253,24 @@ public:
|
||||
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
|
||||
};
|
||||
|
||||
/** base58-encoded bitcoin addresses.
|
||||
/** base58-encoded Bitcoin addresses.
|
||||
* Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
||||
* Script-hash-addresses have version 5 (or 196 testnet).
|
||||
* The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
||||
*/
|
||||
class CBitcoinAddress;
|
||||
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
CBitcoinAddress *addr;
|
||||
public:
|
||||
CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
|
||||
bool operator()(const CKeyID &id) const;
|
||||
bool operator()(const CScriptID &id) const;
|
||||
bool operator()(const CNoDestination &no) const;
|
||||
};
|
||||
|
||||
class CBitcoinAddress : public CBase58Data
|
||||
{
|
||||
public:
|
||||
@@ -269,21 +282,19 @@ public:
|
||||
SCRIPT_ADDRESS_TEST = 196,
|
||||
};
|
||||
|
||||
bool SetHash160(const uint160& hash160)
|
||||
{
|
||||
SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &hash160, 20);
|
||||
bool Set(const CKeyID &id) {
|
||||
SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
SetHash160(Hash160(vchPubKey));
|
||||
bool Set(const CScriptID &id) {
|
||||
SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetScriptHash160(const uint160& hash160)
|
||||
bool Set(const CTxDestination &dest)
|
||||
{
|
||||
SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &hash160, 20);
|
||||
return true;
|
||||
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
@@ -315,27 +326,14 @@ public:
|
||||
}
|
||||
return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
|
||||
}
|
||||
bool IsScript() const
|
||||
{
|
||||
if (!IsValid())
|
||||
return false;
|
||||
if (fTestNet)
|
||||
return nVersion == SCRIPT_ADDRESS_TEST;
|
||||
return nVersion == SCRIPT_ADDRESS;
|
||||
}
|
||||
|
||||
CBitcoinAddress()
|
||||
{
|
||||
}
|
||||
|
||||
CBitcoinAddress(uint160 hash160In)
|
||||
CBitcoinAddress(const CTxDestination &dest)
|
||||
{
|
||||
SetHash160(hash160In);
|
||||
}
|
||||
|
||||
CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
SetPubKey(vchPubKey);
|
||||
Set(dest);
|
||||
}
|
||||
|
||||
CBitcoinAddress(const std::string& strAddress)
|
||||
@@ -348,21 +346,64 @@ public:
|
||||
SetString(pszAddress);
|
||||
}
|
||||
|
||||
uint160 GetHash160() const
|
||||
{
|
||||
assert(vchData.size() == 20);
|
||||
uint160 hash160;
|
||||
memcpy(&hash160, &vchData[0], 20);
|
||||
return hash160;
|
||||
CTxDestination Get() const {
|
||||
if (!IsValid())
|
||||
return CNoDestination();
|
||||
switch (nVersion) {
|
||||
case PUBKEY_ADDRESS:
|
||||
case PUBKEY_ADDRESS_TEST: {
|
||||
uint160 id;
|
||||
memcpy(&id, &vchData[0], 20);
|
||||
return CKeyID(id);
|
||||
}
|
||||
case SCRIPT_ADDRESS:
|
||||
case SCRIPT_ADDRESS_TEST: {
|
||||
uint160 id;
|
||||
memcpy(&id, &vchData[0], 20);
|
||||
return CScriptID(id);
|
||||
}
|
||||
}
|
||||
return CNoDestination();
|
||||
}
|
||||
|
||||
bool GetKeyID(CKeyID &keyID) const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
switch (nVersion) {
|
||||
case PUBKEY_ADDRESS:
|
||||
case PUBKEY_ADDRESS_TEST: {
|
||||
uint160 id;
|
||||
memcpy(&id, &vchData[0], 20);
|
||||
keyID = CKeyID(id);
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsScript() const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
switch (nVersion) {
|
||||
case SCRIPT_ADDRESS:
|
||||
case SCRIPT_ADDRESS_TEST: {
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
|
||||
bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
|
||||
|
||||
/** A base58-encoded secret key */
|
||||
class CBitcoinSecret : public CBase58Data
|
||||
{
|
||||
public:
|
||||
void SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
{
|
||||
assert(vchSecret.size() == 32);
|
||||
SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size());
|
||||
if (fCompressed)
|
||||
|
||||
22
src/bignum.h
22
src/bignum.h
@@ -122,16 +122,24 @@ public:
|
||||
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64 n)
|
||||
void setint64(int64 sn)
|
||||
{
|
||||
unsigned char pch[sizeof(n) + 6];
|
||||
unsigned char pch[sizeof(sn) + 6];
|
||||
unsigned char* p = pch + 4;
|
||||
bool fNegative = false;
|
||||
if (n < (int64)0)
|
||||
bool fNegative;
|
||||
uint64 n;
|
||||
|
||||
if (sn < (int64)0)
|
||||
{
|
||||
n = -n;
|
||||
// Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
|
||||
n = -(sn + 1);
|
||||
++n;
|
||||
fNegative = true;
|
||||
} else {
|
||||
n = sn;
|
||||
fNegative = false;
|
||||
}
|
||||
|
||||
bool fLeadingZeroes = true;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
@@ -297,7 +305,7 @@ public:
|
||||
psz++;
|
||||
|
||||
// hex string to bignum
|
||||
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 };
|
||||
static const 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))
|
||||
{
|
||||
@@ -408,7 +416,7 @@ public:
|
||||
CBigNum& operator>>=(unsigned int shift)
|
||||
{
|
||||
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of openssl
|
||||
// if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
|
||||
CBigNum a = 1;
|
||||
a <<= shift;
|
||||
if (BN_cmp(&a, this) > 0)
|
||||
|
||||
2726
src/bitcoinrpc.cpp
2726
src/bitcoinrpc.cpp
File diff suppressed because it is too large
Load Diff
150
src/bitcoinrpc.h
150
src/bitcoinrpc.h
@@ -7,15 +7,86 @@
|
||||
#define _BITCOINRPC_H_ 1
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
class CBlockIndex;
|
||||
|
||||
#include "json/json_spirit_reader_template.h"
|
||||
#include "json/json_spirit_writer_template.h"
|
||||
#include "json/json_spirit_utils.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
// HTTP status codes
|
||||
enum HTTPStatusCode
|
||||
{
|
||||
HTTP_OK = 200,
|
||||
HTTP_BAD_REQUEST = 400,
|
||||
HTTP_UNAUTHORIZED = 401,
|
||||
HTTP_FORBIDDEN = 403,
|
||||
HTTP_NOT_FOUND = 404,
|
||||
HTTP_INTERNAL_SERVER_ERROR = 500,
|
||||
};
|
||||
|
||||
// Bitcoin RPC error codes
|
||||
enum RPCErrorCode
|
||||
{
|
||||
// Standard JSON-RPC 2.0 errors
|
||||
RPC_INVALID_REQUEST = -32600,
|
||||
RPC_METHOD_NOT_FOUND = -32601,
|
||||
RPC_INVALID_PARAMS = -32602,
|
||||
RPC_INTERNAL_ERROR = -32603,
|
||||
RPC_PARSE_ERROR = -32700,
|
||||
|
||||
// General application defined errors
|
||||
RPC_MISC_ERROR = -1, // std::exception thrown in command handling
|
||||
RPC_FORBIDDEN_BY_SAFE_MODE = -2, // Server is in safe mode, and command is not allowed in safe mode
|
||||
RPC_TYPE_ERROR = -3, // Unexpected type was passed as parameter
|
||||
RPC_INVALID_ADDRESS_OR_KEY = -5, // Invalid address or key
|
||||
RPC_OUT_OF_MEMORY = -7, // Ran out of memory during operation
|
||||
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
|
||||
RPC_DATABASE_ERROR = -20, // Database error
|
||||
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
|
||||
|
||||
// P2P client errors
|
||||
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected
|
||||
RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks
|
||||
|
||||
// Wallet errors
|
||||
RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.)
|
||||
RPC_WALLET_INSUFFICIENT_FUNDS = -6, // Not enough funds in wallet or account
|
||||
RPC_WALLET_INVALID_ACCOUNT_NAME = -11, // Invalid account name
|
||||
RPC_WALLET_KEYPOOL_RAN_OUT = -12, // Keypool ran out, call keypoolrefill first
|
||||
RPC_WALLET_UNLOCK_NEEDED = -13, // Enter the wallet passphrase with walletpassphrase first
|
||||
RPC_WALLET_PASSPHRASE_INCORRECT = -14, // The wallet passphrase entered was incorrect
|
||||
RPC_WALLET_WRONG_ENC_STATE = -15, // Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.)
|
||||
RPC_WALLET_ENCRYPTION_FAILED = -16, // Failed to encrypt the wallet
|
||||
RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked
|
||||
};
|
||||
|
||||
json_spirit::Object JSONRPCError(int code, const std::string& message);
|
||||
|
||||
void ThreadRPCServer(void* parg);
|
||||
int CommandLineRPC(int argc, char *argv[]);
|
||||
|
||||
/** Convert parameter values for RPC call from strings to command-specific JSON objects. */
|
||||
json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams);
|
||||
|
||||
/*
|
||||
Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
|
||||
the right number of arguments are passed, just that any passed are the correct type.
|
||||
Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type));
|
||||
*/
|
||||
void RPCTypeCheck(const json_spirit::Array& params,
|
||||
const std::list<json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
|
||||
/*
|
||||
Check for expected keys/value types in an Object.
|
||||
Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type));
|
||||
*/
|
||||
void RPCTypeCheck(const json_spirit::Object& o,
|
||||
const std::map<std::string, json_spirit::Value_type>& typesExpected, bool fAllowNull=false);
|
||||
|
||||
typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
class CRPCCommand
|
||||
@@ -24,8 +95,12 @@ public:
|
||||
std::string name;
|
||||
rpcfn_type actor;
|
||||
bool okSafeMode;
|
||||
bool unlocked;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitcoin RPC command dispatcher.
|
||||
*/
|
||||
class CRPCTable
|
||||
{
|
||||
private:
|
||||
@@ -34,8 +109,83 @@ public:
|
||||
CRPCTable();
|
||||
const CRPCCommand* operator[](std::string name) const;
|
||||
std::string help(std::string name) const;
|
||||
|
||||
/**
|
||||
* Execute a method.
|
||||
* @param method Method to execute
|
||||
* @param params Array of arguments (JSON objects)
|
||||
* @returns Result of the call.
|
||||
* @throws an exception (json_spirit::Value) when an error happens.
|
||||
*/
|
||||
json_spirit::Value execute(const std::string &method, const json_spirit::Array ¶ms) const;
|
||||
};
|
||||
|
||||
extern const CRPCTable tableRPC;
|
||||
|
||||
extern int64 nWalletUnlockTime;
|
||||
extern int64 AmountFromValue(const json_spirit::Value& value);
|
||||
extern json_spirit::Value ValueFromAmount(int64 amount);
|
||||
extern double GetDifficulty(const CBlockIndex* blockindex = NULL);
|
||||
extern std::string HexBits(unsigned int nBits);
|
||||
extern std::string HelpRequiringPassphrase();
|
||||
extern void EnsureWalletIsUnlocked();
|
||||
|
||||
extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp
|
||||
extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
|
||||
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
|
||||
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp
|
||||
extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value setaccount(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getaccount(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getaddressesbyaccount(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendtoaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value signmessage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value verifymessage(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getbalance(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value movecmd(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendfrom(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendmany(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value backupwallet(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value keypoolrefill(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value walletpassphrase(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value walletpassphrasechange(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value walletlock(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value encryptwallet(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value validateaddress(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
|
||||
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
extern json_spirit::Value getblockcount(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp
|
||||
extern json_spirit::Value getdifficulty(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,30 +29,36 @@ namespace Checkpoints
|
||||
(105000, uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"))
|
||||
(134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
|
||||
(168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
|
||||
(185333, uint256("0x00000000000002334c71b8706940c20348af897a9cfc0f1a6dab0d14d4ceb815"))
|
||||
(193000, uint256("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317"))
|
||||
(210000, uint256("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e"))
|
||||
;
|
||||
|
||||
static MapCheckpoints mapCheckpointsTestnet =
|
||||
boost::assign::map_list_of
|
||||
( 546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"))
|
||||
;
|
||||
|
||||
bool CheckBlock(int nHeight, const uint256& hash)
|
||||
{
|
||||
if (fTestNet) return true; // Testnet has no checkpoints
|
||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||
|
||||
MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
|
||||
if (i == mapCheckpoints.end()) return true;
|
||||
MapCheckpoints::const_iterator i = checkpoints.find(nHeight);
|
||||
if (i == checkpoints.end()) return true;
|
||||
return hash == i->second;
|
||||
}
|
||||
|
||||
int GetTotalBlocksEstimate()
|
||||
{
|
||||
if (fTestNet) return 0;
|
||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||
|
||||
return mapCheckpoints.rbegin()->first;
|
||||
return checkpoints.rbegin()->first;
|
||||
}
|
||||
|
||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
|
||||
{
|
||||
if (fTestNet) return NULL;
|
||||
MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints);
|
||||
|
||||
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
|
||||
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
|
||||
{
|
||||
const uint256& hash = i.second;
|
||||
std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
|
||||
|
||||
19
src/clientversion.h
Normal file
19
src/clientversion.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef CLIENTVERSION_H
|
||||
#define CLIENTVERSION_H
|
||||
|
||||
//
|
||||
// client versioning
|
||||
//
|
||||
|
||||
// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 7
|
||||
#define CLIENT_VERSION_REVISION 2
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
|
||||
// Converts the parameter X to a string after macro replacement on X has been performed.
|
||||
// Don't merge these into one macro!
|
||||
#define STRINGIZE(X) DO_STRINGIZE(X)
|
||||
#define DO_STRINGIZE(X) #X
|
||||
|
||||
#endif // CLIENTVERSION_H
|
||||
@@ -17,12 +17,6 @@ bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::v
|
||||
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
|
||||
return false;
|
||||
|
||||
// Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
||||
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||
mlock(&chKey[0], sizeof chKey);
|
||||
mlock(&chIV[0], sizeof chIV);
|
||||
|
||||
int i = 0;
|
||||
if (nDerivationMethod == 0)
|
||||
i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0],
|
||||
@@ -44,12 +38,6 @@ bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigne
|
||||
if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE)
|
||||
return false;
|
||||
|
||||
// Try to keep the keydata out of swap
|
||||
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||
mlock(&chKey[0], sizeof chKey);
|
||||
mlock(&chIV[0], sizeof chIV);
|
||||
|
||||
memcpy(&chKey[0], &chNewKey[0], sizeof chKey);
|
||||
memcpy(&chIV[0], &chNewIV[0], sizeof chIV);
|
||||
|
||||
|
||||
@@ -78,19 +78,26 @@ public:
|
||||
{
|
||||
memset(&chKey, 0, sizeof chKey);
|
||||
memset(&chIV, 0, sizeof chIV);
|
||||
munlock(&chKey, sizeof chKey);
|
||||
munlock(&chIV, sizeof chIV);
|
||||
fKeySet = false;
|
||||
}
|
||||
|
||||
CCrypter()
|
||||
{
|
||||
fKeySet = false;
|
||||
|
||||
// Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
|
||||
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
|
||||
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
|
||||
LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey);
|
||||
LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV);
|
||||
}
|
||||
|
||||
~CCrypter()
|
||||
{
|
||||
CleanKey();
|
||||
|
||||
LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey);
|
||||
LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
649
src/db.cpp
649
src/db.cpp
@@ -26,45 +26,193 @@ unsigned int nWalletDBUpdated;
|
||||
// CDB
|
||||
//
|
||||
|
||||
CCriticalSection cs_db;
|
||||
static bool fDbEnvInit = false;
|
||||
bool fDetachDB = false;
|
||||
DbEnv dbenv(0);
|
||||
map<string, int> mapFileUseCount;
|
||||
static map<string, Db*> mapDb;
|
||||
CDBEnv bitdb;
|
||||
|
||||
static void EnvShutdown()
|
||||
void CDBEnv::EnvShutdown()
|
||||
{
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
|
||||
fDbEnvInit = false;
|
||||
try
|
||||
{
|
||||
dbenv.close(0);
|
||||
}
|
||||
catch (const DbException& e)
|
||||
{
|
||||
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
|
||||
}
|
||||
DbEnv(0).remove(GetDataDir().string().c_str(), 0);
|
||||
int ret = dbenv.close(0);
|
||||
if (ret != 0)
|
||||
printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
|
||||
if (!fMockDb)
|
||||
DbEnv(0).remove(strPath.c_str(), 0);
|
||||
}
|
||||
|
||||
class CDBInit
|
||||
CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
|
||||
{
|
||||
public:
|
||||
CDBInit()
|
||||
{
|
||||
}
|
||||
~CDBInit()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
fDbEnvInit = false;
|
||||
fMockDb = false;
|
||||
}
|
||||
|
||||
CDBEnv::~CDBEnv()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
|
||||
void CDBEnv::Close()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
|
||||
bool CDBEnv::Open(boost::filesystem::path pathEnv_)
|
||||
{
|
||||
if (fDbEnvInit)
|
||||
return true;
|
||||
|
||||
if (fShutdown)
|
||||
return false;
|
||||
|
||||
pathEnv = pathEnv_;
|
||||
filesystem::path pathDataDir = pathEnv;
|
||||
strPath = pathDataDir.string();
|
||||
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());
|
||||
|
||||
unsigned int nEnvFlags = 0;
|
||||
if (GetBoolArg("-privdb", true))
|
||||
nEnvFlags |= DB_PRIVATE;
|
||||
|
||||
int nDbCache = GetArg("-dbcache", 25);
|
||||
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(pathErrorFile.string().c_str(), "a")); /// debug
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
|
||||
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
|
||||
int ret = dbenv.open(strPath.c_str(),
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
DB_THREAD |
|
||||
DB_RECOVER |
|
||||
nEnvFlags,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret != 0)
|
||||
return error("CDB() : error %s (%d) opening database environment", DbEnv::strerror(ret), ret);
|
||||
|
||||
fDbEnvInit = true;
|
||||
fMockDb = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDBEnv::MakeMock()
|
||||
{
|
||||
if (fDbEnvInit)
|
||||
throw runtime_error("CDBEnv::MakeMock(): already initialized");
|
||||
|
||||
if (fShutdown)
|
||||
throw runtime_error("CDBEnv::MakeMock(): during shutdown");
|
||||
|
||||
printf("CDBEnv::MakeMock()\n");
|
||||
|
||||
dbenv.set_cachesize(1, 0, 1);
|
||||
dbenv.set_lg_bsize(10485760*4);
|
||||
dbenv.set_lg_max(10485760);
|
||||
dbenv.set_lk_max_locks(10000);
|
||||
dbenv.set_lk_max_objects(10000);
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
|
||||
int ret = dbenv.open(NULL,
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
DB_THREAD |
|
||||
DB_PRIVATE,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret > 0)
|
||||
throw runtime_error(strprintf("CDBEnv::MakeMock(): error %d opening database environment", ret));
|
||||
|
||||
fDbEnvInit = true;
|
||||
fMockDb = true;
|
||||
}
|
||||
|
||||
CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile))
|
||||
{
|
||||
LOCK(cs_db);
|
||||
assert(mapFileUseCount.count(strFile) == 0);
|
||||
|
||||
Db db(&dbenv, 0);
|
||||
int result = db.verify(strFile.c_str(), NULL, NULL, 0);
|
||||
if (result == 0)
|
||||
return VERIFY_OK;
|
||||
else if (recoverFunc == NULL)
|
||||
return RECOVER_FAIL;
|
||||
|
||||
// Try to recover:
|
||||
bool fRecovered = (*recoverFunc)(*this, strFile);
|
||||
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
|
||||
}
|
||||
|
||||
bool CDBEnv::Salvage(std::string strFile, bool fAggressive,
|
||||
std::vector<CDBEnv::KeyValPair >& vResult)
|
||||
{
|
||||
LOCK(cs_db);
|
||||
assert(mapFileUseCount.count(strFile) == 0);
|
||||
|
||||
u_int32_t flags = DB_SALVAGE;
|
||||
if (fAggressive) flags |= DB_AGGRESSIVE;
|
||||
|
||||
stringstream strDump;
|
||||
|
||||
Db db(&dbenv, 0);
|
||||
int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("ERROR: db salvage failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format of bdb dump is ascii lines:
|
||||
// header lines...
|
||||
// HEADER=END
|
||||
// hexadecimal key
|
||||
// hexadecimal value
|
||||
// ... repeated
|
||||
// DATA=END
|
||||
|
||||
string strLine;
|
||||
while (!strDump.eof() && strLine != "HEADER=END")
|
||||
getline(strDump, strLine); // Skip past header
|
||||
|
||||
std::string keyHex, valueHex;
|
||||
while (!strDump.eof() && keyHex != "DATA=END")
|
||||
{
|
||||
getline(strDump, keyHex);
|
||||
if (keyHex != "DATA_END")
|
||||
{
|
||||
getline(strDump, valueHex);
|
||||
vResult.push_back(make_pair(ParseHex(keyHex),ParseHex(valueHex)));
|
||||
}
|
||||
}
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
instance_of_cdbinit;
|
||||
|
||||
|
||||
CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
|
||||
void CDBEnv::CheckpointLSN(std::string strFile)
|
||||
{
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
if (fMockDb)
|
||||
return;
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
}
|
||||
|
||||
|
||||
CDB::CDB(const char *pszFile, const char* pszMode) :
|
||||
pdb(NULL), activeTxn(NULL)
|
||||
{
|
||||
int ret;
|
||||
if (pszFile == NULL)
|
||||
@@ -77,64 +225,38 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
|
||||
nFlags |= DB_CREATE;
|
||||
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (!fDbEnvInit)
|
||||
{
|
||||
if (fShutdown)
|
||||
return;
|
||||
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(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(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(pathDataDir.string().c_str(),
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
DB_INIT_LOG |
|
||||
DB_INIT_MPOOL |
|
||||
DB_INIT_TXN |
|
||||
DB_THREAD |
|
||||
DB_RECOVER,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret > 0)
|
||||
throw runtime_error(strprintf("CDB() : error %d opening database environment", ret));
|
||||
fDbEnvInit = true;
|
||||
}
|
||||
LOCK(bitdb.cs_db);
|
||||
if (!bitdb.Open(GetDataDir()))
|
||||
throw runtime_error("env open failed");
|
||||
|
||||
strFile = pszFile;
|
||||
++mapFileUseCount[strFile];
|
||||
pdb = mapDb[strFile];
|
||||
++bitdb.mapFileUseCount[strFile];
|
||||
pdb = bitdb.mapDb[strFile];
|
||||
if (pdb == NULL)
|
||||
{
|
||||
pdb = new Db(&dbenv, 0);
|
||||
pdb = new Db(&bitdb.dbenv, 0);
|
||||
|
||||
bool fMockDb = bitdb.IsMock();
|
||||
if (fMockDb)
|
||||
{
|
||||
DbMpoolFile*mpf = pdb->get_mpf();
|
||||
ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
|
||||
if (ret != 0)
|
||||
throw runtime_error(strprintf("CDB() : failed to configure for no temp file backing for database %s", pszFile));
|
||||
}
|
||||
|
||||
ret = pdb->open(NULL, // Txn pointer
|
||||
pszFile, // Filename
|
||||
fMockDb ? NULL : pszFile, // Filename
|
||||
"main", // Logical db name
|
||||
DB_BTREE, // Database type
|
||||
nFlags, // Flags
|
||||
0);
|
||||
|
||||
if (ret > 0)
|
||||
if (ret != 0)
|
||||
{
|
||||
delete pdb;
|
||||
pdb = NULL;
|
||||
{
|
||||
LOCK(cs_db);
|
||||
--mapFileUseCount[strFile];
|
||||
}
|
||||
--bitdb.mapFileUseCount[strFile];
|
||||
strFile = "";
|
||||
throw runtime_error(strprintf("CDB() : can't open database file %s, error %d", pszFile, ret));
|
||||
}
|
||||
@@ -147,40 +269,46 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
|
||||
fReadOnly = fTmp;
|
||||
}
|
||||
|
||||
mapDb[strFile] = pdb;
|
||||
bitdb.mapDb[strFile] = pdb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsChainFile(std::string strFile)
|
||||
{
|
||||
if (strFile == "blkindex.dat")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDB::Close()
|
||||
{
|
||||
if (!pdb)
|
||||
return;
|
||||
if (!vTxn.empty())
|
||||
vTxn.front()->abort();
|
||||
vTxn.clear();
|
||||
if (activeTxn)
|
||||
activeTxn->abort();
|
||||
activeTxn = NULL;
|
||||
pdb = NULL;
|
||||
|
||||
// Flush database activity from memory pool to disk log
|
||||
unsigned int nMinutes = 0;
|
||||
if (fReadOnly)
|
||||
nMinutes = 1;
|
||||
if (strFile == "addr.dat")
|
||||
if (IsChainFile(strFile))
|
||||
nMinutes = 2;
|
||||
if (strFile == "blkindex.dat")
|
||||
nMinutes = 2;
|
||||
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
|
||||
if (IsChainFile(strFile) && IsInitialBlockDownload())
|
||||
nMinutes = 5;
|
||||
|
||||
dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
|
||||
bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
|
||||
|
||||
{
|
||||
LOCK(cs_db);
|
||||
--mapFileUseCount[strFile];
|
||||
LOCK(bitdb.cs_db);
|
||||
--bitdb.mapFileUseCount[strFile];
|
||||
}
|
||||
}
|
||||
|
||||
void CloseDb(const string& strFile)
|
||||
void CDBEnv::CloseDb(const string& strFile)
|
||||
{
|
||||
{
|
||||
LOCK(cs_db);
|
||||
@@ -195,27 +323,35 @@ void CloseDb(const string& strFile)
|
||||
}
|
||||
}
|
||||
|
||||
bool CDBEnv::RemoveDb(const string& strFile)
|
||||
{
|
||||
this->CloseDb(strFile);
|
||||
|
||||
LOCK(cs_db);
|
||||
int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
|
||||
return (rc == 0);
|
||||
}
|
||||
|
||||
bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
{
|
||||
while (!fShutdown)
|
||||
{
|
||||
{
|
||||
LOCK(cs_db);
|
||||
if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
|
||||
LOCK(bitdb.cs_db);
|
||||
if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0)
|
||||
{
|
||||
// Flush log data to the dat file
|
||||
CloseDb(strFile);
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
mapFileUseCount.erase(strFile);
|
||||
bitdb.CloseDb(strFile);
|
||||
bitdb.CheckpointLSN(strFile);
|
||||
bitdb.mapFileUseCount.erase(strFile);
|
||||
|
||||
bool fSuccess = true;
|
||||
printf("Rewriting %s...\n", strFile.c_str());
|
||||
string strFileRes = strFile + ".rewrite";
|
||||
{ // surround usage of db with extra {}
|
||||
CDB db(strFile.c_str(), "r");
|
||||
Db* pdbCopy = new Db(&dbenv, 0);
|
||||
|
||||
Db* pdbCopy = new Db(&bitdb.dbenv, 0);
|
||||
|
||||
int ret = pdbCopy->open(NULL, // Txn pointer
|
||||
strFileRes.c_str(), // Filename
|
||||
"main", // Logical db name
|
||||
@@ -227,7 +363,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
printf("Cannot create database file %s\n", strFileRes.c_str());
|
||||
fSuccess = false;
|
||||
}
|
||||
|
||||
|
||||
Dbc* pcursor = db.GetCursor();
|
||||
if (pcursor)
|
||||
while (fSuccess)
|
||||
@@ -264,7 +400,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
if (fSuccess)
|
||||
{
|
||||
db.Close();
|
||||
CloseDb(strFile);
|
||||
bitdb.CloseDb(strFile);
|
||||
if (pdbCopy->close(0))
|
||||
fSuccess = false;
|
||||
delete pdbCopy;
|
||||
@@ -272,10 +408,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
}
|
||||
if (fSuccess)
|
||||
{
|
||||
Db dbA(&dbenv, 0);
|
||||
Db dbA(&bitdb.dbenv, 0);
|
||||
if (dbA.remove(strFile.c_str(), NULL, 0))
|
||||
fSuccess = false;
|
||||
Db dbB(&dbenv, 0);
|
||||
Db dbB(&bitdb.dbenv, 0);
|
||||
if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
|
||||
fSuccess = false;
|
||||
}
|
||||
@@ -290,11 +426,12 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
}
|
||||
|
||||
|
||||
void DBFlush(bool fShutdown)
|
||||
void CDBEnv::Flush(bool fShutdown)
|
||||
{
|
||||
int64 nStart = GetTimeMillis();
|
||||
// Flush log data to the actual data file
|
||||
// on all files that are not in use
|
||||
printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
|
||||
printf("Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started");
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
{
|
||||
@@ -311,9 +448,10 @@ void DBFlush(bool fShutdown)
|
||||
CloseDb(strFile);
|
||||
printf("%s checkpoint\n", strFile.c_str());
|
||||
dbenv.txn_checkpoint(0, 0, 0);
|
||||
if ((strFile != "blkindex.dat" && strFile != "addr.dat") || fDetachDB) {
|
||||
if (!IsChainFile(strFile) || fDetachDB) {
|
||||
printf("%s detach\n", strFile.c_str());
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
if (!fMockDb)
|
||||
dbenv.lsn_reset(strFile.c_str(), 0);
|
||||
}
|
||||
printf("%s closed\n", strFile.c_str());
|
||||
mapFileUseCount.erase(mi++);
|
||||
@@ -321,13 +459,14 @@ void DBFlush(bool fShutdown)
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
printf("DBFlush(%s)%s ended %15"PRI64d"ms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started", GetTimeMillis() - nStart);
|
||||
if (fShutdown)
|
||||
{
|
||||
char** listp;
|
||||
if (mapFileUseCount.empty())
|
||||
{
|
||||
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
|
||||
EnvShutdown();
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,66 +518,6 @@ bool CTxDB::ContainsTx(uint256 hash)
|
||||
return Exists(make_pair(string("tx"), hash));
|
||||
}
|
||||
|
||||
bool CTxDB::ReadOwnerTxes(uint160 hash160, int nMinHeight, vector<CTransaction>& vtx)
|
||||
{
|
||||
assert(!fClient);
|
||||
vtx.clear();
|
||||
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
return false;
|
||||
|
||||
unsigned int fFlags = DB_SET_RANGE;
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << string("owner") << hash160 << CDiskTxPos(0, 0, 0);
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
{
|
||||
pcursor->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unserialize
|
||||
string strType;
|
||||
uint160 hashItem;
|
||||
CDiskTxPos pos;
|
||||
int 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)
|
||||
break;
|
||||
if (nItemHeight >= nMinHeight)
|
||||
{
|
||||
vtx.resize(vtx.size()+1);
|
||||
if (!vtx.back().ReadFromDisk(pos))
|
||||
{
|
||||
pcursor->close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pcursor->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
|
||||
{
|
||||
assert(!fClient);
|
||||
@@ -470,11 +549,6 @@ bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
|
||||
return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
|
||||
}
|
||||
|
||||
bool CTxDB::EraseBlockIndex(uint256 hash)
|
||||
{
|
||||
return Erase(make_pair(string("blockindex"), hash));
|
||||
}
|
||||
|
||||
bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
|
||||
{
|
||||
return Read(string("hashBestChain"), hashBestChain);
|
||||
@@ -517,68 +591,9 @@ CBlockIndex static * InsertBlockIndex(uint256 hash)
|
||||
|
||||
bool CTxDB::LoadBlockIndex()
|
||||
{
|
||||
// Get database cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
if (!LoadBlockIndexGuts())
|
||||
return false;
|
||||
|
||||
// Load mapBlockIndex
|
||||
unsigned int fFlags = DB_SET_RANGE;
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << make_pair(string("blockindex"), uint256(0));
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
return false;
|
||||
|
||||
// Unserialize
|
||||
|
||||
try {
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "blockindex" && !fRequestShutdown)
|
||||
{
|
||||
CDiskBlockIndex diskindex;
|
||||
ssValue >> diskindex;
|
||||
|
||||
// Construct block index object
|
||||
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
|
||||
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
|
||||
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
|
||||
pindexNew->nFile = diskindex.nFile;
|
||||
pindexNew->nBlockPos = diskindex.nBlockPos;
|
||||
pindexNew->nHeight = diskindex.nHeight;
|
||||
pindexNew->nVersion = diskindex.nVersion;
|
||||
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
||||
pindexNew->nTime = diskindex.nTime;
|
||||
pindexNew->nBits = diskindex.nBits;
|
||||
pindexNew->nNonce = diskindex.nNonce;
|
||||
|
||||
// Watch for genesis block
|
||||
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
||||
pindexGenesisBlock = pindexNew;
|
||||
|
||||
if (!pindexNew->CheckIndex())
|
||||
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -609,7 +624,9 @@ bool CTxDB::LoadBlockIndex()
|
||||
pindexBest = mapBlockIndex[hashBestChain];
|
||||
nBestHeight = pindexBest->nHeight;
|
||||
bnBestChainWork = pindexBest->bnChainWork;
|
||||
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight);
|
||||
printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n",
|
||||
hashBestChain.ToString().substr(0,20).c_str(), nBestHeight,
|
||||
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
|
||||
|
||||
// Load bnBestInvalidWork, OK if it doesn't exist
|
||||
ReadBestInvalidWork(bnBestInvalidWork);
|
||||
@@ -626,7 +643,7 @@ bool CTxDB::LoadBlockIndex()
|
||||
map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
|
||||
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
|
||||
{
|
||||
if (pindex->nHeight < nBestHeight-nCheckDepth)
|
||||
if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
|
||||
break;
|
||||
CBlock block;
|
||||
if (!block.ReadFromDisk(pindex))
|
||||
@@ -728,7 +745,7 @@ bool CTxDB::LoadBlockIndex()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pindexFork)
|
||||
if (pindexFork && !fRequestShutdown)
|
||||
{
|
||||
// Reorg back to the fork
|
||||
printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
|
||||
@@ -744,71 +761,173 @@ bool CTxDB::LoadBlockIndex()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CAddrDB
|
||||
//
|
||||
|
||||
bool CAddrDB::WriteAddrman(const CAddrMan& addrman)
|
||||
bool CTxDB::LoadBlockIndexGuts()
|
||||
{
|
||||
return Write(string("addrman"), addrman);
|
||||
}
|
||||
|
||||
bool CAddrDB::LoadAddresses()
|
||||
{
|
||||
if (Read(string("addrman"), addrman))
|
||||
{
|
||||
printf("Loaded %i addresses\n", addrman.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read pre-0.6 addr records
|
||||
|
||||
vector<CAddress> vAddr;
|
||||
vector<vector<unsigned char> > vDelete;
|
||||
|
||||
// Get cursor
|
||||
// Get database cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
return false;
|
||||
|
||||
// Load mapBlockIndex
|
||||
unsigned int fFlags = DB_SET_RANGE;
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||
if (fFlags == DB_SET_RANGE)
|
||||
ssKey << make_pair(string("blockindex"), uint256(0));
|
||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
|
||||
fFlags = DB_NEXT;
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
return false;
|
||||
|
||||
// Unserialize
|
||||
|
||||
try {
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "addr")
|
||||
if (strType == "blockindex" && !fRequestShutdown)
|
||||
{
|
||||
CAddress addr;
|
||||
ssValue >> addr;
|
||||
vAddr.push_back(addr);
|
||||
CDiskBlockIndex diskindex;
|
||||
ssValue >> diskindex;
|
||||
|
||||
// Construct block index object
|
||||
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
|
||||
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
|
||||
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
|
||||
pindexNew->nFile = diskindex.nFile;
|
||||
pindexNew->nBlockPos = diskindex.nBlockPos;
|
||||
pindexNew->nHeight = diskindex.nHeight;
|
||||
pindexNew->nVersion = diskindex.nVersion;
|
||||
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
||||
pindexNew->nTime = diskindex.nTime;
|
||||
pindexNew->nBits = diskindex.nBits;
|
||||
pindexNew->nNonce = diskindex.nNonce;
|
||||
|
||||
// Watch for genesis block
|
||||
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
||||
pindexGenesisBlock = pindexNew;
|
||||
|
||||
if (!pindexNew->CheckIndex())
|
||||
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // if shutdown requested or finished loading block index
|
||||
}
|
||||
} // try
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
}
|
||||
pcursor->close();
|
||||
|
||||
addrman.Add(vAddr, CNetAddr("0.0.0.0"));
|
||||
printf("Loaded %i addresses\n", addrman.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Note: old records left; we ran into hangs-on-startup
|
||||
// bugs for some users who (we think) were running after
|
||||
// an unclean shutdown.
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CAddrDB
|
||||
//
|
||||
|
||||
|
||||
CAddrDB::CAddrDB()
|
||||
{
|
||||
pathAddr = GetDataDir() / "peers.dat";
|
||||
}
|
||||
|
||||
bool CAddrDB::Write(const CAddrMan& addr)
|
||||
{
|
||||
// Generate random temporary filename
|
||||
unsigned short randv = 0;
|
||||
RAND_bytes((unsigned char *)&randv, sizeof(randv));
|
||||
std::string tmpfn = strprintf("peers.dat.%04x", randv);
|
||||
|
||||
// serialize addresses, checksum data up to that point, then append csum
|
||||
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
|
||||
ssPeers << FLATDATA(pchMessageStart);
|
||||
ssPeers << addr;
|
||||
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
|
||||
ssPeers << hash;
|
||||
|
||||
// open temp output file, and associate with CAutoFile
|
||||
boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
|
||||
FILE *file = fopen(pathTmp.string().c_str(), "wb");
|
||||
CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return error("CAddrman::Write() : open failed");
|
||||
|
||||
// Write and commit header, data
|
||||
try {
|
||||
fileout << ssPeers;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Write() : I/O error");
|
||||
}
|
||||
FileCommit(fileout);
|
||||
fileout.fclose();
|
||||
|
||||
// replace existing peers.dat, if any, with new peers.dat.XXXX
|
||||
if (!RenameOver(pathTmp, pathAddr))
|
||||
return error("CAddrman::Write() : Rename-into-place failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadAddresses()
|
||||
bool CAddrDB::Read(CAddrMan& addr)
|
||||
{
|
||||
return CAddrDB("cr+").LoadAddresses();
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE *file = fopen(pathAddr.string().c_str(), "rb");
|
||||
CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
|
||||
if (!filein)
|
||||
return error("CAddrman::Read() : open failed");
|
||||
|
||||
// use file size to size memory buffer
|
||||
int fileSize = GetFilesize(filein);
|
||||
int dataSize = fileSize - sizeof(uint256);
|
||||
vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
uint256 hashIn;
|
||||
|
||||
// read data and checksum from file
|
||||
try {
|
||||
filein.read((char *)&vchData[0], dataSize);
|
||||
filein >> hashIn;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
|
||||
}
|
||||
filein.fclose();
|
||||
|
||||
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
|
||||
if (hashIn != hashTmp)
|
||||
return error("CAddrman::Read() : checksum mismatch; data corrupted");
|
||||
|
||||
unsigned char pchMsgTmp[4];
|
||||
try {
|
||||
// de-serialize file header (pchMessageStart magic number) and
|
||||
ssPeers >> FLATDATA(pchMsgTmp);
|
||||
|
||||
// verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
|
||||
return error("CAddrman::Read() : invalid network magic number");
|
||||
|
||||
// de-serialize address data into one CAddrMan object
|
||||
ssPeers >> addr;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() : I/O error or stream data corrupted");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
140
src/db.h
140
src/db.h
@@ -25,21 +25,81 @@ class CWallet;
|
||||
class CWalletTx;
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
extern bool fDetachDB;
|
||||
extern DbEnv dbenv;
|
||||
|
||||
extern void DBFlush(bool fShutdown);
|
||||
void ThreadFlushWalletDB(void* parg);
|
||||
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
|
||||
|
||||
|
||||
class CDBEnv
|
||||
{
|
||||
private:
|
||||
bool fDetachDB;
|
||||
bool fDbEnvInit;
|
||||
bool fMockDb;
|
||||
boost::filesystem::path pathEnv;
|
||||
std::string strPath;
|
||||
|
||||
void EnvShutdown();
|
||||
|
||||
public:
|
||||
mutable CCriticalSection cs_db;
|
||||
DbEnv dbenv;
|
||||
std::map<std::string, int> mapFileUseCount;
|
||||
std::map<std::string, Db*> mapDb;
|
||||
|
||||
CDBEnv();
|
||||
~CDBEnv();
|
||||
void MakeMock();
|
||||
bool IsMock() { return fMockDb; };
|
||||
|
||||
/*
|
||||
* Verify that database file strFile is OK. If it is not,
|
||||
* call the callback to try to recover.
|
||||
* This must be called BEFORE strFile is opened.
|
||||
* Returns true if strFile is OK.
|
||||
*/
|
||||
enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL };
|
||||
VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile));
|
||||
/*
|
||||
* Salvage data from a file that Verify says is bad.
|
||||
* fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
|
||||
* Appends binary key/value pairs to vResult, returns true if successful.
|
||||
* NOTE: reads the entire database into memory, so cannot be used
|
||||
* for huge databases.
|
||||
*/
|
||||
typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
|
||||
bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
|
||||
|
||||
bool Open(boost::filesystem::path pathEnv_);
|
||||
void Close();
|
||||
void Flush(bool fShutdown);
|
||||
void CheckpointLSN(std::string strFile);
|
||||
void SetDetach(bool fDetachDB_) { fDetachDB = fDetachDB_; }
|
||||
bool GetDetach() { return fDetachDB; }
|
||||
|
||||
void CloseDb(const std::string& strFile);
|
||||
bool RemoveDb(const std::string& strFile);
|
||||
|
||||
DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
|
||||
{
|
||||
DbTxn* ptxn = NULL;
|
||||
int ret = dbenv.txn_begin(NULL, &ptxn, flags);
|
||||
if (!ptxn || ret != 0)
|
||||
return NULL;
|
||||
return ptxn;
|
||||
}
|
||||
};
|
||||
|
||||
extern CDBEnv bitdb;
|
||||
|
||||
|
||||
/** RAII class that provides access to a Berkeley database */
|
||||
class CDB
|
||||
{
|
||||
protected:
|
||||
Db* pdb;
|
||||
std::string strFile;
|
||||
std::vector<DbTxn*> vTxn;
|
||||
DbTxn *activeTxn;
|
||||
bool fReadOnly;
|
||||
|
||||
explicit CDB(const char* pszFile, const char* pszMode="r+");
|
||||
@@ -66,7 +126,7 @@ protected:
|
||||
// Read
|
||||
Dbt datValue;
|
||||
datValue.set_flags(DB_DBT_MALLOC);
|
||||
int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
|
||||
int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
if (datValue.get_data() == NULL)
|
||||
return false;
|
||||
@@ -107,7 +167,7 @@ protected:
|
||||
Dbt datValue(&ssValue[0], ssValue.size());
|
||||
|
||||
// Write
|
||||
int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
|
||||
int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
|
||||
|
||||
// Clear memory in case it was a private key
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
@@ -130,7 +190,7 @@ protected:
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Erase
|
||||
int ret = pdb->del(GetTxn(), &datKey, 0);
|
||||
int ret = pdb->del(activeTxn, &datKey, 0);
|
||||
|
||||
// Clear memory
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
@@ -150,7 +210,7 @@ protected:
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
|
||||
// Exists
|
||||
int ret = pdb->exists(GetTxn(), &datKey, 0);
|
||||
int ret = pdb->exists(activeTxn, &datKey, 0);
|
||||
|
||||
// Clear memory
|
||||
memset(datKey.get_data(), 0, datKey.get_size());
|
||||
@@ -207,46 +267,33 @@ protected:
|
||||
return 0;
|
||||
}
|
||||
|
||||
DbTxn* GetTxn()
|
||||
{
|
||||
if (!vTxn.empty())
|
||||
return vTxn.back();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
bool TxnBegin()
|
||||
{
|
||||
if (!pdb)
|
||||
if (!pdb || activeTxn)
|
||||
return false;
|
||||
DbTxn* ptxn = NULL;
|
||||
int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_WRITE_NOSYNC);
|
||||
if (!ptxn || ret != 0)
|
||||
DbTxn* ptxn = bitdb.TxnBegin();
|
||||
if (!ptxn)
|
||||
return false;
|
||||
vTxn.push_back(ptxn);
|
||||
activeTxn = ptxn;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TxnCommit()
|
||||
{
|
||||
if (!pdb)
|
||||
if (!pdb || !activeTxn)
|
||||
return false;
|
||||
if (vTxn.empty())
|
||||
return false;
|
||||
int ret = vTxn.back()->commit(0);
|
||||
vTxn.pop_back();
|
||||
int ret = activeTxn->commit(0);
|
||||
activeTxn = NULL;
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
bool TxnAbort()
|
||||
{
|
||||
if (!pdb)
|
||||
if (!pdb || !activeTxn)
|
||||
return false;
|
||||
if (vTxn.empty())
|
||||
return false;
|
||||
int ret = vTxn.back()->abort();
|
||||
vTxn.pop_back();
|
||||
int ret = activeTxn->abort();
|
||||
activeTxn = NULL;
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
@@ -284,37 +331,32 @@ public:
|
||||
bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
|
||||
bool EraseTxIndex(const CTransaction& tx);
|
||||
bool ContainsTx(uint256 hash);
|
||||
bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx);
|
||||
bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
|
||||
bool ReadDiskTx(uint256 hash, CTransaction& tx);
|
||||
bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
|
||||
bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
|
||||
bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
|
||||
bool EraseBlockIndex(uint256 hash);
|
||||
bool ReadHashBestChain(uint256& hashBestChain);
|
||||
bool WriteHashBestChain(uint256 hashBestChain);
|
||||
bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
|
||||
bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
|
||||
bool LoadBlockIndex();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Access to the (IP) address database (addr.dat) */
|
||||
class CAddrDB : public CDB
|
||||
{
|
||||
public:
|
||||
CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
|
||||
private:
|
||||
CAddrDB(const CAddrDB&);
|
||||
void operator=(const CAddrDB&);
|
||||
public:
|
||||
bool WriteAddrman(const CAddrMan& addr);
|
||||
bool LoadAddresses();
|
||||
bool LoadBlockIndexGuts();
|
||||
};
|
||||
|
||||
bool LoadAddresses();
|
||||
|
||||
|
||||
|
||||
/** Access to the (IP) address database (peers.dat) */
|
||||
class CAddrDB
|
||||
{
|
||||
private:
|
||||
boost::filesystem::path pathAddr;
|
||||
public:
|
||||
CAddrDB();
|
||||
bool Write(const CAddrMan& addr);
|
||||
bool Read(CAddrMan& addr);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_DB_H
|
||||
|
||||
929
src/init.cpp
929
src/init.cpp
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ extern CWallet* pwalletMain;
|
||||
|
||||
void StartShutdown();
|
||||
void Shutdown(void* parg);
|
||||
bool AppInit(int argc, char* argv[]);
|
||||
bool AppInit2(int argc, char* argv[]);
|
||||
bool AppInit2();
|
||||
std::string HelpMessage();
|
||||
|
||||
#endif
|
||||
|
||||
49
src/irc.cpp
49
src/irc.cpp
@@ -12,7 +12,6 @@ using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
int nGotIRCAddresses = 0;
|
||||
bool fGotExternalIP = false;
|
||||
|
||||
void ThreadIRCSeed2(void* parg);
|
||||
|
||||
@@ -177,8 +176,6 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
|
||||
// Hybrid IRC used by lfnet always returns IP when you userhost yourself,
|
||||
// but in case another IRC is ever used this should work.
|
||||
printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
|
||||
if (fUseProxy)
|
||||
return false;
|
||||
CNetAddr addr(strHost, true);
|
||||
if (!addr.IsValid())
|
||||
return false;
|
||||
@@ -191,7 +188,9 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
|
||||
|
||||
void ThreadIRCSeed(void* parg)
|
||||
{
|
||||
IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg));
|
||||
// Make this thread recognisable as the IRC seeding thread
|
||||
RenameThread("bitcoin-ircseed");
|
||||
|
||||
try
|
||||
{
|
||||
ThreadIRCSeed2(parg);
|
||||
@@ -201,22 +200,27 @@ void ThreadIRCSeed(void* parg)
|
||||
} catch (...) {
|
||||
PrintExceptionContinue(NULL, "ThreadIRCSeed()");
|
||||
}
|
||||
printf("ThreadIRCSeed exiting\n");
|
||||
printf("ThreadIRCSeed exited\n");
|
||||
}
|
||||
|
||||
void ThreadIRCSeed2(void* parg)
|
||||
{
|
||||
/* Dont advertise on IRC if we don't allow incoming connections */
|
||||
if (mapArgs.count("-connect") || fNoListen)
|
||||
// Don't connect to IRC if we won't use IPv4 connections.
|
||||
if (IsLimited(NET_IPV4))
|
||||
return;
|
||||
|
||||
// ... or if we won't make outbound connections and won't accept inbound ones.
|
||||
if (mapArgs.count("-connect") && fNoListen)
|
||||
return;
|
||||
|
||||
// ... or if IRC is not enabled.
|
||||
if (!GetBoolArg("-irc", false))
|
||||
return;
|
||||
|
||||
printf("ThreadIRCSeed started\n");
|
||||
int nErrorWait = 10;
|
||||
int nRetryWait = 10;
|
||||
bool fNameInUse = false;
|
||||
int nNameRetry = 0;
|
||||
|
||||
while (!fShutdown)
|
||||
{
|
||||
@@ -248,11 +252,15 @@ void ThreadIRCSeed2(void* parg)
|
||||
return;
|
||||
}
|
||||
|
||||
CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses
|
||||
CService addrLocal;
|
||||
string strMyName;
|
||||
if (addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse)
|
||||
strMyName = EncodeAddress(addrLocalHost);
|
||||
else
|
||||
strMyName = strprintf("x%u", GetRand(1000000000));
|
||||
// Don't use our IP as our nick if we're not listening
|
||||
// or if it keeps failing because the nick is already in use.
|
||||
if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3)
|
||||
strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
|
||||
if (strMyName == "")
|
||||
strMyName = strprintf("x%"PRI64u"", GetRand(1000000000));
|
||||
|
||||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
|
||||
Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str());
|
||||
@@ -265,7 +273,7 @@ void ThreadIRCSeed2(void* parg)
|
||||
if (nRet == 2)
|
||||
{
|
||||
printf("IRC name already in use\n");
|
||||
fNameInUse = true;
|
||||
nNameRetry++;
|
||||
Wait(10);
|
||||
continue;
|
||||
}
|
||||
@@ -275,6 +283,7 @@ void ThreadIRCSeed2(void* parg)
|
||||
else
|
||||
return;
|
||||
}
|
||||
nNameRetry = 0;
|
||||
Sleep(500);
|
||||
|
||||
// Get our external IP from the IRC server and re-nick before joining the channel
|
||||
@@ -282,19 +291,19 @@ void ThreadIRCSeed2(void* parg)
|
||||
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
|
||||
{
|
||||
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
|
||||
if (!fUseProxy && addrFromIRC.IsRoutable())
|
||||
// Don't use our IP as our nick if we're not listening
|
||||
if (!fNoListen && addrFromIRC.IsRoutable())
|
||||
{
|
||||
// IRC lets you to re-nick
|
||||
fGotExternalIP = true;
|
||||
addrLocalHost.SetIP(addrFromIRC);
|
||||
strMyName = EncodeAddress(addrLocalHost);
|
||||
AddLocal(addrFromIRC, LOCAL_IRC);
|
||||
strMyName = EncodeAddress(GetLocalAddress(&addrConnect));
|
||||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fTestNet) {
|
||||
Send(hSocket, "JOIN #bitcoinTEST\r");
|
||||
Send(hSocket, "WHO #bitcoinTEST\r");
|
||||
Send(hSocket, "JOIN #bitcoinTEST3\r");
|
||||
Send(hSocket, "WHO #bitcoinTEST3\r");
|
||||
} else {
|
||||
// randomly join #bitcoin00-#bitcoin99
|
||||
int channel_number = GetRandInt(100);
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
void ThreadIRCSeed(void* parg);
|
||||
|
||||
extern int nGotIRCAddresses;
|
||||
extern bool fGotExternalIP;
|
||||
|
||||
#endif
|
||||
|
||||
55
src/key.cpp
55
src/key.cpp
@@ -8,7 +8,6 @@
|
||||
#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)
|
||||
@@ -49,7 +48,7 @@ err:
|
||||
|
||||
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
|
||||
// recid selects which key is recovered
|
||||
// if check is nonzero, additional checks are performed
|
||||
// if check is non-zero, additional checks are performed
|
||||
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
|
||||
{
|
||||
if (!eckey) return 0;
|
||||
@@ -130,6 +129,8 @@ void CKey::SetCompressedPubKey()
|
||||
void CKey::Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
if (pkey != NULL)
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
@@ -138,6 +139,7 @@ void CKey::Reset()
|
||||
|
||||
CKey::CKey()
|
||||
{
|
||||
pkey = NULL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -184,10 +186,24 @@ void CKey::MakeNewKey(bool fCompressed)
|
||||
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;
|
||||
if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
{
|
||||
// In testing, d2i_ECPrivateKey can return true
|
||||
// but fill in pkey with a key that fails
|
||||
// EC_KEY_check_key, so:
|
||||
if (EC_KEY_check_key(pkey))
|
||||
{
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If vchPrivKey data is bad d2i_ECPrivateKey() can
|
||||
// leave pkey in a state where calling EC_KEY_free()
|
||||
// crashes. To avoid that, set pkey to NULL and
|
||||
// leak the memory (a leak is better than a crash)
|
||||
pkey = NULL;
|
||||
Reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
@@ -240,18 +256,22 @@ CPrivKey CKey::GetPrivKey() const
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool CKey::SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
bool CKey::SetPubKey(const CPubKey& 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;
|
||||
const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
|
||||
if (o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
|
||||
{
|
||||
fSet = true;
|
||||
if (vchPubKey.vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
pkey = NULL;
|
||||
Reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CKey::GetPubKey() const
|
||||
CPubKey CKey::GetPubKey() const
|
||||
{
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
@@ -260,7 +280,7 @@ std::vector<unsigned char> CKey::GetPubKey() const
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return vchPubKey;
|
||||
return CPubKey(vchPubKey);
|
||||
}
|
||||
|
||||
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
@@ -375,6 +395,9 @@ bool CKey::IsValid()
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
if (!EC_KEY_check_key(pkey))
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
|
||||
62
src/key.h
62
src/key.h
@@ -9,7 +9,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "allocators.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_KEY definition
|
||||
|
||||
@@ -42,8 +44,62 @@ public:
|
||||
explicit key_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
/** A reference to a CKey: the Hash160 of its serialized public key */
|
||||
class CKeyID : public uint160
|
||||
{
|
||||
public:
|
||||
CKeyID() : uint160(0) { }
|
||||
CKeyID(const uint160 &in) : uint160(in) { }
|
||||
};
|
||||
|
||||
// secure_allocator is defined in serialize.h
|
||||
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
|
||||
class CScriptID : public uint160
|
||||
{
|
||||
public:
|
||||
CScriptID() : uint160(0) { }
|
||||
CScriptID(const uint160 &in) : uint160(in) { }
|
||||
};
|
||||
|
||||
/** An encapsulated public key. */
|
||||
class CPubKey {
|
||||
private:
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
friend class CKey;
|
||||
|
||||
public:
|
||||
CPubKey() { }
|
||||
CPubKey(const std::vector<unsigned char> &vchPubKeyIn) : vchPubKey(vchPubKeyIn) { }
|
||||
friend bool operator==(const CPubKey &a, const CPubKey &b) { return a.vchPubKey == b.vchPubKey; }
|
||||
friend bool operator!=(const CPubKey &a, const CPubKey &b) { return a.vchPubKey != b.vchPubKey; }
|
||||
friend bool operator<(const CPubKey &a, const CPubKey &b) { return a.vchPubKey < b.vchPubKey; }
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
READWRITE(vchPubKey);
|
||||
)
|
||||
|
||||
CKeyID GetID() const {
|
||||
return CKeyID(Hash160(vchPubKey));
|
||||
}
|
||||
|
||||
uint256 GetHash() const {
|
||||
return Hash(vchPubKey.begin(), vchPubKey.end());
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return vchPubKey.size() == 33 || vchPubKey.size() == 65;
|
||||
}
|
||||
|
||||
bool IsCompressed() const {
|
||||
return vchPubKey.size() == 33;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Raw() const {
|
||||
return vchPubKey;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// secure_allocator is defined in allocators.h
|
||||
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
||||
// CSecret is a serialization of just the secret parameter (32 bytes)
|
||||
@@ -78,8 +134,8 @@ public:
|
||||
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 SetPubKey(const CPubKey& vchPubKey);
|
||||
CPubKey GetPubKey() const;
|
||||
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "keystore.h"
|
||||
#include "script.h"
|
||||
|
||||
bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
|
||||
bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
|
||||
{
|
||||
CKey key;
|
||||
if (!GetKey(address, key))
|
||||
@@ -21,7 +21,7 @@ bool CBasicKeyStore::AddKey(const CKey& key)
|
||||
CSecret secret = key.GetSecret(fCompressed);
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
|
||||
mapKeys[key.GetPubKey().GetID()] = make_pair(secret, fCompressed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -30,12 +30,12 @@ bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
mapScripts[Hash160(redeemScript)] = redeemScript;
|
||||
mapScripts[redeemScript.GetID()] = redeemScript;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveCScript(const uint160& hash) const
|
||||
bool CBasicKeyStore::HaveCScript(const CScriptID& hash) const
|
||||
{
|
||||
bool result;
|
||||
{
|
||||
@@ -46,7 +46,7 @@ bool CBasicKeyStore::HaveCScript(const uint160& hash) const
|
||||
}
|
||||
|
||||
|
||||
bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
|
||||
bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@@ -73,6 +73,20 @@ bool CCryptoKeyStore::SetCrypted()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
{
|
||||
@@ -83,10 +97,10 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CSecret vchSecret;
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
@@ -99,6 +113,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
}
|
||||
vMasterKey = vMasterKeyIn;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -113,9 +128,9 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||
return false;
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
std::vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
bool fCompressed;
|
||||
if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
|
||||
@@ -125,19 +140,19 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
mapCryptedKeys[CBitcoinAddress(vchPubKey)] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@@ -147,10 +162,10 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const std::vector<unsigned char> &vchPubKey = (*mi).second.first;
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CSecret vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
return false;
|
||||
if (vchSecret.size() != 32)
|
||||
return false;
|
||||
@@ -162,7 +177,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const
|
||||
bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@@ -192,10 +207,10 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
CKey key;
|
||||
if (!key.SetSecret(mKey.second.first, mKey.second.second))
|
||||
return false;
|
||||
const std::vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||
const CPubKey vchPubKey = key.GetPubKey();
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
bool fCompressed;
|
||||
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#define BITCOIN_KEYSTORE_H
|
||||
|
||||
#include "crypter.h"
|
||||
#include "util.h"
|
||||
#include "base58.h"
|
||||
#include "sync.h"
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
class CScript;
|
||||
|
||||
@@ -24,17 +24,17 @@ public:
|
||||
virtual bool AddKey(const CKey& key) =0;
|
||||
|
||||
// Check whether a key corresponding to a given address is present in the store.
|
||||
virtual bool HaveKey(const CBitcoinAddress &address) const =0;
|
||||
virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0;
|
||||
virtual void GetKeys(std::set<CBitcoinAddress> &setAddress) const =0;
|
||||
virtual bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
|
||||
virtual bool HaveKey(const CKeyID &address) const =0;
|
||||
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
|
||||
virtual void GetKeys(std::set<CKeyID> &setAddress) const =0;
|
||||
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
|
||||
// Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
|
||||
virtual bool AddCScript(const CScript& redeemScript) =0;
|
||||
virtual bool HaveCScript(const uint160 &hash) const =0;
|
||||
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const =0;
|
||||
virtual bool HaveCScript(const CScriptID &hash) const =0;
|
||||
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
|
||||
|
||||
virtual bool GetSecret(const CBitcoinAddress &address, CSecret& vchSecret, bool &fCompressed) const
|
||||
virtual bool GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const
|
||||
{
|
||||
CKey key;
|
||||
if (!GetKey(address, key))
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<CBitcoinAddress, std::pair<CSecret, bool> > KeyMap;
|
||||
typedef std::map<uint160, CScript > ScriptMap;
|
||||
typedef std::map<CKeyID, std::pair<CSecret, bool> > KeyMap;
|
||||
typedef std::map<CScriptID, CScript > ScriptMap;
|
||||
|
||||
/** Basic key store, that keeps keys in an address->secret map */
|
||||
class CBasicKeyStore : public CKeyStore
|
||||
@@ -56,7 +56,7 @@ protected:
|
||||
|
||||
public:
|
||||
bool AddKey(const CKey& key);
|
||||
bool HaveKey(const CBitcoinAddress &address) const
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
bool result;
|
||||
{
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void GetKeys(std::set<CBitcoinAddress> &setAddress) const
|
||||
void GetKeys(std::set<CKeyID> &setAddress) const
|
||||
{
|
||||
setAddress.clear();
|
||||
{
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
|
||||
bool GetKey(const CKeyID &address, CKey &keyOut) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@@ -93,11 +93,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
virtual bool AddCScript(const CScript& redeemScript);
|
||||
virtual bool HaveCScript(const uint160 &hash) const;
|
||||
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const;
|
||||
virtual bool HaveCScript(const CScriptID &hash) const;
|
||||
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const;
|
||||
};
|
||||
|
||||
typedef std::map<CBitcoinAddress, std::pair<std::vector<unsigned char>, std::vector<unsigned char> > > CryptedKeyMap;
|
||||
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
|
||||
|
||||
/** Keystore which keeps the private keys encrypted.
|
||||
* It derives from the basic key store, which is used if no encryption is active.
|
||||
@@ -143,22 +143,11 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
bool Lock();
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKey(const CKey& key);
|
||||
bool HaveKey(const CBitcoinAddress &address) const
|
||||
bool HaveKey(const CKeyID &address) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
@@ -168,9 +157,9 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const;
|
||||
bool GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char>& vchPubKeyOut) const;
|
||||
void GetKeys(std::set<CBitcoinAddress> &setAddress) const
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
|
||||
void GetKeys(std::set<CKeyID> &setAddress) const
|
||||
{
|
||||
if (!IsCrypted())
|
||||
{
|
||||
@@ -185,6 +174,11 @@ public:
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
843
src/main.cpp
843
src/main.cpp
File diff suppressed because it is too large
Load Diff
334
src/main.h
334
src/main.h
@@ -6,13 +6,10 @@
|
||||
#define BITCOIN_MAIN_H
|
||||
|
||||
#include "bignum.h"
|
||||
#include "sync.h"
|
||||
#include "net.h"
|
||||
#include "script.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h> /* for _commit */
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
|
||||
class CWallet;
|
||||
@@ -30,13 +27,14 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
||||
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
||||
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
||||
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
||||
static const unsigned int MAX_INV_SZ = 50000;
|
||||
static const int64 MIN_TX_FEE = 50000;
|
||||
static const int64 MIN_RELAY_TX_FEE = 10000;
|
||||
static const int64 MAX_MONEY = 21000000 * COIN;
|
||||
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
|
||||
static const int COINBASE_MATURITY = 100;
|
||||
// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
|
||||
static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
||||
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
||||
#ifdef USE_UPNP
|
||||
static const int fHaveUPnP = true;
|
||||
#else
|
||||
@@ -69,12 +67,13 @@ extern int64 nHPSTimerStart;
|
||||
extern int64 nTimeBestReceived;
|
||||
extern CCriticalSection cs_setpwalletRegistered;
|
||||
extern std::set<CWallet*> setpwalletRegistered;
|
||||
extern unsigned char pchMessageStart[4];
|
||||
|
||||
// Settings
|
||||
extern int64 nTransactionFee;
|
||||
|
||||
|
||||
|
||||
// Minimum disk space required - used in CheckDiskSpace()
|
||||
static const uint64 nMinDiskSpace = 52428800;
|
||||
|
||||
|
||||
class CReserveKey;
|
||||
@@ -83,14 +82,17 @@ class CTxIndex;
|
||||
|
||||
void RegisterWallet(CWallet* pwalletIn);
|
||||
void UnregisterWallet(CWallet* pwalletIn);
|
||||
void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
|
||||
bool ProcessBlock(CNode* pfrom, CBlock* pblock);
|
||||
bool CheckDiskSpace(uint64 nAdditionalBytes=0);
|
||||
FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
|
||||
FILE* AppendBlockFile(unsigned int& nFileRet);
|
||||
bool LoadBlockIndex(bool fAllowNew=true);
|
||||
void PrintBlockTree();
|
||||
CBlockIndex* FindBlockByHeight(int nHeight);
|
||||
bool ProcessMessages(CNode* pfrom);
|
||||
bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||
bool LoadExternalBlockFile(FILE* fileIn);
|
||||
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
|
||||
CBlock* CreateNewBlock(CReserveKey& reservekey);
|
||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
||||
@@ -101,7 +103,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
|
||||
int GetNumBlocksOfPeers();
|
||||
bool IsInitialBlockDownload();
|
||||
std::string GetWarnings(std::string strFor);
|
||||
|
||||
bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
|
||||
|
||||
|
||||
|
||||
@@ -136,8 +138,8 @@ public:
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
|
||||
void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
|
||||
bool IsNull() const { return (nFile == -1); }
|
||||
void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; }
|
||||
bool IsNull() const { return (nFile == (unsigned int) -1); }
|
||||
|
||||
friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
|
||||
{
|
||||
@@ -156,7 +158,7 @@ public:
|
||||
if (IsNull())
|
||||
return "null";
|
||||
else
|
||||
return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
|
||||
return strprintf("(nFile=%u, nBlockPos=%u, nTxPos=%u)", nFile, nBlockPos, nTxPos);
|
||||
}
|
||||
|
||||
void print() const
|
||||
@@ -176,8 +178,8 @@ public:
|
||||
|
||||
CInPoint() { SetNull(); }
|
||||
CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
|
||||
void SetNull() { ptx = NULL; n = -1; }
|
||||
bool IsNull() const { return (ptx == NULL && n == -1); }
|
||||
void SetNull() { ptx = NULL; n = (unsigned int) -1; }
|
||||
bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); }
|
||||
};
|
||||
|
||||
|
||||
@@ -192,8 +194,8 @@ public:
|
||||
COutPoint() { SetNull(); }
|
||||
COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
|
||||
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
|
||||
void SetNull() { hash = 0; n = -1; }
|
||||
bool IsNull() const { return (hash == 0 && n == -1); }
|
||||
void SetNull() { hash = 0; n = (unsigned int) -1; }
|
||||
bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); }
|
||||
|
||||
friend bool operator<(const COutPoint& a, const COutPoint& b)
|
||||
{
|
||||
@@ -212,7 +214,7 @@ public:
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
|
||||
return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n);
|
||||
}
|
||||
|
||||
void print() const
|
||||
@@ -386,6 +388,7 @@ typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
|
||||
class CTransaction
|
||||
{
|
||||
public:
|
||||
static const int CURRENT_VERSION=1;
|
||||
int nVersion;
|
||||
std::vector<CTxIn> vin;
|
||||
std::vector<CTxOut> vout;
|
||||
@@ -411,7 +414,7 @@ public:
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nVersion = CTransaction::CURRENT_VERSION;
|
||||
vin.clear();
|
||||
vout.clear();
|
||||
nLockTime = 0;
|
||||
@@ -537,53 +540,7 @@ public:
|
||||
return dPriority > COIN * 144 / 250;
|
||||
}
|
||||
|
||||
int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const
|
||||
{
|
||||
// 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, PROTOCOL_VERSION);
|
||||
unsigned int nNewBlockSize = nBlockSize + nBytes;
|
||||
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
|
||||
|
||||
if (fAllowFree)
|
||||
{
|
||||
if (nBlockSize == 1)
|
||||
{
|
||||
// Transactions under 10K are free
|
||||
// (about 4500bc if made of 50bc inputs)
|
||||
if (nBytes < 10000)
|
||||
nMinFee = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Free transaction area
|
||||
if (nNewBlockSize < 27000)
|
||||
nMinFee = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
|
||||
return MAX_MONEY;
|
||||
nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
|
||||
}
|
||||
|
||||
if (!MoneyRange(nMinFee))
|
||||
nMinFee = MAX_MONEY;
|
||||
return nMinFee;
|
||||
}
|
||||
|
||||
int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const;
|
||||
|
||||
bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
|
||||
{
|
||||
@@ -629,7 +586,7 @@ public:
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string str;
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
|
||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n",
|
||||
GetHash().ToString().substr(0,10).c_str(),
|
||||
nVersion,
|
||||
vin.size(),
|
||||
@@ -796,7 +753,7 @@ public:
|
||||
return !(a == b);
|
||||
}
|
||||
int GetDepthInMainChain() const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -817,6 +774,7 @@ class CBlock
|
||||
{
|
||||
public:
|
||||
// header
|
||||
static const int CURRENT_VERSION=2;
|
||||
int nVersion;
|
||||
uint256 hashPrevBlock;
|
||||
uint256 hashMerkleRoot;
|
||||
@@ -858,7 +816,7 @@ public:
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nVersion = CBlock::CURRENT_VERSION;
|
||||
hashPrevBlock = 0;
|
||||
hashMerkleRoot = 0;
|
||||
nTime = 0;
|
||||
@@ -959,13 +917,7 @@ public:
|
||||
// Flush stdio buffers and commit to disk before returning
|
||||
fflush(fileout);
|
||||
if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
_commit(_fileno(fileout));
|
||||
#else
|
||||
fsync(fileno(fileout));
|
||||
#endif
|
||||
}
|
||||
FileCommit(fileout);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1000,7 +952,7 @@ public:
|
||||
|
||||
void print() const
|
||||
{
|
||||
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
|
||||
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
|
||||
GetHash().ToString().substr(0,20).c_str(),
|
||||
nVersion,
|
||||
hashPrevBlock.ToString().substr(0,20).c_str(),
|
||||
@@ -1020,11 +972,11 @@ public:
|
||||
|
||||
|
||||
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
|
||||
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
|
||||
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false);
|
||||
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
|
||||
bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
|
||||
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
|
||||
bool CheckBlock() const;
|
||||
bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
|
||||
bool AcceptBlock();
|
||||
|
||||
private:
|
||||
@@ -1138,21 +1090,6 @@ public:
|
||||
return CheckProofOfWork(GetBlockHash(), nBits);
|
||||
}
|
||||
|
||||
bool EraseBlockFromDisk()
|
||||
{
|
||||
// Open history file
|
||||
CAutoFile fileout = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb+"), SER_DISK, CLIENT_VERSION);
|
||||
if (!fileout)
|
||||
return false;
|
||||
|
||||
// Overwrite with empty null block
|
||||
CBlock block;
|
||||
block.SetNull();
|
||||
fileout << block;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum { nMedianTimeSpan=11 };
|
||||
|
||||
int64 GetMedianTimePast() const
|
||||
@@ -1181,11 +1118,17 @@ public:
|
||||
return pindex->GetMedianTimePast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are nRequired or more blocks of minVersion or above
|
||||
* in the last nToCheck blocks, starting at pstart and going backwards.
|
||||
*/
|
||||
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
|
||||
unsigned int nRequired, unsigned int nToCheck);
|
||||
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6u nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||
pprev, pnext, nFile, nBlockPos, nHeight,
|
||||
hashMerkleRoot.ToString().substr(0,10).c_str(),
|
||||
GetBlockHash().ToString().substr(0,20).c_str());
|
||||
@@ -1408,207 +1351,6 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** Alerts are for notifying old versions if they become too obsolete and
|
||||
* need to upgrade. The message is displayed in the status bar.
|
||||
* Alert messages are broadcast as a vector of signed data. Unserializing may
|
||||
* not read the entire buffer if the alert is for a newer version, but older
|
||||
* versions can still relay the original data.
|
||||
*/
|
||||
class CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
int nVersion;
|
||||
int64 nRelayUntil; // when newer nodes stop relaying to newer nodes
|
||||
int64 nExpiration;
|
||||
int nID;
|
||||
int nCancel;
|
||||
std::set<int> setCancel;
|
||||
int nMinVer; // lowest version inclusive
|
||||
int nMaxVer; // highest version inclusive
|
||||
std::set<std::string> setSubVer; // empty matches all
|
||||
int nPriority;
|
||||
|
||||
// Actions
|
||||
std::string strComment;
|
||||
std::string strStatusBar;
|
||||
std::string strReserved;
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(nRelayUntil);
|
||||
READWRITE(nExpiration);
|
||||
READWRITE(nID);
|
||||
READWRITE(nCancel);
|
||||
READWRITE(setCancel);
|
||||
READWRITE(nMinVer);
|
||||
READWRITE(nMaxVer);
|
||||
READWRITE(setSubVer);
|
||||
READWRITE(nPriority);
|
||||
|
||||
READWRITE(strComment);
|
||||
READWRITE(strStatusBar);
|
||||
READWRITE(strReserved);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nRelayUntil = 0;
|
||||
nExpiration = 0;
|
||||
nID = 0;
|
||||
nCancel = 0;
|
||||
setCancel.clear();
|
||||
nMinVer = 0;
|
||||
nMaxVer = 0;
|
||||
setSubVer.clear();
|
||||
nPriority = 0;
|
||||
|
||||
strComment.clear();
|
||||
strStatusBar.clear();
|
||||
strReserved.clear();
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string strSetCancel;
|
||||
BOOST_FOREACH(int n, setCancel)
|
||||
strSetCancel += strprintf("%d ", n);
|
||||
std::string strSetSubVer;
|
||||
BOOST_FOREACH(std::string str, setSubVer)
|
||||
strSetSubVer += "\"" + str + "\" ";
|
||||
return strprintf(
|
||||
"CAlert(\n"
|
||||
" nVersion = %d\n"
|
||||
" nRelayUntil = %"PRI64d"\n"
|
||||
" nExpiration = %"PRI64d"\n"
|
||||
" nID = %d\n"
|
||||
" nCancel = %d\n"
|
||||
" setCancel = %s\n"
|
||||
" nMinVer = %d\n"
|
||||
" nMaxVer = %d\n"
|
||||
" setSubVer = %s\n"
|
||||
" nPriority = %d\n"
|
||||
" strComment = \"%s\"\n"
|
||||
" strStatusBar = \"%s\"\n"
|
||||
")\n",
|
||||
nVersion,
|
||||
nRelayUntil,
|
||||
nExpiration,
|
||||
nID,
|
||||
nCancel,
|
||||
strSetCancel.c_str(),
|
||||
nMinVer,
|
||||
nMaxVer,
|
||||
strSetSubVer.c_str(),
|
||||
nPriority,
|
||||
strComment.c_str(),
|
||||
strStatusBar.c_str());
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
printf("%s", ToString().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
||||
class CAlert : public CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
std::vector<unsigned char> vchMsg;
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CAlert()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(vchMsg);
|
||||
READWRITE(vchSig);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
CUnsignedAlert::SetNull();
|
||||
vchMsg.clear();
|
||||
vchSig.clear();
|
||||
}
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return (nExpiration == 0);
|
||||
}
|
||||
|
||||
uint256 GetHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
bool IsInEffect() const
|
||||
{
|
||||
return (GetAdjustedTime() < nExpiration);
|
||||
}
|
||||
|
||||
bool Cancels(const CAlert& alert) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false; // this was a no-op before 31403
|
||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||
}
|
||||
|
||||
bool AppliesTo(int nVersion, std::string strSubVerIn) const
|
||||
{
|
||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
||||
return (IsInEffect() &&
|
||||
nMinVer <= nVersion && nVersion <= nMaxVer &&
|
||||
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
|
||||
}
|
||||
|
||||
bool AppliesToMe() const
|
||||
{
|
||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
|
||||
}
|
||||
|
||||
bool RelayTo(CNode* pnode) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
// returns true if wasn't already contained in the set
|
||||
if (pnode->setKnown.insert(GetHash()).second)
|
||||
{
|
||||
if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
|
||||
AppliesToMe() ||
|
||||
GetAdjustedTime() < nRelayUntil)
|
||||
{
|
||||
pnode->PushMessage("alert", *this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckSignature()
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
|
||||
return error("CAlert::CheckSignature() : SetPubKey failed");
|
||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||
return error("CAlert::CheckSignature() : verify signature failed");
|
||||
|
||||
// Now unserialize the data
|
||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||
sMsg >> *(CUnsignedAlert*)this;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessAlert();
|
||||
};
|
||||
|
||||
class CTxMemPool
|
||||
{
|
||||
public:
|
||||
@@ -1618,8 +1360,10 @@ public:
|
||||
|
||||
bool accept(CTxDB& txdb, CTransaction &tx,
|
||||
bool fCheckInputs, bool* pfMissingInputs);
|
||||
bool addUnchecked(CTransaction &tx);
|
||||
bool addUnchecked(const uint256& hash, CTransaction &tx);
|
||||
bool remove(CTransaction &tx);
|
||||
void clear();
|
||||
void queryHashes(std::vector<uint256>& vtxid);
|
||||
|
||||
unsigned long size()
|
||||
{
|
||||
|
||||
@@ -1,50 +1,62 @@
|
||||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# 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.
|
||||
|
||||
DEPSDIR:=/usr/i586-mingw32msvc
|
||||
|
||||
USE_UPNP:=0
|
||||
USE_IPV6:=1
|
||||
|
||||
INCLUDEPATHS= \
|
||||
-I"$(DEPSDIR)/boost_1_47_0" \
|
||||
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-I"$(DEPSDIR)/openssl-1.0.1b/include" \
|
||||
-I"$(DEPSDIR)" \
|
||||
-I"$(CURDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
-I"$(DEPSDIR)/boost_1_50_0" \
|
||||
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-I"$(DEPSDIR)/openssl-1.0.1c/include" \
|
||||
-I"$(DEPSDIR)"
|
||||
|
||||
LIBPATHS= \
|
||||
-L"$(DEPSDIR)/boost_1_47_0/stage/lib" \
|
||||
-L"$(DEPSDIR)/boost_1_50_0/stage/lib" \
|
||||
-L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-L"$(DEPSDIR)/openssl-1.0.1b"
|
||||
-L"$(DEPSDIR)/openssl-1.0.1c"
|
||||
|
||||
LIBS= \
|
||||
-l boost_system-mt-s \
|
||||
-l boost_filesystem-mt-s \
|
||||
-l boost_program_options-mt-s \
|
||||
-l boost_thread_win32-mt-s \
|
||||
-l boost_chrono-mt-s \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
|
||||
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)
|
||||
CFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifdef USE_UPNP
|
||||
ifndef USE_UPNP
|
||||
override USE_UPNP = -
|
||||
endif
|
||||
ifneq (${USE_UPNP}, -)
|
||||
LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
|
||||
LIBS += -l miniupnpc -l iphlpapi
|
||||
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
||||
endif
|
||||
|
||||
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
|
||||
|
||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/alert.o \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
@@ -60,7 +72,13 @@ OBJS= \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/rpcnet.o \
|
||||
obj/rpcmining.o \
|
||||
obj/rpcwallet.o \
|
||||
obj/rpcblockchain.o \
|
||||
obj/rpcrawtransaction.o \
|
||||
obj/script.o \
|
||||
obj/sync.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
@@ -77,7 +95,7 @@ obj/%.o: %.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
@@ -85,7 +103,7 @@ obj-test/%.o: test/%.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(TESTDEFS) $(CFLAGS) -o $@ $<
|
||||
|
||||
test_bitcoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
|
||||
i586-mingw32msvc-g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
|
||||
|
||||
|
||||
clean:
|
||||
@@ -93,6 +111,6 @@ clean:
|
||||
-rm -f bitcoind.exe
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f test_bitcoin.exe
|
||||
-rm -f src/build.h
|
||||
-rm -f obj/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -1,47 +1,58 @@
|
||||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# 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.
|
||||
|
||||
USE_UPNP:=0
|
||||
USE_IPV6:=1
|
||||
|
||||
INCLUDEPATHS= \
|
||||
-I"C:\boost-1.47.0-mgw" \
|
||||
-I"C:\boost-1.50.0-mgw" \
|
||||
-I"C:\db-4.8.30.NC-mgw\build_unix" \
|
||||
-I"C:\openssl-1.0.1b-mgw\include"
|
||||
-I"C:\openssl-1.0.1c-mgw\include"
|
||||
|
||||
LIBPATHS= \
|
||||
-L"C:\boost-1.47.0-mgw\stage\lib" \
|
||||
-L"C:\boost-1.50.0-mgw\stage\lib" \
|
||||
-L"C:\db-4.8.30.NC-mgw\build_unix" \
|
||||
-L"C:\openssl-1.0.1b-mgw"
|
||||
-L"C:\openssl-1.0.1c-mgw"
|
||||
|
||||
LIBS= \
|
||||
-l boost_system-mgw45-mt-s-1_47 \
|
||||
-l boost_filesystem-mgw45-mt-s-1_47 \
|
||||
-l boost_program_options-mgw45-mt-s-1_47 \
|
||||
-l boost_thread-mgw45-mt-s-1_47 \
|
||||
-l boost_system-mgw45-mt-s-1_50 \
|
||||
-l boost_filesystem-mgw45-mt-s-1_50 \
|
||||
-l boost_program_options-mgw45-mt-s-1_50 \
|
||||
-l boost_thread-mgw45-mt-s-1_50 \
|
||||
-l boost_chrono-mgw45-mt-s-1_50 \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
|
||||
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
|
||||
DEBUGFLAGS=-g
|
||||
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
CFLAGS=-mthreads -O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifdef USE_UPNP
|
||||
ifndef USE_UPNP
|
||||
override USE_UPNP = -
|
||||
endif
|
||||
ifneq (${USE_UPNP}, -)
|
||||
INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw"
|
||||
LIBPATHS += -L"C:\miniupnpc-1.6-mgw"
|
||||
LIBS += -l miniupnpc -l iphlpapi
|
||||
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
||||
endif
|
||||
|
||||
LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
|
||||
|
||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/alert.o \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
@@ -57,7 +68,13 @@ OBJS= \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/rpcnet.o \
|
||||
obj/rpcmining.o \
|
||||
obj/rpcwallet.o \
|
||||
obj/rpcblockchain.o \
|
||||
obj/rpcrawtransaction.o \
|
||||
obj/script.o \
|
||||
obj/sync.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
@@ -66,11 +83,14 @@ OBJS= \
|
||||
|
||||
all: bitcoind.exe
|
||||
|
||||
test check: test_bitcoin.exe FORCE
|
||||
test_bitcoin.exe
|
||||
|
||||
obj/%.o: %.cpp $(HEADERS)
|
||||
g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
@@ -78,10 +98,11 @@ 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)
|
||||
g++ $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework $(LIBS)
|
||||
|
||||
clean:
|
||||
-del /Q bitcoind test_bitcoin
|
||||
-del /Q obj\*
|
||||
-del /Q obj-test\*
|
||||
-del /Q build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- mode: Makefile; -*-
|
||||
# Copyright (c) 2011 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.
|
||||
|
||||
# Mac OS X makefile for bitcoin
|
||||
# Originally by Laszlo Hanyecz (solar@heliacal.net)
|
||||
@@ -20,6 +20,7 @@ LIBPATHS= \
|
||||
-L"$(DEPSDIR)/lib/db48"
|
||||
|
||||
USE_UPNP:=1
|
||||
USE_IPV6:=1
|
||||
|
||||
LIBS= -dead_strip
|
||||
|
||||
@@ -65,10 +66,11 @@ CFLAGS = -g
|
||||
endif
|
||||
|
||||
# ppc doesn't work because we don't support big-endian
|
||||
CFLAGS += -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wformat-security \
|
||||
CFLAGS += -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
|
||||
$(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
|
||||
OBJS= \
|
||||
obj/alert.o \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
@@ -84,13 +86,22 @@ OBJS= \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/rpcnet.o \
|
||||
obj/rpcmining.o \
|
||||
obj/rpcwallet.o \
|
||||
obj/rpcblockchain.o \
|
||||
obj/rpcrawtransaction.o \
|
||||
obj/script.o \
|
||||
obj/sync.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o
|
||||
|
||||
ifdef USE_UPNP
|
||||
ifndef USE_UPNP
|
||||
override USE_UPNP = -
|
||||
endif
|
||||
ifneq (${USE_UPNP}, -)
|
||||
DEFS += -DUSE_UPNP=$(USE_UPNP)
|
||||
ifdef STATIC
|
||||
LIBS += $(DEPSDIR)/lib/libminiupnpc.a
|
||||
@@ -99,8 +110,15 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
all: bitcoind
|
||||
|
||||
test check: test_bitcoin FORCE
|
||||
./test_bitcoin
|
||||
|
||||
# auto-generated dependencies:
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
@@ -111,7 +129,7 @@ version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
|
||||
$(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
|
||||
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
|
||||
@@ -123,7 +141,7 @@ bitcoind: $(OBJS:obj/%=obj/%)
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj-test/%.o: test/%.cpp
|
||||
$(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -o $@ $<
|
||||
$(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
|
||||
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
|
||||
@@ -138,6 +156,6 @@ clean:
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj-test/*.P
|
||||
-rm -f src/build.h
|
||||
-rm -f obj/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# 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.
|
||||
|
||||
USE_UPNP:=0
|
||||
USE_IPV6:=1
|
||||
|
||||
LINK:=$(CXX)
|
||||
|
||||
DEFS=-DBOOST_SPIRIT_THREADSAFE
|
||||
|
||||
@@ -41,6 +44,10 @@ ifneq (${USE_UPNP}, -)
|
||||
DEFS += -DUSE_UPNP=$(USE_UPNP)
|
||||
endif
|
||||
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
LIBS+= \
|
||||
-Wl,-B$(LMODE2) \
|
||||
-l z \
|
||||
@@ -66,13 +73,14 @@ LIBS+= \
|
||||
# Make some important things such as the global offset table read only as soon as
|
||||
# the dynamic linker is finished building it. This will prevent overwriting of addresses
|
||||
# which would later be jumped to.
|
||||
HARDENING+=-Wl,-z,relro -Wl,-z,now
|
||||
LDHARDENING+=-Wl,-z,relro -Wl,-z,now
|
||||
|
||||
# Build position independent code to take advantage of Address Space Layout Randomization
|
||||
# offered by some kernels.
|
||||
# see doc/build-unix.txt for more information.
|
||||
ifdef PIE
|
||||
HARDENING+=-fPIE -pie
|
||||
HARDENING+=-fPIE
|
||||
LDHARDENING+=-pie
|
||||
endif
|
||||
|
||||
# -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in
|
||||
@@ -82,11 +90,18 @@ LIBS+= \
|
||||
|
||||
|
||||
DEBUGFLAGS=-g
|
||||
CXXFLAGS=-O2
|
||||
xCXXFLAGS=-pthread -Wall -Wextra -Wno-sign-compare -Wno-invalid-offsetof -Wno-unused-parameter -Wformat -Wformat-security \
|
||||
|
||||
# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
|
||||
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
|
||||
xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
|
||||
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
|
||||
|
||||
# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
|
||||
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
|
||||
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
|
||||
|
||||
OBJS= \
|
||||
obj/alert.o \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
@@ -102,7 +117,13 @@ OBJS= \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/rpcnet.o \
|
||||
obj/rpcmining.o \
|
||||
obj/rpcwallet.o \
|
||||
obj/rpcblockchain.o \
|
||||
obj/rpcrawtransaction.o \
|
||||
obj/script.o \
|
||||
obj/sync.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
@@ -111,6 +132,9 @@ OBJS= \
|
||||
|
||||
all: bitcoind
|
||||
|
||||
test check: test_bitcoin FORCE
|
||||
./test_bitcoin
|
||||
|
||||
# auto-generated dependencies:
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
@@ -121,26 +145,26 @@ version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
|
||||
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
|
||||
rm -f $(@:%.o=%.d)
|
||||
|
||||
bitcoind: $(OBJS:obj/%=obj/%)
|
||||
$(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
$(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS)
|
||||
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj-test/%.o: test/%.cpp
|
||||
$(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -o $@ $<
|
||||
$(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $<
|
||||
@cp $(@:%.o=%.d) $(@:%.o=%.P); \
|
||||
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
|
||||
-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
|
||||
rm -f $(@:%.o=%.d)
|
||||
|
||||
test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
$(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
|
||||
$(LINK) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(xLDFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
-rm -f bitcoind test_bitcoin
|
||||
@@ -148,6 +172,6 @@ clean:
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj-test/*.P
|
||||
-rm -f src/build.h
|
||||
-rm -f obj/build.h
|
||||
|
||||
FORCE:
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
size_type max_size(size_type s)
|
||||
{
|
||||
if (s)
|
||||
while (queue.size() >= s)
|
||||
while (queue.size() > s)
|
||||
{
|
||||
set.erase(queue.front());
|
||||
queue.pop_front();
|
||||
|
||||
752
src/net.cpp
752
src/net.cpp
File diff suppressed because it is too large
Load Diff
90
src/net.h
90
src/net.h
@@ -19,7 +19,6 @@
|
||||
#include "protocol.h"
|
||||
#include "addrman.h"
|
||||
|
||||
class CAddrDB;
|
||||
class CRequestTracker;
|
||||
class CNode;
|
||||
class CBlockIndex;
|
||||
@@ -27,20 +26,48 @@ extern int nBestHeight;
|
||||
|
||||
|
||||
|
||||
inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
|
||||
inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); }
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); }
|
||||
|
||||
void AddOneShot(std::string strDest);
|
||||
bool RecvLine(SOCKET hSocket, std::string& strLine);
|
||||
bool GetMyExternalIP(CNetAddr& ipRet);
|
||||
void AddressCurrentlyConnected(const CService& addr);
|
||||
CNode* FindNode(const CNetAddr& ip);
|
||||
CNode* FindNode(const CService& ip);
|
||||
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
|
||||
void MapPort(bool fMapPort);
|
||||
bool BindListenPort(std::string& strError=REF(std::string()));
|
||||
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0);
|
||||
void MapPort();
|
||||
unsigned short GetListenPort();
|
||||
bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string()));
|
||||
void StartNode(void* parg);
|
||||
bool StopNode();
|
||||
|
||||
enum
|
||||
{
|
||||
LOCAL_NONE, // unknown
|
||||
LOCAL_IF, // address a local interface listens on
|
||||
LOCAL_BIND, // address explicit bound to
|
||||
LOCAL_UPNP, // address reported by UPnP
|
||||
LOCAL_IRC, // address reported by IRC (deprecated)
|
||||
LOCAL_HTTP, // address reported by whatismyip.com and similar
|
||||
LOCAL_MANUAL, // address explicitly specified (-externalip=)
|
||||
|
||||
LOCAL_MAX
|
||||
};
|
||||
|
||||
void SetLimited(enum Network net, bool fLimited = true);
|
||||
bool IsLimited(enum Network net);
|
||||
bool IsLimited(const CNetAddr& addr);
|
||||
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
||||
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
||||
bool SeenLocal(const CService& addr);
|
||||
bool IsLocal(const CService& addr);
|
||||
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
|
||||
bool IsReachable(const CNetAddr &addr);
|
||||
void SetReachable(enum Network net, bool fFlag = true);
|
||||
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MSG_TX = 1,
|
||||
@@ -73,19 +100,20 @@ enum threadId
|
||||
THREAD_OPENCONNECTIONS,
|
||||
THREAD_MESSAGEHANDLER,
|
||||
THREAD_MINER,
|
||||
THREAD_RPCSERVER,
|
||||
THREAD_RPCLISTENER,
|
||||
THREAD_UPNP,
|
||||
THREAD_DNSSEED,
|
||||
THREAD_ADDEDCONNECTIONS,
|
||||
THREAD_DUMPADDRESS,
|
||||
THREAD_RPCHANDLER,
|
||||
|
||||
THREAD_MAX
|
||||
};
|
||||
|
||||
extern bool fClient;
|
||||
extern bool fAllowDNS;
|
||||
extern bool fDiscover;
|
||||
extern bool fUseUPnP;
|
||||
extern uint64 nLocalServices;
|
||||
extern CAddress addrLocalHost;
|
||||
extern uint64 nLocalHostNonce;
|
||||
extern boost::array<int, THREAD_MAX> vnThreadsRunning;
|
||||
extern CAddrMan addrman;
|
||||
@@ -100,6 +128,24 @@ extern std::map<CInv, int64> mapAlreadyAskedFor;
|
||||
|
||||
|
||||
|
||||
class CNodeStats
|
||||
{
|
||||
public:
|
||||
uint64 nServices;
|
||||
int64 nLastSend;
|
||||
int64 nLastRecv;
|
||||
int64 nTimeConnected;
|
||||
std::string addrName;
|
||||
int nVersion;
|
||||
std::string strSubVer;
|
||||
bool fInbound;
|
||||
int64 nReleaseTime;
|
||||
int nStartingHeight;
|
||||
int nMisbehavior;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Information about a peer */
|
||||
@@ -120,19 +166,22 @@ public:
|
||||
int nHeaderStart;
|
||||
unsigned int nMessageStart;
|
||||
CAddress addr;
|
||||
std::string addrName;
|
||||
CService addrLocal;
|
||||
int nVersion;
|
||||
std::string strSubVer;
|
||||
bool fOneShot;
|
||||
bool fClient;
|
||||
bool fInbound;
|
||||
bool fNetworkNode;
|
||||
bool fSuccessfullyConnected;
|
||||
bool fDisconnect;
|
||||
bool fHasGrant; // whether to call semOutbound.post() at disconnect
|
||||
CSemaphoreGrant grantOutbound;
|
||||
protected:
|
||||
int nRefCount;
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
// Key is ip address, value is banned-until-time
|
||||
// Key is IP address, value is banned-until-time
|
||||
static std::map<CNetAddr, int64> setBanned;
|
||||
static CCriticalSection cs_setBanned;
|
||||
int nMisbehavior;
|
||||
@@ -158,7 +207,7 @@ public:
|
||||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64, CInv> mapAskFor;
|
||||
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
|
||||
{
|
||||
nServices = 0;
|
||||
hSocket = hSocketIn;
|
||||
@@ -169,10 +218,11 @@ public:
|
||||
nHeaderStart = -1;
|
||||
nMessageStart = -1;
|
||||
addr = addrIn;
|
||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||
nVersion = 0;
|
||||
strSubVer = "";
|
||||
fOneShot = false;
|
||||
fClient = false; // set by version message
|
||||
fHasGrant = false;
|
||||
fInbound = fInboundIn;
|
||||
fNetworkNode = false;
|
||||
fSuccessfullyConnected = false;
|
||||
@@ -265,7 +315,8 @@ public:
|
||||
// We're using mapAskFor as a priority queue,
|
||||
// the key is the earliest time the request can be sent
|
||||
int64& nRequestTime = mapAlreadyAskedFor[inv];
|
||||
printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
|
||||
if (fDebugNet)
|
||||
printf("askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
|
||||
|
||||
// Make sure not to reuse time indexes to keep things in the same order
|
||||
int64 nNow = (GetTime() - 1) * 1000000;
|
||||
@@ -289,10 +340,8 @@ public:
|
||||
nHeaderStart = vSend.size();
|
||||
vSend << CMessageHeader(pszCommand, 0);
|
||||
nMessageStart = vSend.size();
|
||||
if (fDebug) {
|
||||
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
|
||||
if (fDebug)
|
||||
printf("sending: %s ", pszCommand);
|
||||
}
|
||||
}
|
||||
|
||||
void AbortMessage()
|
||||
@@ -322,14 +371,14 @@ public:
|
||||
|
||||
// Set the size
|
||||
unsigned int nSize = vSend.size() - nMessageStart;
|
||||
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
|
||||
memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &nSize, sizeof(nSize));
|
||||
|
||||
// Set the checksum
|
||||
uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
|
||||
unsigned int nChecksum = 0;
|
||||
memcpy(&nChecksum, &hash, sizeof(nChecksum));
|
||||
assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
|
||||
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
|
||||
assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
|
||||
memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum));
|
||||
|
||||
if (fDebug) {
|
||||
printf("(%d bytes)\n", nSize);
|
||||
@@ -586,6 +635,7 @@ public:
|
||||
static void ClearBanned(); // needed for unit testing
|
||||
static bool IsBanned(CNetAddr ip);
|
||||
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
|
||||
void copyStats(CNodeStats &stats);
|
||||
};
|
||||
|
||||
|
||||
|
||||
666
src/netbase.cpp
666
src/netbase.cpp
@@ -5,26 +5,68 @@
|
||||
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
#include "sync.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "strlcpy.h"
|
||||
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Settings
|
||||
int fUseProxy = false;
|
||||
CService addrProxy("127.0.0.1",9050);
|
||||
static proxyType proxyInfo[NET_MAX];
|
||||
static proxyType nameproxyInfo;
|
||||
static CCriticalSection cs_proxyInfos;
|
||||
int nConnectTimeout = 5000;
|
||||
|
||||
bool fNameLookup = false;
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
enum Network ParseNetwork(std::string net) {
|
||||
boost::to_lower(net);
|
||||
if (net == "ipv4") return NET_IPV4;
|
||||
if (net == "ipv6") return NET_IPV6;
|
||||
if (net == "tor") return NET_TOR;
|
||||
if (net == "i2p") return NET_I2P;
|
||||
return NET_UNROUTABLE;
|
||||
}
|
||||
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
|
||||
size_t colon = in.find_last_of(':');
|
||||
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
||||
bool fHaveColon = colon != in.npos;
|
||||
bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
||||
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||
char *endp = NULL;
|
||||
int n = strtol(in.c_str() + colon + 1, &endp, 10);
|
||||
if (endp && *endp == 0 && n >= 0) {
|
||||
in = in.substr(0, colon);
|
||||
if (n > 0 && n < 0x10000)
|
||||
portOut = n;
|
||||
}
|
||||
}
|
||||
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||
hostOut = in.substr(1, in.size()-2);
|
||||
else
|
||||
hostOut = in;
|
||||
}
|
||||
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
vIP.clear();
|
||||
|
||||
{
|
||||
CNetAddr addr;
|
||||
if (addr.SetSpecial(std::string(pszName))) {
|
||||
vIP.push_back(addr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
struct addrinfo aiHint;
|
||||
memset(&aiHint, 0, sizeof(struct addrinfo));
|
||||
|
||||
@@ -33,19 +75,17 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
|
||||
#ifdef WIN32
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
# endif
|
||||
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
|
||||
#else
|
||||
# ifdef USE_IPV6
|
||||
aiHint.ai_family = AF_UNSPEC;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# else
|
||||
aiHint.ai_family = AF_INET;
|
||||
aiHint.ai_flags = AI_ADDRCONFIG | (fAllowLookup ? 0 : AI_NUMERICHOST);
|
||||
# endif
|
||||
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
|
||||
#endif
|
||||
struct addrinfo *aiRes = NULL;
|
||||
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
|
||||
@@ -103,36 +143,11 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
int port = portDefault;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
char* pszColon = strrchr(psz+1,':');
|
||||
char *pszPortEnd = NULL;
|
||||
int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
|
||||
if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
|
||||
{
|
||||
if (psz[0] == '[' && pszColon[-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
pszColon[-1] = 0;
|
||||
}
|
||||
else
|
||||
pszColon[0] = 0;
|
||||
if (port >= 0 && port <= USHRT_MAX)
|
||||
port = portParsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
psz[strlen(psz)-1] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
std::string hostname = "";
|
||||
SplitHostPort(std::string(pszName), port, hostname);
|
||||
|
||||
std::vector<CNetAddr> vIP;
|
||||
bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
|
||||
if (!fRet)
|
||||
return false;
|
||||
vAddr.resize(vIP.size());
|
||||
@@ -156,11 +171,169 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
bool static Socks4(const CService &addrDest, SOCKET& hSocket)
|
||||
{
|
||||
printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
|
||||
if (!addrDest.IsIPv4())
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Proxy destination is not IPv4");
|
||||
}
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Cannot get proxy destination address");
|
||||
}
|
||||
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
return false;
|
||||
}
|
||||
printf("SOCKS4 connected %s\n", addrDest.ToString().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool static Socks5(string strDest, int port, SOCKET& hSocket)
|
||||
{
|
||||
printf("SOCKS5 connecting %s\n", strDest.c_str());
|
||||
if (strDest.size() > 255)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Hostname too long");
|
||||
}
|
||||
char pszSocks5Init[] = "\5\1\0";
|
||||
char *pszSocks5 = pszSocks5Init;
|
||||
ssize_t nSize = sizeof(pszSocks5Init) - 1;
|
||||
|
||||
ssize_t ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet1[2];
|
||||
if (recv(hSocket, pchRet1, 2, 0) != 2)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Proxy failed to initialize");
|
||||
}
|
||||
string strSocks5("\5\1");
|
||||
strSocks5 += '\000'; strSocks5 += '\003';
|
||||
strSocks5 += static_cast<char>(std::min((int)strDest.size(), 255));
|
||||
strSocks5 += strDest;
|
||||
strSocks5 += static_cast<char>((port >> 8) & 0xFF);
|
||||
strSocks5 += static_cast<char>((port >> 0) & 0xFF);
|
||||
ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
|
||||
if (ret != (ssize_t)strSocks5.size())
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet2[4];
|
||||
if (recv(hSocket, pchRet2, 4, 0) != 4)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet2[0] != 0x05)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Proxy failed to accept request");
|
||||
}
|
||||
if (pchRet2[1] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
switch (pchRet2[1])
|
||||
{
|
||||
case 0x01: return error("Proxy error: general failure");
|
||||
case 0x02: return error("Proxy error: connection not allowed");
|
||||
case 0x03: return error("Proxy error: network unreachable");
|
||||
case 0x04: return error("Proxy error: host unreachable");
|
||||
case 0x05: return error("Proxy error: connection refused");
|
||||
case 0x06: return error("Proxy error: TTL expired");
|
||||
case 0x07: return error("Proxy error: protocol error");
|
||||
case 0x08: return error("Proxy error: address type not supported");
|
||||
default: return error("Proxy error: unknown");
|
||||
}
|
||||
}
|
||||
if (pchRet2[2] != 0x00)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error: malformed proxy response");
|
||||
}
|
||||
char pchRet3[256];
|
||||
switch (pchRet2[3])
|
||||
{
|
||||
case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break;
|
||||
case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break;
|
||||
case 0x03:
|
||||
{
|
||||
ret = recv(hSocket, pchRet3, 1, 0) != 1;
|
||||
if (ret)
|
||||
return error("Error reading from proxy");
|
||||
int nRecv = pchRet3[0];
|
||||
ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
|
||||
break;
|
||||
}
|
||||
default: closesocket(hSocket); return error("Error: malformed proxy response");
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading from proxy");
|
||||
}
|
||||
if (recv(hSocket, pchRet3, 2, 0) != 2)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading from proxy");
|
||||
}
|
||||
printf("SOCKS5 connected %s\n", strDest.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
hSocketRet = INVALID_SOCKET;
|
||||
|
||||
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
#ifdef USE_IPV6
|
||||
struct sockaddr_storage sockaddr;
|
||||
#else
|
||||
struct sockaddr sockaddr;
|
||||
#endif
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
|
||||
printf("Cannot connect to %s: unsupported network\n", addrConnect.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return false;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
@@ -168,13 +341,6 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
|
||||
#endif
|
||||
|
||||
bool fProxy = (fUseProxy && addrDest.IsRoutable());
|
||||
struct sockaddr_in sockaddr;
|
||||
if (fProxy)
|
||||
addrProxy.GetSockAddr(&sockaddr);
|
||||
else
|
||||
addrDest.GetSockAddr(&sockaddr);
|
||||
|
||||
#ifdef WIN32
|
||||
u_long fNonblock = 1;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
@@ -187,8 +353,7 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
|
||||
{
|
||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||
@@ -258,37 +423,123 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fProxy)
|
||||
{
|
||||
printf("proxy connecting %s\n", addrDest.ToString().c_str());
|
||||
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
|
||||
struct sockaddr_in addr;
|
||||
addrDest.GetSockAddr(&addr);
|
||||
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
|
||||
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
|
||||
char* pszSocks4 = pszSocks4IP;
|
||||
int nSize = sizeof(pszSocks4IP);
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
}
|
||||
char pchRet[8];
|
||||
if (recv(hSocket, pchRet, 8, 0) != 8)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error reading proxy response");
|
||||
}
|
||||
if (pchRet[1] != 0x5a)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
if (pchRet[1] != 0x5b)
|
||||
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!proxyInfo[net].second)
|
||||
return false;
|
||||
proxyInfoOut = proxyInfo[net];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion) {
|
||||
if (nSocksVersion != 0 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
return false;
|
||||
LOCK(cs_proxyInfos);
|
||||
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNameProxy(proxyType &nameproxyInfoOut) {
|
||||
LOCK(cs_proxyInfos);
|
||||
if (!nameproxyInfo.second)
|
||||
return false;
|
||||
nameproxyInfoOut = nameproxyInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HaveNameProxy() {
|
||||
LOCK(cs_proxyInfos);
|
||||
return nameproxyInfo.second != 0;
|
||||
}
|
||||
|
||||
bool IsProxy(const CNetAddr &addr) {
|
||||
LOCK(cs_proxyInfos);
|
||||
for (int i = 0; i < NET_MAX; i++) {
|
||||
if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
proxyType proxy;
|
||||
|
||||
// no proxy needed
|
||||
if (!GetProxy(addrDest.GetNetwork(), proxy))
|
||||
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
// first connect to proxy server
|
||||
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
// do socks negotiation
|
||||
switch (proxy.second) {
|
||||
case 4:
|
||||
if (!Socks4(addrDest, hSocket))
|
||||
return false;
|
||||
}
|
||||
printf("proxy connected %s\n", addrDest.ToString().c_str());
|
||||
break;
|
||||
case 5:
|
||||
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
|
||||
{
|
||||
string strDest;
|
||||
int port = portDefault;
|
||||
SplitHostPort(string(pszDest), port, strDest);
|
||||
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
|
||||
proxyType nameproxy;
|
||||
GetNameProxy(nameproxy);
|
||||
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port);
|
||||
if (addrResolved.IsValid()) {
|
||||
addr = addrResolved;
|
||||
return ConnectSocket(addr, hSocketRet, nTimeout);
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
if (!nameproxy.second)
|
||||
return false;
|
||||
if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
switch(nameproxy.second) {
|
||||
default:
|
||||
case 4: return false;
|
||||
case 5:
|
||||
if (!Socks5(strDest, port, hSocket))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
@@ -305,6 +556,32 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
|
||||
static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5};
|
||||
|
||||
bool CNetAddr::SetSpecial(const std::string &strName)
|
||||
{
|
||||
if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
|
||||
std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
|
||||
if (vchAddr.size() != 16-sizeof(pchOnionCat))
|
||||
return false;
|
||||
memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
|
||||
for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
|
||||
ip[i + sizeof(pchOnionCat)] = vchAddr[i];
|
||||
return true;
|
||||
}
|
||||
if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") {
|
||||
std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 11).c_str());
|
||||
if (vchAddr.size() != 16-sizeof(pchGarliCat))
|
||||
return false;
|
||||
memcpy(ip, pchOnionCat, sizeof(pchGarliCat));
|
||||
for (unsigned int i=0; i<16-sizeof(pchGarliCat); i++)
|
||||
ip[i + sizeof(pchGarliCat)] = vchAddr[i];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
@@ -339,7 +616,7 @@ CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
int CNetAddr::GetByte(int n) const
|
||||
unsigned int CNetAddr::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
@@ -349,11 +626,16 @@ bool CNetAddr::IsIPv4() const
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv6() const
|
||||
{
|
||||
return (!IsIPv4() && !IsTor() && !IsI2P());
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
@@ -405,6 +687,16 @@ bool CNetAddr::IsRFC4843() const
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsTor() const
|
||||
{
|
||||
return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsI2P() const
|
||||
{
|
||||
return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsLocal() const
|
||||
{
|
||||
// IPv4 loopback
|
||||
@@ -427,7 +719,7 @@ bool CNetAddr::IsMulticast() const
|
||||
|
||||
bool CNetAddr::IsValid() const
|
||||
{
|
||||
// Clean up 3-byte shifted addresses caused by garbage in size field
|
||||
// Cleanup 3-byte shifted addresses caused by garbage in size field
|
||||
// of addr messages from versions before 0.2.9 checksum.
|
||||
// Two consecutive addr messages look like this:
|
||||
// header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
|
||||
@@ -463,11 +755,44 @@ bool CNetAddr::IsValid() const
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || IsRFC4193() || IsRFC4843() || IsLocal());
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsTor() && !IsI2P()) || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
enum Network CNetAddr::GetNetwork() const
|
||||
{
|
||||
if (!IsRoutable())
|
||||
return NET_UNROUTABLE;
|
||||
|
||||
if (IsIPv4())
|
||||
return NET_IPV4;
|
||||
|
||||
if (IsTor())
|
||||
return NET_TOR;
|
||||
|
||||
if (IsI2P())
|
||||
return NET_I2P;
|
||||
|
||||
return NET_IPV6;
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsTor())
|
||||
return EncodeBase32(&ip[6], 10) + ".onion";
|
||||
if (IsI2P())
|
||||
return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p";
|
||||
CService serv(*this, 0);
|
||||
#ifdef USE_IPV6
|
||||
struct sockaddr_storage sockaddr;
|
||||
#else
|
||||
struct sockaddr sockaddr;
|
||||
#endif
|
||||
socklen_t socklen = sizeof(sockaddr);
|
||||
if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
|
||||
char name[1025] = "";
|
||||
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
|
||||
return std::string(name);
|
||||
}
|
||||
if (IsIPv4())
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
else
|
||||
@@ -519,44 +844,56 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
{
|
||||
std::vector<unsigned char> vchRet;
|
||||
int nClass = 0; // 0=IPv6, 1=IPv4, 254=local, 255=unroutable
|
||||
int nClass = NET_IPV6;
|
||||
int nStartByte = 0;
|
||||
int nBits = 16;
|
||||
|
||||
// all local addresses belong to the same group
|
||||
if (IsLocal())
|
||||
{
|
||||
nClass = 254;
|
||||
nClass = 255;
|
||||
nBits = 0;
|
||||
}
|
||||
|
||||
// all unroutable addresses belong to the same group
|
||||
if (!IsRoutable())
|
||||
{
|
||||
nClass = 255;
|
||||
nClass = NET_UNROUTABLE;
|
||||
nBits = 0;
|
||||
}
|
||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
|
||||
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
|
||||
else if (IsIPv4() || IsRFC6145() || IsRFC6052())
|
||||
{
|
||||
nClass = 1;
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 12;
|
||||
}
|
||||
// for 6to4 tunneled addresses, use the encapsulated IPv4 address
|
||||
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC3964())
|
||||
{
|
||||
nClass = 1;
|
||||
nClass = NET_IPV4;
|
||||
nStartByte = 2;
|
||||
}
|
||||
// for Teredo-tunneled IPv6 addresses, use the encapsulated IPv4 address
|
||||
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC4380())
|
||||
{
|
||||
vchRet.push_back(1);
|
||||
vchRet.push_back(NET_IPV4);
|
||||
vchRet.push_back(GetByte(3) ^ 0xFF);
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
else if (IsTor())
|
||||
{
|
||||
nClass = NET_TOR;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
else if (IsI2P())
|
||||
{
|
||||
nClass = NET_I2P;
|
||||
nStartByte = 6;
|
||||
nBits = 4;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
@@ -577,10 +914,10 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
int64 CNetAddr::GetHash() const
|
||||
uint64 CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
int64 nRet;
|
||||
uint64 nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
@@ -590,6 +927,84 @@ void CNetAddr::print() const
|
||||
printf("CNetAddr(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
// private extensions to enum Network, only returned by GetExtNetwork,
|
||||
// and only used in GetReachabilityFrom
|
||||
static const int NET_UNKNOWN = NET_MAX + 0;
|
||||
static const int NET_TEREDO = NET_MAX + 1;
|
||||
int static GetExtNetwork(const CNetAddr *addr)
|
||||
{
|
||||
if (addr == NULL)
|
||||
return NET_UNKNOWN;
|
||||
if (addr->IsRFC4380())
|
||||
return NET_TEREDO;
|
||||
return addr->GetNetwork();
|
||||
}
|
||||
|
||||
/** Calculates a metric for how reachable (*this) is from a given partner */
|
||||
int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
|
||||
{
|
||||
enum Reachability {
|
||||
REACH_UNREACHABLE,
|
||||
REACH_DEFAULT,
|
||||
REACH_TEREDO,
|
||||
REACH_IPV6_WEAK,
|
||||
REACH_IPV4,
|
||||
REACH_IPV6_STRONG,
|
||||
REACH_PRIVATE
|
||||
};
|
||||
|
||||
if (!IsRoutable())
|
||||
return REACH_UNREACHABLE;
|
||||
|
||||
int ourNet = GetExtNetwork(this);
|
||||
int theirNet = GetExtNetwork(paddrPartner);
|
||||
bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
|
||||
|
||||
switch(theirNet) {
|
||||
case NET_IPV4:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_IPV6:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
|
||||
}
|
||||
case NET_TOR:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
|
||||
case NET_TOR: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_I2P:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_I2P: return REACH_PRIVATE;
|
||||
}
|
||||
case NET_TEREDO:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
}
|
||||
case NET_UNKNOWN:
|
||||
case NET_UNROUTABLE:
|
||||
default:
|
||||
switch(ourNet) {
|
||||
default: return REACH_DEFAULT;
|
||||
case NET_TEREDO: return REACH_TEREDO;
|
||||
case NET_IPV6: return REACH_IPV6_WEAK;
|
||||
case NET_IPV4: return REACH_IPV4;
|
||||
case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are
|
||||
case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
{
|
||||
port = 0;
|
||||
@@ -626,6 +1041,22 @@ CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr),
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CService::SetSockAddr(const struct sockaddr *paddr)
|
||||
{
|
||||
switch (paddr->sa_family) {
|
||||
case AF_INET:
|
||||
*this = CService(*(const struct sockaddr_in*)paddr);
|
||||
return true;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
*this = CService(*(const struct sockaddr_in6*)paddr);
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CService::CService(const char *pszIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
@@ -678,29 +1109,36 @@ bool operator<(const CService& a, const CService& b)
|
||||
return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
|
||||
}
|
||||
|
||||
bool CService::GetSockAddr(struct sockaddr_in* paddr) const
|
||||
bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memset(paddr, 0, sizeof(struct sockaddr_in));
|
||||
if (!GetInAddr(&paddr->sin_addr))
|
||||
return false;
|
||||
paddr->sin_family = AF_INET;
|
||||
paddr->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsIPv4()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
|
||||
memset(paddrin, 0, *addrlen);
|
||||
if (!GetInAddr(&paddrin->sin_addr))
|
||||
return false;
|
||||
paddrin->sin_family = AF_INET;
|
||||
paddrin->sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
#ifdef USE_IPV6
|
||||
bool CService::GetSockAddr6(struct sockaddr_in6* paddr) const
|
||||
{
|
||||
memset(paddr, 0, sizeof(struct sockaddr_in6));
|
||||
if (!GetIn6Addr(&paddr->sin6_addr))
|
||||
return false;
|
||||
paddr->sin6_family = AF_INET6;
|
||||
paddr->sin6_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
if (IsIPv6()) {
|
||||
if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
|
||||
return false;
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
|
||||
memset(paddrin6, 0, *addrlen);
|
||||
if (!GetIn6Addr(&paddrin6->sin6_addr))
|
||||
return false;
|
||||
paddrin6->sin6_family = AF_INET6;
|
||||
paddrin6->sin6_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CService::GetKey() const
|
||||
{
|
||||
@@ -714,12 +1152,16 @@ std::vector<unsigned char> CService::GetKey() const
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf(":%i", port);
|
||||
return strprintf("%u", port);
|
||||
}
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
return ToStringIP() + ToStringPort();
|
||||
if (IsIPv4() || IsTor() || IsI2P()) {
|
||||
return ToStringIP() + ":" + ToStringPort();
|
||||
} else {
|
||||
return "[" + ToStringIP() + "]:" + ToStringPort();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CService::ToString() const
|
||||
|
||||
@@ -17,6 +17,20 @@ extern int nConnectTimeout;
|
||||
#undef SetPort
|
||||
#endif
|
||||
|
||||
enum Network
|
||||
{
|
||||
NET_UNROUTABLE,
|
||||
NET_IPV4,
|
||||
NET_IPV6,
|
||||
NET_TOR,
|
||||
NET_I2P,
|
||||
|
||||
NET_MAX,
|
||||
};
|
||||
|
||||
extern int nConnectTimeout;
|
||||
extern bool fNameLookup;
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
{
|
||||
@@ -30,27 +44,33 @@ class CNetAddr
|
||||
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
bool SetSpecial(const std::string &strName); // for Tor and I2P addresses
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/I2P)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||
bool IsRFC3964() const; // IPv6 6to4 tunneling (2002::/16)
|
||||
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
|
||||
bool IsRFC4193() const; // IPv6 unique local (FC00::/15)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunneling (2001::/32)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
|
||||
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
|
||||
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
|
||||
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
||||
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
||||
bool IsTor() const;
|
||||
bool IsI2P() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
bool IsMulticast() const;
|
||||
enum Network GetNetwork() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
int GetByte(int n) const;
|
||||
int64 GetHash() const;
|
||||
unsigned int GetByte(int n) const;
|
||||
uint64 GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
|
||||
void print() const;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
@@ -86,7 +106,8 @@ class CService : public CNetAddr
|
||||
void Init();
|
||||
void SetPort(unsigned short portIn);
|
||||
unsigned short GetPort() const;
|
||||
bool GetSockAddr(struct sockaddr_in* paddr) const;
|
||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
|
||||
bool SetSockAddr(const struct sockaddr* paddr);
|
||||
friend bool operator==(const CService& a, const CService& b);
|
||||
friend bool operator!=(const CService& a, const CService& b);
|
||||
friend bool operator<(const CService& a, const CService& b);
|
||||
@@ -98,7 +119,6 @@ class CService : public CNetAddr
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||
bool GetSockAddr6(struct sockaddr_in6* paddr) const;
|
||||
CService(const struct sockaddr_in6& addr);
|
||||
#endif
|
||||
|
||||
@@ -113,15 +133,21 @@ class CService : public CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
typedef std::pair<CService, int> proxyType;
|
||||
|
||||
enum Network ParseNetwork(std::string net);
|
||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
||||
bool IsProxy(const CNetAddr &addr);
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
|
||||
bool HaveNameProxy();
|
||||
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, unsigned int nMaxSolutions = 0);
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
|
||||
|
||||
// Settings
|
||||
extern int fUseProxy;
|
||||
extern CService addrProxy;
|
||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
|
||||
|
||||
#endif
|
||||
|
||||
32
src/noui.cpp
32
src/noui.cpp
@@ -3,42 +3,26 @@
|
||||
// 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 "init.h"
|
||||
#include "bitcoinrpc.h"
|
||||
|
||||
#include <string>
|
||||
#include "init.h"
|
||||
|
||||
int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
|
||||
static int noui_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)
|
||||
static bool noui_ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainFrameRepaint()
|
||||
void noui_connect()
|
||||
{
|
||||
// Connect bitcoind signal handlers
|
||||
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
|
||||
uiInterface.ThreadSafeAskFee.connect(noui_ThreadSafeAskFee);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,16 @@ class CMessageHeader
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
enum { COMMAND_SIZE=12 };
|
||||
char pchMessageStart[sizeof(::pchMessageStart)];
|
||||
enum {
|
||||
MESSAGE_START_SIZE=sizeof(::pchMessageStart),
|
||||
COMMAND_SIZE=12,
|
||||
MESSAGE_SIZE_SIZE=sizeof(int),
|
||||
CHECKSUM_SIZE=sizeof(int),
|
||||
|
||||
MESSAGE_SIZE_OFFSET=MESSAGE_START_SIZE+COMMAND_SIZE,
|
||||
CHECKSUM_OFFSET=MESSAGE_SIZE_OFFSET+MESSAGE_SIZE_SIZE
|
||||
};
|
||||
char pchMessageStart[MESSAGE_START_SIZE];
|
||||
char pchCommand[COMMAND_SIZE];
|
||||
unsigned int nMessageSize;
|
||||
unsigned int nChecksum;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "ui_addressbookpage.h"
|
||||
|
||||
#include "addresstablemodel.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "bitcoingui.h"
|
||||
#include "editaddressdialog.h"
|
||||
#include "csvmodelwriter.h"
|
||||
@@ -20,12 +21,13 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddressBookPage),
|
||||
model(0),
|
||||
optionsModel(0),
|
||||
mode(mode),
|
||||
tab(tab)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
#ifdef Q_WS_MAC // Icons on push buttons are very uncommon on Mac
|
||||
#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
|
||||
ui->newAddressButton->setIcon(QIcon());
|
||||
ui->copyToClipboard->setIcon(QIcon());
|
||||
ui->deleteButton->setIcon(QIcon());
|
||||
@@ -58,25 +60,38 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
ui->signMessage->setVisible(true);
|
||||
break;
|
||||
}
|
||||
ui->tableView->setTabKeyNavigation(false);
|
||||
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
// Context menu actions
|
||||
QAction *copyAddressAction = new QAction(tr("Copy address"), this);
|
||||
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
|
||||
QAction *editAction = new QAction(tr("Edit"), this);
|
||||
deleteAction = new QAction(tr("Delete"), this);
|
||||
QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
|
||||
QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
|
||||
QAction *editAction = new QAction(tr("&Edit"), this);
|
||||
QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
|
||||
QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
|
||||
QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
|
||||
deleteAction = new QAction(ui->deleteButton->text(), this);
|
||||
|
||||
// Build context menu
|
||||
contextMenu = new QMenu();
|
||||
contextMenu->addAction(copyAddressAction);
|
||||
contextMenu->addAction(copyLabelAction);
|
||||
contextMenu->addAction(editAction);
|
||||
contextMenu->addAction(deleteAction);
|
||||
if(tab == SendingTab)
|
||||
contextMenu->addAction(deleteAction);
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction(showQRCodeAction);
|
||||
if(tab == ReceivingTab)
|
||||
contextMenu->addAction(signMessageAction);
|
||||
else if(tab == SendingTab)
|
||||
contextMenu->addAction(verifyMessageAction);
|
||||
|
||||
// Connect signals for context menu actions
|
||||
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
|
||||
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
|
||||
connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
|
||||
connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
|
||||
connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
|
||||
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
|
||||
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));
|
||||
|
||||
connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
|
||||
|
||||
@@ -98,6 +113,8 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
proxyModel = new QSortFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(model);
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
switch(tab)
|
||||
{
|
||||
case ReceivingTab:
|
||||
@@ -123,9 +140,18 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(selectionChanged()));
|
||||
|
||||
// Select row for newly created address
|
||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(selectNewAddress(QModelIndex,int,int)));
|
||||
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
void AddressBookPage::setOptionsModel(OptionsModel *optionsModel)
|
||||
{
|
||||
this->optionsModel = optionsModel;
|
||||
}
|
||||
|
||||
void AddressBookPage::on_copyToClipboard_clicked()
|
||||
{
|
||||
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
|
||||
@@ -166,10 +192,22 @@ void AddressBookPage::on_signMessage_clicked()
|
||||
addr = address.toString();
|
||||
}
|
||||
|
||||
QObject *qoGUI = parent()->parent();
|
||||
BitcoinGUI *gui = qobject_cast<BitcoinGUI *>(qoGUI);
|
||||
if (gui)
|
||||
gui->gotoMessagePage(addr);
|
||||
emit signMessage(addr);
|
||||
}
|
||||
|
||||
void AddressBookPage::on_verifyMessage_clicked()
|
||||
{
|
||||
QTableView *table = ui->tableView;
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
||||
QString addr;
|
||||
|
||||
foreach (QModelIndex index, indexes)
|
||||
{
|
||||
QVariant address = index.data();
|
||||
addr = address.toString();
|
||||
}
|
||||
|
||||
emit verifyMessage(addr);
|
||||
}
|
||||
|
||||
void AddressBookPage::on_newAddressButton_clicked()
|
||||
@@ -179,20 +217,11 @@ void AddressBookPage::on_newAddressButton_clicked()
|
||||
EditAddressDialog dlg(
|
||||
tab == SendingTab ?
|
||||
EditAddressDialog::NewSendingAddress :
|
||||
EditAddressDialog::NewReceivingAddress);
|
||||
EditAddressDialog::NewReceivingAddress, this);
|
||||
dlg.setModel(model);
|
||||
if(dlg.exec())
|
||||
{
|
||||
// Select row for newly created address
|
||||
QString address = dlg.getAddress();
|
||||
QModelIndexList lst = proxyModel->match(proxyModel->index(0,
|
||||
AddressTableModel::Address, QModelIndex()),
|
||||
Qt::EditRole, address, 1, Qt::MatchExactly);
|
||||
if(!lst.isEmpty())
|
||||
{
|
||||
ui->tableView->setFocus();
|
||||
ui->tableView->selectRow(lst.at(0).row());
|
||||
}
|
||||
newAddressToSelect = dlg.getAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +255,8 @@ void AddressBookPage::selectionChanged()
|
||||
deleteAction->setEnabled(true);
|
||||
ui->signMessage->setEnabled(false);
|
||||
ui->signMessage->setVisible(false);
|
||||
ui->verifyMessage->setEnabled(true);
|
||||
ui->verifyMessage->setVisible(true);
|
||||
break;
|
||||
case ReceivingTab:
|
||||
// Deleting receiving addresses, however, is not allowed
|
||||
@@ -234,6 +265,8 @@ void AddressBookPage::selectionChanged()
|
||||
deleteAction->setEnabled(false);
|
||||
ui->signMessage->setEnabled(true);
|
||||
ui->signMessage->setVisible(true);
|
||||
ui->verifyMessage->setEnabled(false);
|
||||
ui->verifyMessage->setVisible(false);
|
||||
break;
|
||||
}
|
||||
ui->copyToClipboard->setEnabled(true);
|
||||
@@ -245,6 +278,7 @@ void AddressBookPage::selectionChanged()
|
||||
ui->showQRCode->setEnabled(false);
|
||||
ui->copyToClipboard->setEnabled(false);
|
||||
ui->signMessage->setEnabled(false);
|
||||
ui->verifyMessage->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +344,9 @@ void AddressBookPage::on_showQRCode_clicked()
|
||||
QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();
|
||||
|
||||
QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
|
||||
if(optionsModel)
|
||||
dialog->setModel(optionsModel);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->show();
|
||||
}
|
||||
#endif
|
||||
@@ -323,3 +360,15 @@ void AddressBookPage::contextualMenu(const QPoint &point)
|
||||
contextMenu->exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
|
||||
{
|
||||
QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
|
||||
if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
|
||||
{
|
||||
// Select row of newly created address, once
|
||||
ui->tableView->setFocus();
|
||||
ui->tableView->selectRow(idx.row());
|
||||
newAddressToSelect.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ namespace Ui {
|
||||
class AddressBookPage;
|
||||
}
|
||||
class AddressTableModel;
|
||||
class OptionsModel;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTableView;
|
||||
class QItemSelection;
|
||||
class QSortFilterProxyModel;
|
||||
class QMenu;
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/** Widget that shows a list of sending or receiving addresses.
|
||||
@@ -36,6 +38,7 @@ public:
|
||||
~AddressBookPage();
|
||||
|
||||
void setModel(AddressTableModel *model);
|
||||
void setOptionsModel(OptionsModel *optionsModel);
|
||||
const QString &getReturnValue() const { return returnValue; }
|
||||
|
||||
public slots:
|
||||
@@ -45,12 +48,14 @@ public slots:
|
||||
private:
|
||||
Ui::AddressBookPage *ui;
|
||||
AddressTableModel *model;
|
||||
OptionsModel *optionsModel;
|
||||
Mode mode;
|
||||
Tabs tab;
|
||||
QString returnValue;
|
||||
QSortFilterProxyModel *proxyModel;
|
||||
QMenu *contextMenu;
|
||||
QAction *deleteAction;
|
||||
QString newAddressToSelect;
|
||||
|
||||
private slots:
|
||||
void on_deleteButton_clicked();
|
||||
@@ -58,6 +63,7 @@ private slots:
|
||||
/** Copy address of currently selected address entry to clipboard */
|
||||
void on_copyToClipboard_clicked();
|
||||
void on_signMessage_clicked();
|
||||
void on_verifyMessage_clicked();
|
||||
void selectionChanged();
|
||||
void on_showQRCode_clicked();
|
||||
/** Spawn contextual menu (right mouse menu) for address book entry */
|
||||
@@ -67,6 +73,13 @@ private slots:
|
||||
void onCopyLabelAction();
|
||||
/** Edit currently selected address entry */
|
||||
void onEditAction();
|
||||
|
||||
/** New entry/entries were added to address table */
|
||||
void selectNewAddress(const QModelIndex &parent, int begin, int end);
|
||||
|
||||
signals:
|
||||
void signMessage(QString addr);
|
||||
void verifyMessage(QString addr);
|
||||
};
|
||||
|
||||
#endif // ADDRESSBOOKDIALOG_H
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "walletmodel.h"
|
||||
|
||||
#include "wallet.h"
|
||||
#include "base58.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QColor>
|
||||
@@ -26,27 +27,43 @@ struct AddressTableEntry
|
||||
type(type), label(label), address(address) {}
|
||||
};
|
||||
|
||||
struct AddressTableEntryLessThan
|
||||
{
|
||||
bool operator()(const AddressTableEntry &a, const AddressTableEntry &b) const
|
||||
{
|
||||
return a.address < b.address;
|
||||
}
|
||||
bool operator()(const AddressTableEntry &a, const QString &b) const
|
||||
{
|
||||
return a.address < b;
|
||||
}
|
||||
bool operator()(const QString &a, const AddressTableEntry &b) const
|
||||
{
|
||||
return a < b.address;
|
||||
}
|
||||
};
|
||||
|
||||
// Private implementation
|
||||
class AddressTablePriv
|
||||
{
|
||||
public:
|
||||
CWallet *wallet;
|
||||
QList<AddressTableEntry> cachedAddressTable;
|
||||
AddressTableModel *parent;
|
||||
|
||||
AddressTablePriv(CWallet *wallet):
|
||||
wallet(wallet) {}
|
||||
AddressTablePriv(CWallet *wallet, AddressTableModel *parent):
|
||||
wallet(wallet), parent(parent) {}
|
||||
|
||||
void refreshAddressTable()
|
||||
{
|
||||
cachedAddressTable.clear();
|
||||
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, wallet->mapAddressBook)
|
||||
BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, wallet->mapAddressBook)
|
||||
{
|
||||
const CBitcoinAddress& address = item.first;
|
||||
const std::string& strName = item.second;
|
||||
bool fMine = wallet->HaveKey(address);
|
||||
bool fMine = IsMine(*wallet, address.Get());
|
||||
cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
|
||||
QString::fromStdString(strName),
|
||||
QString::fromStdString(address.ToString())));
|
||||
@@ -54,6 +71,53 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void updateEntry(const QString &address, const QString &label, bool isMine, int status)
|
||||
{
|
||||
// Find address / label in model
|
||||
QList<AddressTableEntry>::iterator lower = qLowerBound(
|
||||
cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
|
||||
QList<AddressTableEntry>::iterator upper = qUpperBound(
|
||||
cachedAddressTable.begin(), cachedAddressTable.end(), address, AddressTableEntryLessThan());
|
||||
int lowerIndex = (lower - cachedAddressTable.begin());
|
||||
int upperIndex = (upper - cachedAddressTable.begin());
|
||||
bool inModel = (lower != upper);
|
||||
AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending;
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case CT_NEW:
|
||||
if(inModel)
|
||||
{
|
||||
OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_NOW, but entry is already in model\n");
|
||||
break;
|
||||
}
|
||||
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex);
|
||||
cachedAddressTable.insert(lowerIndex, AddressTableEntry(newEntryType, label, address));
|
||||
parent->endInsertRows();
|
||||
break;
|
||||
case CT_UPDATED:
|
||||
if(!inModel)
|
||||
{
|
||||
OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_UPDATED, but entry is not in model\n");
|
||||
break;
|
||||
}
|
||||
lower->type = newEntryType;
|
||||
lower->label = label;
|
||||
parent->emitDataChanged(lowerIndex);
|
||||
break;
|
||||
case CT_DELETED:
|
||||
if(!inModel)
|
||||
{
|
||||
OutputDebugStringF("Warning: AddressTablePriv::updateEntry: Got CT_DELETED, but entry is not in model\n");
|
||||
break;
|
||||
}
|
||||
parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
|
||||
cachedAddressTable.erase(lower, upper);
|
||||
parent->endRemoveRows();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int size()
|
||||
{
|
||||
return cachedAddressTable.size();
|
||||
@@ -76,7 +140,7 @@ AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
|
||||
QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
|
||||
{
|
||||
columns << tr("Label") << tr("Address");
|
||||
priv = new AddressTablePriv(wallet);
|
||||
priv = new AddressTablePriv(wallet, this);
|
||||
priv->refreshAddressTable();
|
||||
}
|
||||
|
||||
@@ -157,7 +221,7 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
|
||||
switch(index.column())
|
||||
{
|
||||
case Label:
|
||||
wallet->SetAddressBookName(rec->address.toStdString(), value.toString().toStdString());
|
||||
wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString());
|
||||
rec->label = value.toString();
|
||||
break;
|
||||
case Address:
|
||||
@@ -173,16 +237,13 @@ bool AddressTableModel::setData(const QModelIndex & index, const QVariant & valu
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
// Remove old entry
|
||||
wallet->DelAddressBookName(rec->address.toStdString());
|
||||
wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
|
||||
// Add new entry with new address
|
||||
wallet->SetAddressBookName(value.toString().toStdString(), rec->label.toStdString());
|
||||
wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString());
|
||||
}
|
||||
|
||||
rec->address = value.toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -232,12 +293,10 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & pa
|
||||
}
|
||||
}
|
||||
|
||||
void AddressTableModel::update()
|
||||
void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status)
|
||||
{
|
||||
// Update address book model from Bitcoin core
|
||||
beginResetModel();
|
||||
priv->refreshAddressTable();
|
||||
endResetModel();
|
||||
priv->updateEntry(address, label, isMine, status);
|
||||
}
|
||||
|
||||
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
|
||||
@@ -257,7 +316,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
// Check for duplicate addresses
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
if(wallet->mapAddressBook.count(strAddress))
|
||||
if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get()))
|
||||
{
|
||||
editStatus = DUPLICATE_ADDRESS;
|
||||
return QString();
|
||||
@@ -274,13 +333,13 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
editStatus = WALLET_UNLOCK_FAILURE;
|
||||
return QString();
|
||||
}
|
||||
std::vector<unsigned char> newKey;
|
||||
CPubKey newKey;
|
||||
if(!wallet->GetKeyFromPool(newKey, true))
|
||||
{
|
||||
editStatus = KEY_GENERATION_FAILURE;
|
||||
return QString();
|
||||
}
|
||||
strAddress = CBitcoinAddress(newKey).ToString();
|
||||
strAddress = CBitcoinAddress(newKey.GetID()).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -289,7 +348,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
|
||||
// Add entry
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->SetAddressBookName(strAddress, strLabel);
|
||||
wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel);
|
||||
}
|
||||
return QString::fromStdString(strAddress);
|
||||
}
|
||||
@@ -306,7 +365,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
|
||||
}
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->DelAddressBookName(rec->address.toStdString());
|
||||
wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -318,7 +377,7 @@ QString AddressTableModel::labelForAddress(const QString &address) const
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
CBitcoinAddress address_parsed(address.toStdString());
|
||||
std::map<CBitcoinAddress, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed);
|
||||
std::map<CTxDestination, std::string>::iterator mi = wallet->mapAddressBook.find(address_parsed.Get());
|
||||
if (mi != wallet->mapAddressBook.end())
|
||||
{
|
||||
return QString::fromStdString(mi->second);
|
||||
@@ -341,3 +400,7 @@ int AddressTableModel::lookupAddress(const QString &address) const
|
||||
}
|
||||
}
|
||||
|
||||
void AddressTableModel::emitDataChanged(int idx)
|
||||
{
|
||||
emit dataChanged(index(idx, 0, QModelIndex()), index(idx, columns.length()-1, QModelIndex()));
|
||||
}
|
||||
|
||||
@@ -74,13 +74,18 @@ private:
|
||||
QStringList columns;
|
||||
EditStatus editStatus;
|
||||
|
||||
/** Notify listeners that data changed. */
|
||||
void emitDataChanged(int index);
|
||||
|
||||
signals:
|
||||
void defaultAddressChanged(const QString &address);
|
||||
|
||||
public slots:
|
||||
/* Update address list from core. Invalidates any indices.
|
||||
/* Update address list from core.
|
||||
*/
|
||||
void update();
|
||||
void updateEntry(const QString &address, const QString &label, bool isMine, int status);
|
||||
|
||||
friend class AddressTablePriv;
|
||||
};
|
||||
|
||||
#endif // ADDRESSTABLEMODEL_H
|
||||
|
||||
@@ -24,7 +24,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
|
||||
ui->passEdit1->installEventFilter(this);
|
||||
ui->passEdit2->installEventFilter(this);
|
||||
ui->passEdit3->installEventFilter(this);
|
||||
ui->capsLabel->clear();
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
@@ -99,7 +98,7 @@ void AskPassphraseDialog::accept()
|
||||
break;
|
||||
}
|
||||
QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"),
|
||||
tr("WARNING: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>!\nAre you sure you wish to encrypt your wallet?"),
|
||||
tr("Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>!") + "<br><br>" + tr("Are you sure you wish to encrypt your wallet?"),
|
||||
QMessageBox::Yes|QMessageBox::Cancel,
|
||||
QMessageBox::Cancel);
|
||||
if(retval == QMessageBox::Yes)
|
||||
@@ -109,7 +108,16 @@ void AskPassphraseDialog::accept()
|
||||
if(model->setWalletEncrypted(true, newpass1))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Wallet encrypted"),
|
||||
tr("Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
|
||||
"<qt>" +
|
||||
tr("Bitcoin will close now to finish the encryption process. "
|
||||
"Remember that encrypting your wallet cannot fully protect "
|
||||
"your bitcoins from being stolen by malware infecting your computer.") +
|
||||
"<br><br><b>" +
|
||||
tr("IMPORTANT: Any previous backups you have made of your wallet file "
|
||||
"should be replaced with the newly generated, encrypted wallet file. "
|
||||
"For security reasons, previous backups of the unencrypted wallet file "
|
||||
"will become useless as soon as you start using the new, encrypted wallet.") +
|
||||
"</b></qt>");
|
||||
QApplication::quit();
|
||||
}
|
||||
else
|
||||
@@ -158,7 +166,7 @@ void AskPassphraseDialog::accept()
|
||||
if(model->changePassphrase(oldpass, newpass1))
|
||||
{
|
||||
QMessageBox::information(this, tr("Wallet encrypted"),
|
||||
tr("Wallet passphrase was succesfully changed."));
|
||||
tr("Wallet passphrase was successfully changed."));
|
||||
QDialog::accept(); // Success
|
||||
}
|
||||
else
|
||||
@@ -178,7 +186,7 @@ void AskPassphraseDialog::accept()
|
||||
|
||||
void AskPassphraseDialog::textChanged()
|
||||
{
|
||||
// Validate input, set Ok button to enabled when accepable
|
||||
// Validate input, set Ok button to enabled when acceptable
|
||||
bool acceptable = false;
|
||||
switch(mode)
|
||||
{
|
||||
@@ -205,7 +213,7 @@ bool AskPassphraseDialog::event(QEvent *event)
|
||||
fCapsLock = !fCapsLock;
|
||||
}
|
||||
if (fCapsLock) {
|
||||
ui->capsLabel->setText(tr("Warning: The Caps Lock key is on."));
|
||||
ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
|
||||
} else {
|
||||
ui->capsLabel->clear();
|
||||
}
|
||||
@@ -213,9 +221,9 @@ bool AskPassphraseDialog::event(QEvent *event)
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
bool AskPassphraseDialog::eventFilter(QObject *, QEvent *event)
|
||||
bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
/* Detect Caps Lock.
|
||||
/* Detect Caps Lock.
|
||||
* There is no good OS-independent way to check a key state in Qt, but we
|
||||
* can detect Caps Lock by checking for the following condition:
|
||||
* Shift key is down and the result is a lower case character, or
|
||||
@@ -229,12 +237,12 @@ bool AskPassphraseDialog::eventFilter(QObject *, QEvent *event)
|
||||
bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0;
|
||||
if ((fShift && psz->isLower()) || (!fShift && psz->isUpper())) {
|
||||
fCapsLock = true;
|
||||
ui->capsLabel->setText(tr("Warning: The Caps Lock key is on."));
|
||||
ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!"));
|
||||
} else if (psz->isLetter()) {
|
||||
fCapsLock = false;
|
||||
ui->capsLabel->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return QDialog::eventFilter(object, event);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "walletmodel.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "guiutil.h"
|
||||
#include "guiconstants.h"
|
||||
|
||||
#include "init.h"
|
||||
#include "ui_interface.h"
|
||||
@@ -19,8 +20,6 @@
|
||||
#include <QSplashScreen>
|
||||
#include <QLibraryInfo>
|
||||
|
||||
#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__
|
||||
@@ -35,15 +34,13 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
||||
// Need a global reference for the notifications to find the GUI
|
||||
static BitcoinGUI *guiref;
|
||||
static QSplashScreen *splashref;
|
||||
static WalletModel *walletmodel;
|
||||
static ClientModel *clientmodel;
|
||||
|
||||
int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
|
||||
static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
|
||||
{
|
||||
// Message from network thread
|
||||
if(guiref)
|
||||
{
|
||||
bool modal = (style & wxMODAL);
|
||||
bool modal = (style & CClientUIInterface::MODAL);
|
||||
// in case of modal message, use blocking connection to wait for user to click OK
|
||||
QMetaObject::invokeMethod(guiref, "error",
|
||||
modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
|
||||
@@ -56,10 +53,9 @@ int ThreadSafeMessageBox(const std::string& message, const std::string& caption,
|
||||
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)
|
||||
static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
|
||||
{
|
||||
if(!guiref)
|
||||
return false;
|
||||
@@ -74,7 +70,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
|
||||
return payFee;
|
||||
}
|
||||
|
||||
void ThreadSafeHandleURI(const std::string& strURI)
|
||||
static void ThreadSafeHandleURI(const std::string& strURI)
|
||||
{
|
||||
if(!guiref)
|
||||
return;
|
||||
@@ -83,21 +79,7 @@ void ThreadSafeHandleURI(const std::string& strURI)
|
||||
Q_ARG(QString, QString::fromStdString(strURI)));
|
||||
}
|
||||
|
||||
void MainFrameRepaint()
|
||||
{
|
||||
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)
|
||||
static void InitMessage(const std::string &message)
|
||||
{
|
||||
if(splashref)
|
||||
{
|
||||
@@ -106,7 +88,7 @@ void InitMessage(const std::string &message)
|
||||
}
|
||||
}
|
||||
|
||||
void QueueShutdown()
|
||||
static void QueueShutdown()
|
||||
{
|
||||
QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
|
||||
}
|
||||
@@ -114,7 +96,7 @@ void QueueShutdown()
|
||||
/*
|
||||
Translate string to current locale using Qt.
|
||||
*/
|
||||
std::string _(const char* psz)
|
||||
static std::string Translate(const char* psz)
|
||||
{
|
||||
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
|
||||
}
|
||||
@@ -124,38 +106,15 @@ std::string _(const char* psz)
|
||||
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));
|
||||
QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. 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[])
|
||||
{
|
||||
#if !defined(MAC_OSX) && !defined(WIN32)
|
||||
// TODO: implement qtipcserver.cpp for Mac and Windows
|
||||
|
||||
// Do this early as we don't want to bother initializing if we are just calling IPC
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
|
||||
{
|
||||
const char *strURI = argv[i];
|
||||
try {
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
|
||||
if(mq.try_send(strURI, strlen(strURI), 0))
|
||||
exit(0);
|
||||
else
|
||||
break;
|
||||
}
|
||||
catch (boost::interprocess::interprocess_exception &ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ipcScanRelay(argc, argv);
|
||||
|
||||
// Internal string conversion is all UTF-8
|
||||
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
||||
@@ -164,13 +123,19 @@ int main(int argc, char *argv[])
|
||||
Q_INIT_RESOURCE(bitcoin);
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Install global event filter that makes sure that long tooltips can be word-wrapped
|
||||
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
|
||||
|
||||
// Command-line options take precedence:
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
// ... then bitcoin.conf:
|
||||
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
||||
{
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
// This message can not be translated, as translation is not initialized yet
|
||||
// (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
|
||||
QMessageBox::critical(0, "Bitcoin",
|
||||
QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
|
||||
return 1;
|
||||
}
|
||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||
@@ -187,32 +152,50 @@ int main(int argc, char *argv[])
|
||||
// ... then GUI settings:
|
||||
OptionsModel optionsModel;
|
||||
|
||||
// Get desired locale ("en_US") from command line or system locale
|
||||
// Get desired locale (e.g. "de_DE") from command line or use system locale
|
||||
QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
|
||||
QString lang = lang_territory;
|
||||
// Convert to "de" only by truncating "_DE"
|
||||
lang.truncate(lang_territory.lastIndexOf('_'));
|
||||
|
||||
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
|
||||
// Load language files for configured locale:
|
||||
// - First load the translator for the base language, without territory
|
||||
// - Then load the more specific locale translator
|
||||
QString lang = lang_territory;
|
||||
|
||||
lang.truncate(lang_territory.lastIndexOf('_')); // "en"
|
||||
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
|
||||
|
||||
qtTranslatorBase.load(QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + lang);
|
||||
if (!qtTranslatorBase.isEmpty())
|
||||
// Load e.g. qt_de.qm
|
||||
if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
app.installTranslator(&qtTranslatorBase);
|
||||
|
||||
qtTranslator.load(QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + lang_territory);
|
||||
if (!qtTranslator.isEmpty())
|
||||
// Load e.g. qt_de_DE.qm
|
||||
if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
app.installTranslator(&qtTranslator);
|
||||
|
||||
translatorBase.load(":/translations/"+lang);
|
||||
if (!translatorBase.isEmpty())
|
||||
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
|
||||
if (translatorBase.load(lang, ":/translations/"))
|
||||
app.installTranslator(&translatorBase);
|
||||
|
||||
translator.load(":/translations/"+lang_territory);
|
||||
if (!translator.isEmpty())
|
||||
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
|
||||
if (translator.load(lang_territory, ":/translations/"))
|
||||
app.installTranslator(&translator);
|
||||
|
||||
// Subscribe to global signals from core
|
||||
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
|
||||
uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
|
||||
uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
|
||||
uiInterface.InitMessage.connect(InitMessage);
|
||||
uiInterface.QueueShutdown.connect(QueueShutdown);
|
||||
uiInterface.Translate.connect(Translate);
|
||||
|
||||
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
|
||||
// but before showing splash screen.
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
{
|
||||
GUIUtil::HelpMessageBox help;
|
||||
help.showOrPrint();
|
||||
return 1;
|
||||
}
|
||||
|
||||
QSplashScreen splash(QPixmap(":/images/splash"), 0);
|
||||
if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
|
||||
{
|
||||
@@ -227,9 +210,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
try
|
||||
{
|
||||
// Regenerate startup link, to fix links to old versions
|
||||
if (GUIUtil::GetStartOnSystemStartup())
|
||||
GUIUtil::SetStartOnSystemStartup(true);
|
||||
|
||||
BitcoinGUI window;
|
||||
guiref = &window;
|
||||
if(AppInit2(argc, argv))
|
||||
if(AppInit2())
|
||||
{
|
||||
{
|
||||
// Put this in a block, so that the Model objects are cleaned up before
|
||||
@@ -241,9 +228,7 @@ int main(int argc, char *argv[])
|
||||
splash.finish(&window);
|
||||
|
||||
ClientModel clientModel(&optionsModel);
|
||||
clientmodel = &clientModel;
|
||||
WalletModel walletModel(pwalletMain, &optionsModel);
|
||||
walletmodel = &walletModel;
|
||||
|
||||
window.setClientModel(&clientModel);
|
||||
window.setWalletModel(&walletModel);
|
||||
@@ -258,37 +243,17 @@ int main(int argc, char *argv[])
|
||||
window.show();
|
||||
}
|
||||
|
||||
// Place this here as guiref has to be defined if we dont want to lose URIs
|
||||
ipcInit();
|
||||
// Place this here as guiref has to be defined if we don't want to lose URIs
|
||||
ipcInit(argc, argv);
|
||||
|
||||
#if !defined(MAC_OSX) && !defined(WIN32)
|
||||
// TODO: implement qtipcserver.cpp for Mac and Windows
|
||||
|
||||
// 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 *strURI = argv[i];
|
||||
try {
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#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 the core and its threads, but don't exit Bitcoin-Qt here
|
||||
Shutdown(NULL);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -38,30 +38,33 @@
|
||||
<file alias="lock_open">res/icons/lock_open.png</file>
|
||||
<file alias="key">res/icons/key.png</file>
|
||||
<file alias="filesave">res/icons/filesave.png</file>
|
||||
<file alias="qrcode">res/icons/qrcode.png</file>
|
||||
<file alias="debugwindow">res/icons/debugwindow.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images">
|
||||
<file alias="about">res/images/about.png</file>
|
||||
<file alias="splash">res/images/splash2.jpg</file>
|
||||
<file alias="qrcode">res/images/qrcode.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/movies">
|
||||
<file alias="update_spinner">res/movies/update_spinner.mng</file>
|
||||
</qresource>
|
||||
<qresource prefix="/translations">
|
||||
<file alias="bg">locale/bitcoin_bg.qm</file>
|
||||
<file alias="ca_ES">locale/bitcoin_ca_ES.qm</file>
|
||||
<file alias="cs">locale/bitcoin_cs.qm</file>
|
||||
<file alias="da">locale/bitcoin_da.qm</file>
|
||||
<file alias="de">locale/bitcoin_de.qm</file>
|
||||
<file alias="el_GR">locale/bitcoin_el_GR.qm</file>
|
||||
<file alias="en">locale/bitcoin_en.qm</file>
|
||||
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
|
||||
<file alias="es">locale/bitcoin_es.qm</file>
|
||||
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
|
||||
<file alias="et">locale/bitcoin_et.qm</file>
|
||||
<file alias="eu_ES">locale/bitcoin_eu_ES.qm</file>
|
||||
<file alias="fa_IR">locale/bitcoin_fa_IR.qm</file>
|
||||
<file alias="fa">locale/bitcoin_fa.qm</file>
|
||||
<file alias="fa_IR">locale/bitcoin_fa_IR.qm</file>
|
||||
<file alias="fi">locale/bitcoin_fi.qm</file>
|
||||
<file alias="fr">locale/bitcoin_fr.qm</file>
|
||||
<file alias="fr_CA">locale/bitcoin_fr_CA.qm</file>
|
||||
<file alias="fr_FR">locale/bitcoin_fr_FR.qm</file>
|
||||
<file alias="he">locale/bitcoin_he.qm</file>
|
||||
<file alias="hr">locale/bitcoin_hr.qm</file>
|
||||
<file alias="hu">locale/bitcoin_hu.qm</file>
|
||||
@@ -71,6 +74,7 @@
|
||||
<file alias="nl">locale/bitcoin_nl.qm</file>
|
||||
<file alias="pl">locale/bitcoin_pl.qm</file>
|
||||
<file alias="pt_BR">locale/bitcoin_pt_BR.qm</file>
|
||||
<file alias="pt_PT">locale/bitcoin_pt_PT.qm</file>
|
||||
<file alias="ro_RO">locale/bitcoin_ro_RO.qm</file>
|
||||
<file alias="ru">locale/bitcoin_ru.qm</file>
|
||||
<file alias="sk">locale/bitcoin_sk.qm</file>
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
This is:
|
||||
- All numbers except for '0'
|
||||
- All uppercase letters except for 'I' and 'O'
|
||||
- All lowercase letters except for 'l'
|
||||
- All upper-case letters except for 'I' and 'O'
|
||||
- All lower-case letters except for 'l'
|
||||
|
||||
User friendly Base58 input can map
|
||||
- 'l' and 'I' to '1'
|
||||
@@ -25,17 +25,11 @@ QValidator::State BitcoinAddressValidator::validate(QString &input, int &pos) co
|
||||
{
|
||||
bool removeChar = false;
|
||||
QChar ch = input.at(idx);
|
||||
// Transform characters that are visually close
|
||||
// Corrections made are very conservative on purpose, to avoid
|
||||
// users unexpectedly getting away with typos that would normally
|
||||
// be detected, and thus sending to the wrong address.
|
||||
switch(ch.unicode())
|
||||
{
|
||||
case 'l':
|
||||
case 'I':
|
||||
input[idx] = QChar('1');
|
||||
break;
|
||||
case '0':
|
||||
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
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
/** Make field empty and ready for new input. */
|
||||
void clear();
|
||||
|
||||
/** Qt messes up the tab chain by default in some cases (issue http://bugreports.qt.nokia.com/browse/QTBUG-10907),
|
||||
/** Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907),
|
||||
in these cases we have to set it up manually.
|
||||
*/
|
||||
QWidget *setupTabChain(QWidget *prev);
|
||||
@@ -40,7 +40,7 @@ signals:
|
||||
void textChanged();
|
||||
|
||||
protected:
|
||||
/** Intercept focus-in event and ',' keypresses */
|
||||
/** Intercept focus-in event and ',' key presses */
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "transactiontablemodel.h"
|
||||
#include "addressbookpage.h"
|
||||
#include "sendcoinsdialog.h"
|
||||
#include "messagepage.h"
|
||||
#include "signverifymessagedialog.h"
|
||||
#include "optionsdialog.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "clientmodel.h"
|
||||
@@ -24,8 +24,9 @@
|
||||
#include "askpassphrasedialog.h"
|
||||
#include "notificator.h"
|
||||
#include "guiutil.h"
|
||||
#include "rpcconsole.h"
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#ifdef Q_OS_MAC
|
||||
#include "macdockiconhandler.h"
|
||||
#endif
|
||||
|
||||
@@ -50,9 +51,9 @@
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QUrl>
|
||||
#include <QStyle>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -64,11 +65,13 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
changePassphraseAction(0),
|
||||
aboutQtAction(0),
|
||||
trayIcon(0),
|
||||
notificator(0)
|
||||
notificator(0),
|
||||
rpcConsole(0)
|
||||
{
|
||||
resize(850, 550);
|
||||
setWindowTitle(tr("Bitcoin Wallet"));
|
||||
#ifndef Q_WS_MAC
|
||||
setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
|
||||
#ifndef Q_OS_MAC
|
||||
qApp->setWindowIcon(QIcon(":icons/bitcoin"));
|
||||
setWindowIcon(QIcon(":icons/bitcoin"));
|
||||
#else
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
@@ -104,7 +107,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
|
||||
sendCoinsPage = new SendCoinsDialog(this);
|
||||
|
||||
messagePage = new MessagePage(this);
|
||||
signVerifyMessageDialog = new SignVerifyMessageDialog(this);
|
||||
|
||||
centralWidget = new QStackedWidget(this);
|
||||
centralWidget->addWidget(overviewPage);
|
||||
@@ -112,9 +115,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
centralWidget->addWidget(addressBookPage);
|
||||
centralWidget->addWidget(receiveCoinsPage);
|
||||
centralWidget->addWidget(sendCoinsPage);
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
centralWidget->addWidget(messagePage);
|
||||
#endif
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
// Create status bar
|
||||
@@ -146,6 +146,15 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
progressBar->setAlignment(Qt::AlignCenter);
|
||||
progressBar->setVisible(false);
|
||||
|
||||
// Override style sheet for progress bar for styles that have a segmented progress bar,
|
||||
// as they make the text unreadable (workaround for issue #1071)
|
||||
// See https://qt-project.org/doc/qt-4.8/gallery.html
|
||||
QString curStyle = qApp->style()->metaObject()->className();
|
||||
if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
|
||||
{
|
||||
progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }");
|
||||
}
|
||||
|
||||
statusBar()->addWidget(progressBarLabel);
|
||||
statusBar()->addWidget(progressBar);
|
||||
statusBar()->addPermanentWidget(frameBlocks);
|
||||
@@ -154,16 +163,27 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
|
||||
// Clicking on a transaction on the overview page simply sends you to transaction history page
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
|
||||
|
||||
// Doubleclicking on a transaction on the transaction history page shows details
|
||||
// Double-clicking on a transaction on the transaction history page shows details
|
||||
connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
|
||||
|
||||
rpcConsole = new RPCConsole(this);
|
||||
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
|
||||
|
||||
// Clicking on "Verify Message" in the address book sends you to the verify message tab
|
||||
connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString)));
|
||||
// Clicking on "Sign Message" in the receive coins page sends you to the sign message tab
|
||||
connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString)));
|
||||
|
||||
gotoOverviewPage();
|
||||
}
|
||||
|
||||
BitcoinGUI::~BitcoinGUI()
|
||||
{
|
||||
#ifdef Q_WS_MAC
|
||||
if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
|
||||
trayIcon->hide();
|
||||
#ifdef Q_OS_MAC
|
||||
delete appMenuBar;
|
||||
#endif
|
||||
}
|
||||
@@ -178,6 +198,18 @@ void BitcoinGUI::createActions()
|
||||
overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
|
||||
tabGroup->addAction(overviewAction);
|
||||
|
||||
sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
|
||||
sendCoinsAction->setToolTip(tr("Send coins to a Bitcoin address"));
|
||||
sendCoinsAction->setCheckable(true);
|
||||
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
|
||||
tabGroup->addAction(sendCoinsAction);
|
||||
|
||||
receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
|
||||
receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments"));
|
||||
receiveCoinsAction->setCheckable(true);
|
||||
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
|
||||
tabGroup->addAction(receiveCoinsAction);
|
||||
|
||||
historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
|
||||
historyAction->setToolTip(tr("Browse transaction history"));
|
||||
historyAction->setCheckable(true);
|
||||
@@ -190,76 +222,61 @@ void BitcoinGUI::createActions()
|
||||
addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
|
||||
tabGroup->addAction(addressBookAction);
|
||||
|
||||
receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
|
||||
receiveCoinsAction->setToolTip(tr("Show the list of addresses for receiving payments"));
|
||||
receiveCoinsAction->setCheckable(true);
|
||||
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
|
||||
tabGroup->addAction(receiveCoinsAction);
|
||||
|
||||
sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
|
||||
sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address"));
|
||||
sendCoinsAction->setCheckable(true);
|
||||
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
|
||||
tabGroup->addAction(sendCoinsAction);
|
||||
|
||||
messageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message"), this);
|
||||
messageAction->setToolTip(tr("Prove you control an address"));
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
messageAction->setCheckable(true);
|
||||
#endif
|
||||
tabGroup->addAction(messageAction);
|
||||
|
||||
connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
|
||||
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
|
||||
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
|
||||
connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
|
||||
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
|
||||
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
|
||||
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
|
||||
connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage()));
|
||||
|
||||
quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
|
||||
quitAction->setToolTip(tr("Quit application"));
|
||||
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
|
||||
quitAction->setMenuRole(QAction::QuitRole);
|
||||
aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About %1").arg(qApp->applicationName()), this);
|
||||
aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
|
||||
aboutAction->setToolTip(tr("Show information about Bitcoin"));
|
||||
aboutAction->setMenuRole(QAction::AboutRole);
|
||||
aboutQtAction = new QAction(tr("About &Qt"), this);
|
||||
aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this);
|
||||
aboutQtAction->setToolTip(tr("Show information about Qt"));
|
||||
aboutQtAction->setMenuRole(QAction::AboutQtRole);
|
||||
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
|
||||
optionsAction->setToolTip(tr("Modify configuration options for bitcoin"));
|
||||
optionsAction->setToolTip(tr("Modify configuration options for Bitcoin"));
|
||||
optionsAction->setMenuRole(QAction::PreferencesRole);
|
||||
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);
|
||||
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
|
||||
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
|
||||
encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet"));
|
||||
encryptWalletAction->setCheckable(true);
|
||||
backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet"), this);
|
||||
backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
|
||||
backupWalletAction->setToolTip(tr("Backup wallet to another location"));
|
||||
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase"), this);
|
||||
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
|
||||
changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption"));
|
||||
signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
|
||||
verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
|
||||
|
||||
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
|
||||
exportAction->setToolTip(tr("Export the data in the current tab to a file"));
|
||||
openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this);
|
||||
openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console"));
|
||||
|
||||
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
|
||||
connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
|
||||
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
|
||||
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
|
||||
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()));
|
||||
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
|
||||
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
|
||||
}
|
||||
|
||||
void BitcoinGUI::createMenuBar()
|
||||
{
|
||||
#ifdef Q_WS_MAC
|
||||
#ifdef Q_OS_MAC
|
||||
// Create a decoupled menu bar on Mac which stays even if the window is closed
|
||||
appMenuBar = new QMenuBar();
|
||||
#else
|
||||
@@ -271,9 +288,8 @@ void BitcoinGUI::createMenuBar()
|
||||
QMenu *file = appMenuBar->addMenu(tr("&File"));
|
||||
file->addAction(backupWalletAction);
|
||||
file->addAction(exportAction);
|
||||
#ifndef FIRST_CLASS_MESSAGING
|
||||
file->addAction(messageAction);
|
||||
#endif
|
||||
file->addAction(signMessageAction);
|
||||
file->addAction(verifyMessageAction);
|
||||
file->addSeparator();
|
||||
file->addAction(quitAction);
|
||||
|
||||
@@ -284,6 +300,8 @@ void BitcoinGUI::createMenuBar()
|
||||
settings->addAction(optionsAction);
|
||||
|
||||
QMenu *help = appMenuBar->addMenu(tr("&Help"));
|
||||
help->addAction(openRPCConsoleAction);
|
||||
help->addSeparator();
|
||||
help->addAction(aboutAction);
|
||||
help->addAction(aboutQtAction);
|
||||
}
|
||||
@@ -297,9 +315,6 @@ void BitcoinGUI::createToolBars()
|
||||
toolbar->addAction(receiveCoinsAction);
|
||||
toolbar->addAction(historyAction);
|
||||
toolbar->addAction(addressBookAction);
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
toolbar->addAction(messageAction);
|
||||
#endif
|
||||
|
||||
QToolBar *toolbar2 = addToolBar(tr("Actions toolbar"));
|
||||
toolbar2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
@@ -311,31 +326,39 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
||||
this->clientModel = clientModel;
|
||||
if(clientModel)
|
||||
{
|
||||
// Replace some strings and icons, when using the testnet
|
||||
if(clientModel->isTestNet())
|
||||
{
|
||||
QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
|
||||
setWindowTitle(title_testnet);
|
||||
#ifndef Q_WS_MAC
|
||||
setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]"));
|
||||
#ifndef Q_OS_MAC
|
||||
qApp->setWindowIcon(QIcon(":icons/bitcoin_testnet"));
|
||||
setWindowIcon(QIcon(":icons/bitcoin_testnet"));
|
||||
#else
|
||||
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
|
||||
#endif
|
||||
if(trayIcon)
|
||||
{
|
||||
trayIcon->setToolTip(title_testnet);
|
||||
trayIcon->setToolTip(tr("Bitcoin client") + QString(" ") + tr("[testnet]"));
|
||||
trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
|
||||
toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet"));
|
||||
}
|
||||
|
||||
aboutAction->setIcon(QIcon(":/icons/toolbar_testnet"));
|
||||
}
|
||||
|
||||
// Keep up to date with client
|
||||
setNumConnections(clientModel->getNumConnections());
|
||||
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
|
||||
|
||||
setNumBlocks(clientModel->getNumBlocks());
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
|
||||
setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
|
||||
connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
|
||||
|
||||
// Report errors from network/worker thread
|
||||
connect(clientModel, SIGNAL(error(QString,QString, bool)), this, SLOT(error(QString,QString,bool)));
|
||||
connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool)));
|
||||
|
||||
rpcConsole->setClientModel(clientModel);
|
||||
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,12 +377,12 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
|
||||
addressBookPage->setModel(walletModel->getAddressTableModel());
|
||||
receiveCoinsPage->setModel(walletModel->getAddressTableModel());
|
||||
sendCoinsPage->setModel(walletModel);
|
||||
messagePage->setModel(walletModel);
|
||||
signVerifyMessageDialog->setModel(walletModel);
|
||||
|
||||
setEncryptionStatus(walletModel->getEncryptionStatus());
|
||||
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
|
||||
|
||||
// Balloon popup for new transaction
|
||||
// Balloon pop-up for new transaction
|
||||
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(incomingTransaction(QModelIndex,int,int)));
|
||||
|
||||
@@ -371,7 +394,7 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
|
||||
void BitcoinGUI::createTrayIcon()
|
||||
{
|
||||
QMenu *trayIconMenu;
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
trayIcon = new QSystemTrayIcon(this);
|
||||
trayIconMenu = new QMenu(this);
|
||||
trayIcon->setContextMenu(trayIconMenu);
|
||||
@@ -389,55 +412,33 @@ void BitcoinGUI::createTrayIcon()
|
||||
// Configuration of the tray icon (or dock icon) icon menu
|
||||
trayIconMenu->addAction(toggleHideAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(messageAction);
|
||||
#ifndef FIRST_CLASS_MESSAGING
|
||||
trayIconMenu->addSeparator();
|
||||
#endif
|
||||
trayIconMenu->addAction(receiveCoinsAction);
|
||||
trayIconMenu->addAction(sendCoinsAction);
|
||||
trayIconMenu->addAction(receiveCoinsAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(signMessageAction);
|
||||
trayIconMenu->addAction(verifyMessageAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(optionsAction);
|
||||
#ifndef Q_WS_MAC // This is built-in on Mac
|
||||
trayIconMenu->addAction(openRPCConsoleAction);
|
||||
#ifndef Q_OS_MAC // This is built-in on Mac
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(quitAction);
|
||||
#endif
|
||||
|
||||
notificator = new Notificator(tr("bitcoin-qt"), trayIcon);
|
||||
notificator = new Notificator(qApp->applicationName(), trayIcon);
|
||||
}
|
||||
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
if(reason == QSystemTrayIcon::Trigger)
|
||||
{
|
||||
// Click on system tray icon triggers "show/hide bitcoin"
|
||||
// Click on system tray icon triggers show/hide of the main window
|
||||
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())
|
||||
@@ -469,9 +470,9 @@ void BitcoinGUI::setNumConnections(int count)
|
||||
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
|
||||
}
|
||||
|
||||
void BitcoinGUI::setNumBlocks(int count)
|
||||
void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
|
||||
{
|
||||
// don't show / hide progressBar and it's label if we have no connection(s) to the network
|
||||
// don't show / hide progress bar and its label if we have no connection to the network
|
||||
if (!clientModel || clientModel->getNumConnections() == 0)
|
||||
{
|
||||
progressBarLabel->setVisible(false);
|
||||
@@ -480,7 +481,7 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
return;
|
||||
}
|
||||
|
||||
int nTotalBlocks = clientModel->getNumBlocksOfPeers();
|
||||
QString strStatusBarWarnings = clientModel->getStatusBarWarnings();
|
||||
QString tooltip;
|
||||
|
||||
if(count < nTotalBlocks)
|
||||
@@ -488,7 +489,7 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
int nRemainingBlocks = nTotalBlocks - count;
|
||||
float nPercentageDone = count / (nTotalBlocks * 0.01f);
|
||||
|
||||
if (clientModel->getStatusBarWarnings() == "")
|
||||
if (strStatusBarWarnings.isEmpty())
|
||||
{
|
||||
progressBarLabel->setText(tr("Synchronizing with network..."));
|
||||
progressBarLabel->setVisible(true);
|
||||
@@ -497,30 +498,28 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
progressBar->setValue(count);
|
||||
progressBar->setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBarLabel->setText(clientModel->getStatusBarWarnings());
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clientModel->getStatusBarWarnings() == "")
|
||||
if (strStatusBarWarnings.isEmpty())
|
||||
progressBarLabel->setVisible(false);
|
||||
else
|
||||
{
|
||||
progressBarLabel->setText(clientModel->getStatusBarWarnings());
|
||||
progressBarLabel->setVisible(true);
|
||||
}
|
||||
|
||||
progressBar->setVisible(false);
|
||||
tooltip = tr("Downloaded %1 blocks of transaction history.").arg(count);
|
||||
}
|
||||
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
// Override progressBarLabel text and hide progress bar, when we have warnings to display
|
||||
if (!strStatusBarWarnings.isEmpty())
|
||||
{
|
||||
progressBarLabel->setText(strStatusBarWarnings);
|
||||
progressBarLabel->setVisible(true);
|
||||
progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
QDateTime lastBlockDate = clientModel->getLastBlockDate();
|
||||
int secs = lastBlockDate.secsTo(now);
|
||||
int secs = lastBlockDate.secsTo(QDateTime::currentDateTime());
|
||||
QString text;
|
||||
|
||||
// Represent time from last generated block in human readable text
|
||||
@@ -548,22 +547,29 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
// Set icon state: spinning if catching up, tick otherwise
|
||||
if(secs < 90*60 && count >= nTotalBlocks)
|
||||
{
|
||||
tooltip = tr("Up to date") + QString(".\n") + tooltip;
|
||||
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
|
||||
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
|
||||
|
||||
overviewPage->showOutOfSyncWarning(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip = tr("Catching up...") + QString("\n") + tooltip;
|
||||
tooltip = tr("Catching up...") + QString("<br>") + tooltip;
|
||||
labelBlocksIcon->setMovie(syncIconMovie);
|
||||
syncIconMovie->start();
|
||||
|
||||
overviewPage->showOutOfSyncWarning(true);
|
||||
}
|
||||
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
tooltip += QString("\n");
|
||||
tooltip += QString("<br>");
|
||||
tooltip += tr("Last received block was generated %1.").arg(text);
|
||||
}
|
||||
|
||||
// Don't word-wrap this (fixed-width) tooltip
|
||||
tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
|
||||
|
||||
labelBlocksIcon->setToolTip(tooltip);
|
||||
progressBarLabel->setToolTip(tooltip);
|
||||
progressBar->setToolTip(tooltip);
|
||||
@@ -583,7 +589,7 @@ void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
|
||||
void BitcoinGUI::changeEvent(QEvent *e)
|
||||
{
|
||||
QMainWindow::changeEvent(e);
|
||||
#ifndef Q_WS_MAC // Ignored on Mac
|
||||
#ifndef Q_OS_MAC // Ignored on Mac
|
||||
if(e->type() == QEvent::WindowStateChange)
|
||||
{
|
||||
if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray())
|
||||
@@ -603,7 +609,7 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if(clientModel)
|
||||
{
|
||||
#ifndef Q_WS_MAC // Ignored on Mac
|
||||
#ifndef Q_OS_MAC // Ignored on Mac
|
||||
if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
|
||||
!clientModel->getOptionsModel()->getMinimizeOnClose())
|
||||
{
|
||||
@@ -622,7 +628,7 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
|
||||
"Do you want to pay the fee?").arg(
|
||||
BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nFeeRequired));
|
||||
QMessageBox::StandardButton retval = QMessageBox::question(
|
||||
this, tr("Sending..."), strMessage,
|
||||
this, tr("Confirm transaction fee"), strMessage,
|
||||
QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes);
|
||||
*payFee = (retval == QMessageBox::Yes);
|
||||
}
|
||||
@@ -710,24 +716,22 @@ void BitcoinGUI::gotoSendCoinsPage()
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoMessagePage()
|
||||
void BitcoinGUI::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
messageAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(messagePage);
|
||||
// call show() in showTab_SM()
|
||||
signVerifyMessageDialog->showTab_SM(true);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
#else
|
||||
messagePage->show();
|
||||
messagePage->setFocus();
|
||||
#endif
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_SM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoMessagePage(QString addr)
|
||||
void BitcoinGUI::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
gotoMessagePage();
|
||||
messagePage->setAddress(addr);
|
||||
// call show() in showTab_VM()
|
||||
signVerifyMessageDialog->showTab_VM(true);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_VM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
|
||||
@@ -741,12 +745,19 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if(event->mimeData()->hasUrls())
|
||||
{
|
||||
gotoSendCoinsPage();
|
||||
int nValidUrisFound = 0;
|
||||
QList<QUrl> uris = event->mimeData()->urls();
|
||||
foreach(const QUrl &uri, uris)
|
||||
{
|
||||
sendCoinsPage->handleURI(uri.toString());
|
||||
if (sendCoinsPage->handleURI(uri.toString()))
|
||||
nValidUrisFound++;
|
||||
}
|
||||
|
||||
// if valid URIs were found
|
||||
if (nValidUrisFound)
|
||||
gotoSendCoinsPage();
|
||||
else
|
||||
notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."));
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
@@ -754,13 +765,14 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
|
||||
|
||||
void BitcoinGUI::handleURI(QString strURI)
|
||||
{
|
||||
gotoSendCoinsPage();
|
||||
sendCoinsPage->handleURI(strURI);
|
||||
|
||||
if(!isActiveWindow())
|
||||
activateWindow();
|
||||
|
||||
showNormalIfMinimized();
|
||||
// URI has to be valid
|
||||
if (sendCoinsPage->handleURI(strURI))
|
||||
{
|
||||
showNormalIfMinimized();
|
||||
gotoSendCoinsPage();
|
||||
}
|
||||
else
|
||||
notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."));
|
||||
}
|
||||
|
||||
void BitcoinGUI::setEncryptionStatus(int status)
|
||||
@@ -835,10 +847,29 @@ void BitcoinGUI::unlockWallet()
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::showNormalIfMinimized()
|
||||
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
|
||||
{
|
||||
if(!isVisible()) // Show, if hidden
|
||||
// activateWindow() (sometimes) helps with keyboard focus on Windows
|
||||
if (isHidden())
|
||||
{
|
||||
show();
|
||||
if(isMinimized()) // Unminimize, if minimized
|
||||
activateWindow();
|
||||
}
|
||||
else if (isMinimized())
|
||||
{
|
||||
showNormal();
|
||||
activateWindow();
|
||||
}
|
||||
else if (GUIUtil::isObscured(this))
|
||||
{
|
||||
raise();
|
||||
activateWindow();
|
||||
}
|
||||
else if(fToggleHidden)
|
||||
hide();
|
||||
}
|
||||
|
||||
void BitcoinGUI::toggleHidden()
|
||||
{
|
||||
showNormalIfMinimized(true);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ class TransactionView;
|
||||
class OverviewPage;
|
||||
class AddressBookPage;
|
||||
class SendCoinsDialog;
|
||||
class MessagePage;
|
||||
class SignVerifyMessageDialog;
|
||||
class Notificator;
|
||||
class RPCConsole;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
@@ -45,7 +46,7 @@ public:
|
||||
functionality.
|
||||
*/
|
||||
void setWalletModel(WalletModel *walletModel);
|
||||
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
void closeEvent(QCloseEvent *event);
|
||||
@@ -63,7 +64,7 @@ private:
|
||||
AddressBookPage *addressBookPage;
|
||||
AddressBookPage *receiveCoinsPage;
|
||||
SendCoinsDialog *sendCoinsPage;
|
||||
MessagePage *messagePage;
|
||||
SignVerifyMessageDialog *signVerifyMessageDialog;
|
||||
|
||||
QLabel *labelEncryptionIcon;
|
||||
QLabel *labelConnectionsIcon;
|
||||
@@ -77,7 +78,8 @@ private:
|
||||
QAction *quitAction;
|
||||
QAction *sendCoinsAction;
|
||||
QAction *addressBookAction;
|
||||
QAction *messageAction;
|
||||
QAction *signMessageAction;
|
||||
QAction *verifyMessageAction;
|
||||
QAction *aboutAction;
|
||||
QAction *receiveCoinsAction;
|
||||
QAction *optionsAction;
|
||||
@@ -87,16 +89,18 @@ private:
|
||||
QAction *backupWalletAction;
|
||||
QAction *changePassphraseAction;
|
||||
QAction *aboutQtAction;
|
||||
QAction *openRPCConsoleAction;
|
||||
|
||||
QSystemTrayIcon *trayIcon;
|
||||
Notificator *notificator;
|
||||
TransactionView *transactionView;
|
||||
RPCConsole *rpcConsole;
|
||||
|
||||
QMovie *syncIconMovie;
|
||||
|
||||
/** Create the main UI actions. */
|
||||
void createActions();
|
||||
/** Create the menu bar and submenus. */
|
||||
/** Create the menu bar and sub-menus. */
|
||||
void createMenuBar();
|
||||
/** Create the toolbars */
|
||||
void createToolBars();
|
||||
@@ -107,7 +111,7 @@ public slots:
|
||||
/** Set number of connections shown in the UI */
|
||||
void setNumConnections(int count);
|
||||
/** Set number of blocks shown in the UI */
|
||||
void setNumBlocks(int count);
|
||||
void setNumBlocks(int count, int nTotalBlocks);
|
||||
/** Set the encryption status as shown in the UI.
|
||||
@param[in] status current encryption status
|
||||
@see WalletModel::EncryptionStatus
|
||||
@@ -119,7 +123,7 @@ public slots:
|
||||
/** 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.
|
||||
http://bugreports.qt.nokia.com/browse/QTBUG-10440
|
||||
https://bugreports.qt-project.org/browse/QTBUG-10440
|
||||
|
||||
@param[in] nFeeRequired the required fee
|
||||
@param[out] payFee true to pay the fee, false to not pay the fee
|
||||
@@ -127,9 +131,6 @@ public slots:
|
||||
void askFee(qint64 nFeeRequired, bool *payFee);
|
||||
void handleURI(QString strURI);
|
||||
|
||||
void gotoMessagePage();
|
||||
void gotoMessagePage(QString);
|
||||
|
||||
private slots:
|
||||
/** Switch to overview (home) page */
|
||||
void gotoOverviewPage();
|
||||
@@ -142,11 +143,16 @@ private slots:
|
||||
/** Switch to send coins page */
|
||||
void gotoSendCoinsPage();
|
||||
|
||||
/** Show Sign/Verify Message dialog and switch to sign message tab */
|
||||
void gotoSignMessageTab(QString addr = "");
|
||||
/** Show Sign/Verify Message dialog and switch to verify message tab */
|
||||
void gotoVerifyMessageTab(QString addr = "");
|
||||
|
||||
/** Show configuration dialog */
|
||||
void optionsClicked();
|
||||
/** Show about dialog */
|
||||
void aboutClicked();
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
/** Handle tray icon clicked */
|
||||
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
#endif
|
||||
@@ -161,12 +167,12 @@ private slots:
|
||||
void backupWallet();
|
||||
/** Change encrypted wallet passphrase */
|
||||
void changePassphrase();
|
||||
/** Ask for pass phrase to unlock wallet temporarily */
|
||||
/** Ask for passphrase to unlock wallet temporarily */
|
||||
void unlockWallet();
|
||||
|
||||
/** Show window if hidden, unminimize when minimized */
|
||||
void showNormalIfMinimized();
|
||||
/** Hide window if visible, show if hidden */
|
||||
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
|
||||
void showNormalIfMinimized(bool fToggleHidden = false);
|
||||
/** simply calls showNormalIfMinimized(true) for use in SLOT() macro */
|
||||
void toggleHidden();
|
||||
};
|
||||
|
||||
|
||||
@@ -5,101 +5,7 @@
|
||||
#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"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify configuration file (default: bitcoin.conf)"),
|
||||
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 and attempt to keep the connection open"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node"),
|
||||
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", "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"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to debugger"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
|
||||
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)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"),
|
||||
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..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading blkindex.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading wallet..."),
|
||||
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"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>"),
|
||||
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", "To use the %s option"),
|
||||
static const char UNUSED *bitcoin_strings[] = {
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"%s, you must set a rpcpassword in the configuration file:\n"
|
||||
" %s\n"
|
||||
@@ -109,26 +15,162 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"(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", ""
|
||||
"Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:"
|
||||
"@STRENGTH)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"An error occurred while setting up the RPC port %u for listening on IPv4: %s"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"An error occurred while setting up the RPC port %u for listening on IPv6, "
|
||||
"falling back to IPv4: %s"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Cannot obtain a lock on data directory %s. Bitcoin is probably already "
|
||||
"running."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Detach block and address databases. Increases shutdown time (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Error initializing database environment %s! To recover, BACKUP THAT "
|
||||
"DIRECTORY, then remove everything from it except for wallet.dat."),
|
||||
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", ""
|
||||
"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", ""
|
||||
"Execute command when the best block changes (%s in cmd is replaced by block "
|
||||
"hash)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Number of seconds to keep misbehaving peers from reconnecting (default: "
|
||||
"86400)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Set maximum size of high-priority/low-fee transactions in bytes (default: "
|
||||
"27000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Unable to bind to %s on this computer. Bitcoin is probably already running."),
|
||||
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", ""
|
||||
"Warning: Displayed transactions may not be correct! You may need to upgrade, "
|
||||
"or other nodes may need to upgrade."),
|
||||
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", ""
|
||||
"Warning: error reading wallet.dat! All keys read correctly, but transaction "
|
||||
"data or address book entries might be missing or incorrect."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", ""
|
||||
"Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as "
|
||||
"wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect "
|
||||
"you should restore from a backup."),
|
||||
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", "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", "Accept command line and JSON-RPC commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bind to given address. Use [host]:port notation for IPv6"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot initialize keypool"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect through socks proxy"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Discover own IP address (default: 1 when listening and no -externalip)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Don't generate coins"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Done loading"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading blkindex.dat"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat"),
|
||||
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", "Error"),
|
||||
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", "Error: Wallet locked, unable to create transaction "),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Error: could not start node"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using internet relay chat (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
|
||||
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", "Importing blockchain data file."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Importing bootstrap blockchain data file."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000?.dat file"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -tor address: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "List commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: 8333 or testnet: 18333)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Loading wallet..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most <n> connections to peers (default: 125)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4, IPv6 or Tor)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Options:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information. Implies all other -debug* options"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Output extra network debugging information"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Select the version of socks proxy to use (4-5, default: 5)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send command to -server or bitcoind"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on <ip> (default: 127.0.0.1)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to debugger"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Sending..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"),
|
||||
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", "Set key pool size to <n> (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: 250000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify configuration file (default: bitcoin.conf)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify connection timeout in milliseconds (default: 5000)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify data directory"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: bitcoind.pid)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "This help message"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %d, %s)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use proxy to reach tor hidden services (default: same as -proxy)"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying database integrity..."),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Disk space is low!"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"),
|
||||
QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"),
|
||||
};
|
||||
@@ -99,7 +99,7 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
|
||||
QString quotient_str = QString::number(quotient);
|
||||
QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
|
||||
|
||||
// Right-trim excess 0's after the decimal point
|
||||
// Right-trim excess zeros after the decimal point
|
||||
int nTrim = 0;
|
||||
for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
|
||||
++nTrim;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <QAbstractListModel>
|
||||
|
||||
/** Bitcoin unit definitions. Encapsulates parsing and formatting
|
||||
and serves as list model for dropdown selection boxes.
|
||||
and serves as list model for drop-down selection boxes.
|
||||
*/
|
||||
class BitcoinUnits: public QAbstractListModel
|
||||
{
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
//! Unit conversion and formatting
|
||||
///@{
|
||||
|
||||
//! Get list of units, for dropdown box
|
||||
//! Get list of units, for drop-down box
|
||||
static QList<Unit> availableUnits();
|
||||
//! Is unit ID valid?
|
||||
static bool valid(int unit);
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
///@}
|
||||
|
||||
//! @name AbstractListModel implementation
|
||||
//! List model for unit dropdown selection box.
|
||||
//! List model for unit drop-down selection box.
|
||||
///@{
|
||||
enum RoleIndex {
|
||||
/** Unit identifier */
|
||||
|
||||
@@ -4,15 +4,32 @@
|
||||
#include "addresstablemodel.h"
|
||||
#include "transactiontablemodel.h"
|
||||
|
||||
#include "alert.h"
|
||||
#include "main.h"
|
||||
#include "ui_interface.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
|
||||
static const int64 nClientStartupTime = GetTime();
|
||||
|
||||
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
||||
QObject(parent), optionsModel(optionsModel),
|
||||
cachedNumConnections(0), cachedNumBlocks(0)
|
||||
cachedNumBlocks(0), cachedNumBlocksOfPeers(0), pollTimer(0)
|
||||
{
|
||||
numBlocksAtStartup = -1;
|
||||
|
||||
pollTimer = new QTimer(this);
|
||||
pollTimer->setInterval(MODEL_UPDATE_DELAY);
|
||||
pollTimer->start();
|
||||
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
|
||||
|
||||
subscribeToCoreSignals();
|
||||
}
|
||||
|
||||
ClientModel::~ClientModel()
|
||||
{
|
||||
unsubscribeFromCoreSignals();
|
||||
}
|
||||
|
||||
int ClientModel::getNumConnections() const
|
||||
@@ -36,27 +53,44 @@ QDateTime ClientModel::getLastBlockDate() const
|
||||
return QDateTime::fromTime_t(pindexBest->GetBlockTime());
|
||||
}
|
||||
|
||||
void ClientModel::update()
|
||||
void ClientModel::updateTimer()
|
||||
{
|
||||
int newNumConnections = getNumConnections();
|
||||
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
|
||||
// Periodically check and update with a timer.
|
||||
int newNumBlocks = getNumBlocks();
|
||||
QString newStatusBar = getStatusBarWarnings();
|
||||
int newNumBlocksOfPeers = getNumBlocksOfPeers();
|
||||
|
||||
if(cachedNumConnections != newNumConnections)
|
||||
emit numConnectionsChanged(newNumConnections);
|
||||
if(cachedNumBlocks != newNumBlocks || cachedStatusBar != newStatusBar)
|
||||
if(cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers)
|
||||
{
|
||||
// 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);
|
||||
cachedNumBlocks = newNumBlocks;
|
||||
cachedNumBlocksOfPeers = newNumBlocksOfPeers;
|
||||
|
||||
emit numBlocksChanged(newNumBlocks, newNumBlocksOfPeers);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientModel::updateNumConnections(int numConnections)
|
||||
{
|
||||
emit numConnectionsChanged(numConnections);
|
||||
}
|
||||
|
||||
void ClientModel::updateAlert(const QString &hash, int status)
|
||||
{
|
||||
// Show error message notification for new alert
|
||||
if(status == CT_NEW)
|
||||
{
|
||||
uint256 hash_256;
|
||||
hash_256.SetHex(hash.toStdString());
|
||||
CAlert alert = CAlert::getAlertByHash(hash_256);
|
||||
if(!alert.IsNull())
|
||||
{
|
||||
emit error(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), false);
|
||||
}
|
||||
}
|
||||
|
||||
cachedNumConnections = newNumConnections;
|
||||
cachedNumBlocks = newNumBlocks;
|
||||
cachedStatusBar = newStatusBar;
|
||||
// Emit a numBlocksChanged when the status message changes,
|
||||
// so that the view recomputes and updates the status bar.
|
||||
emit numBlocksChanged(getNumBlocks(), getNumBlocksOfPeers());
|
||||
}
|
||||
|
||||
bool ClientModel::isTestNet() const
|
||||
@@ -93,3 +127,51 @@ QString ClientModel::formatBuildDate() const
|
||||
{
|
||||
return QString::fromStdString(CLIENT_DATE);
|
||||
}
|
||||
|
||||
QString ClientModel::clientName() const
|
||||
{
|
||||
return QString::fromStdString(CLIENT_NAME);
|
||||
}
|
||||
|
||||
QString ClientModel::formatClientStartupTime() const
|
||||
{
|
||||
return QDateTime::fromTime_t(nClientStartupTime).toString();
|
||||
}
|
||||
|
||||
// Handlers for core signals
|
||||
static void NotifyBlocksChanged(ClientModel *clientmodel)
|
||||
{
|
||||
// This notification is too frequent. Don't trigger a signal.
|
||||
// Don't remove it, though, as it might be useful later.
|
||||
}
|
||||
|
||||
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
|
||||
{
|
||||
// Too noisy: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
|
||||
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
|
||||
Q_ARG(int, newNumConnections));
|
||||
}
|
||||
|
||||
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
|
||||
{
|
||||
OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), status);
|
||||
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
|
||||
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
|
||||
Q_ARG(int, status));
|
||||
}
|
||||
|
||||
void ClientModel::subscribeToCoreSignals()
|
||||
{
|
||||
// Connect signals to client
|
||||
uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
|
||||
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
}
|
||||
|
||||
void ClientModel::unsubscribeFromCoreSignals()
|
||||
{
|
||||
// Disconnect signals from client
|
||||
uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
|
||||
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class CWallet;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDateTime;
|
||||
class QTimer;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/** Model for Bitcoin network client. */
|
||||
@@ -18,6 +19,7 @@ class ClientModel : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ClientModel(OptionsModel *optionsModel, QObject *parent = 0);
|
||||
~ClientModel();
|
||||
|
||||
OptionsModel *getOptionsModel();
|
||||
|
||||
@@ -38,27 +40,32 @@ public:
|
||||
|
||||
QString formatFullVersion() const;
|
||||
QString formatBuildDate() const;
|
||||
QString clientName() const;
|
||||
QString formatClientStartupTime() const;
|
||||
|
||||
private:
|
||||
OptionsModel *optionsModel;
|
||||
|
||||
int cachedNumConnections;
|
||||
int cachedNumBlocks;
|
||||
QString cachedStatusBar;
|
||||
int cachedNumBlocksOfPeers;
|
||||
|
||||
int numBlocksAtStartup;
|
||||
|
||||
QTimer *pollTimer;
|
||||
|
||||
void subscribeToCoreSignals();
|
||||
void unsubscribeFromCoreSignals();
|
||||
signals:
|
||||
void numConnectionsChanged(int count);
|
||||
void numBlocksChanged(int count);
|
||||
void numBlocksChanged(int count, int countOfPeers);
|
||||
|
||||
//! Asynchronous error notification
|
||||
void error(const QString &title, const QString &message, bool modal);
|
||||
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void update();
|
||||
void updateTimer();
|
||||
void updateNumConnections(int numConnections);
|
||||
void updateAlert(const QString &hash, int status);
|
||||
};
|
||||
|
||||
#endif // CLIENTMODEL_H
|
||||
|
||||
@@ -93,7 +93,7 @@ void EditAddressDialog::accept()
|
||||
break;
|
||||
case AddressTableModel::INVALID_ADDRESS:
|
||||
QMessageBox::warning(this, windowTitle(),
|
||||
tr("The entered address \"%1\" is not a valid bitcoin address.").arg(ui->addressEdit->text()),
|
||||
tr("The entered address \"%1\" is not a valid Bitcoin address.").arg(ui->addressEdit->text()),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
return;
|
||||
case AddressTableModel::WALLET_UNLOCK_FAILURE:
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../bitcoin.qrc">:/images/about</pixmap>
|
||||
</property>
|
||||
@@ -49,6 +46,9 @@
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><b>Bitcoin</b> version</string>
|
||||
</property>
|
||||
@@ -59,12 +59,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="versionLabel">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0.3.666-beta</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
@@ -86,13 +86,28 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copyright © 2009-2012 Bitcoin Developers
|
||||
|
||||
<string>Copyright © 2009-2012 The Bitcoin developers</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>
|
||||
This is experimental software.
|
||||
|
||||
Distributed under the MIT/X11 software license, see the accompanying file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</string>
|
||||
</property>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>627</width>
|
||||
<height>347</height>
|
||||
<width>760</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -17,10 +17,10 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="labelExplanation">
|
||||
<property name="text">
|
||||
<string>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</string>
|
||||
<string>These are your Bitcoin addresses for receiving payments. You may want to give a different one to each sender so you can keep track of who is paying you.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -29,9 +29,15 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Double-click to edit address or label</string>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -57,7 +63,7 @@
|
||||
<string>Create a new address</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Address...</string>
|
||||
<string>&New Address</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
@@ -71,7 +77,7 @@
|
||||
<string>Copy the currently selected address to the system clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy to Clipboard</string>
|
||||
<string>&Copy Address</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
@@ -86,17 +92,17 @@
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/images/qrcode</normaloff>:/images/qrcode</iconset>
|
||||
<normaloff>:/icons/qrcode</normaloff>:/icons/qrcode</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="signMessage">
|
||||
<property name="toolTip">
|
||||
<string>Sign a message to prove you own this address</string>
|
||||
<string>Sign a message to prove you own a Bitcoin address</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Sign Message</string>
|
||||
<string>Sign &Message</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
@@ -104,10 +110,24 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="verifyMessage">
|
||||
<property name="toolTip">
|
||||
<string>Verify a message to ensure it was signed with a specified Bitcoin address</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Verify Message</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="toolTip">
|
||||
<string>Delete the currently selected address from the list. Only sending addresses can be deleted.</string>
|
||||
<string>Delete the currently selected address from the list</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Delete</string>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Passphrase Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
@@ -41,57 +41,58 @@
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="passLabel1">
|
||||
<property name="text">
|
||||
<string>Enter passphrase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="passEdit1">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="passLabel2">
|
||||
<property name="text">
|
||||
<string>New passphrase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="passEdit2">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="passLabel3">
|
||||
<property name="text">
|
||||
<string>Repeat new passphrase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="passEdit3">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="capsLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#capsLabel {
|
||||
font: bold;
|
||||
}</string>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MessagePage</class>
|
||||
<widget class="QWidget" name="MessagePage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>627</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Message</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelExplanation">
|
||||
<property name="text">
|
||||
<string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="signFrom">
|
||||
<property name="toolTip">
|
||||
<string>The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>34</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addressBookButton">
|
||||
<property name="toolTip">
|
||||
<string>Choose adress from address book</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+A</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pasteButton">
|
||||
<property name="toolTip">
|
||||
<string>Paste address from clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+P</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="message">
|
||||
<property name="toolTip">
|
||||
<string>Enter the message you want to sign here</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="signature">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Click "Sign Message" to get signature</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="signMessage">
|
||||
<property name="toolTip">
|
||||
<string>Sign a message to prove you own this address</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Sign Message</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/edit</normaloff>:/icons/edit</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="copyToClipboard">
|
||||
<property name="toolTip">
|
||||
<string>Copy the current signature to the system clipboard</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy to Clipboard</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../bitcoin.qrc">
|
||||
<normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QValidatedLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>qvalidatedlineedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../bitcoin.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
460
src/qt/forms/optionsdialog.ui
Normal file
460
src/qt/forms/optionsdialog.ui
Normal file
@@ -0,0 +1,460 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OptionsDialog</class>
|
||||
<widget class="QDialog" name="OptionsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>540</width>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabMain">
|
||||
<attribute name="title">
|
||||
<string>&Main</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Main">
|
||||
<item>
|
||||
<widget class="QLabel" name="transactionFeeInfoLabel">
|
||||
<property name="text">
|
||||
<string>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_Main">
|
||||
<item>
|
||||
<widget class="QLabel" name="transactionFeeLabel">
|
||||
<property name="text">
|
||||
<string>Pay transaction &fee</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>transactionFee</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="BitcoinAmountField" name="transactionFee"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_Main">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="bitcoinAtStartup">
|
||||
<property name="toolTip">
|
||||
<string>Automatically start Bitcoin after logging in to the system.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Start Bitcoin on system login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="detachDatabases">
|
||||
<property name="toolTip">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Detach databases at shutdown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_Main">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabNetwork">
|
||||
<attribute name="title">
|
||||
<string>&Network</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Network">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mapPortUpnp">
|
||||
<property name="toolTip">
|
||||
<string>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Map port using &UPnP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="connectSocks">
|
||||
<property name="toolTip">
|
||||
<string>Connect to the Bitcoin network through a SOCKS proxy (e.g. when connecting through Tor).</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Connect through SOCKS proxy:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_Network">
|
||||
<item>
|
||||
<widget class="QLabel" name="proxyIpLabel">
|
||||
<property name="text">
|
||||
<string>Proxy &IP:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>proxyIp</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValidatedLineEdit" name="proxyIp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>IP address of the proxy (e.g. 127.0.0.1)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="proxyPortLabel">
|
||||
<property name="text">
|
||||
<string>&Port:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>proxyPort</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="proxyPort">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Port of the proxy (e.g. 9050)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="socksVersionLabel">
|
||||
<property name="text">
|
||||
<string>SOCKS &Version:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>socksVersion</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValueComboBox" name="socksVersion">
|
||||
<property name="toolTip">
|
||||
<string>SOCKS version of the proxy (e.g. 5)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_Network">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_Network">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabWindow">
|
||||
<attribute name="title">
|
||||
<string>&Window</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Window">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="minimizeToTray">
|
||||
<property name="toolTip">
|
||||
<string>Show only a tray icon after minimizing the window.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Minimize to the tray instead of the taskbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="minimizeOnClose">
|
||||
<property name="toolTip">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>M&inimize on close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_Window">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabDisplay">
|
||||
<attribute name="title">
|
||||
<string>&Display</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Display">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_1_Display">
|
||||
<item>
|
||||
<widget class="QLabel" name="langLabel">
|
||||
<property name="text">
|
||||
<string>User Interface &language:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lang</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValueComboBox" name="lang">
|
||||
<property name="toolTip">
|
||||
<string>The user interface language can be set here. This setting will take effect after restarting Bitcoin.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2_Display">
|
||||
<item>
|
||||
<widget class="QLabel" name="unitLabel">
|
||||
<property name="text">
|
||||
<string>&Unit to show amounts in:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>unit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QValueComboBox" name="unit">
|
||||
<property name="toolTip">
|
||||
<string>Choose the default subdivision unit to show in the interface and when sending coins.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="displayAddresses">
|
||||
<property name="toolTip">
|
||||
<string>Whether to show Bitcoin addresses in the transaction list or not.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Display addresses in transaction list</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_Display">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_Buttons">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="statusLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="text">
|
||||
<string>&OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="applyButton">
|
||||
<property name="text">
|
||||
<string>&Apply</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BitcoinAmountField</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>bitcoinamountfield.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QValueComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>qvaluecombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QValidatedLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>qvalidatedlineedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user