mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-25 09:34:19 +01:00
Compare commits
884 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a4e67afad | ||
|
|
b3295cd283 | ||
|
|
c1d79812f4 | ||
|
|
d078739965 | ||
|
|
8b1eb5687d | ||
|
|
a21bdda7ad | ||
|
|
ab91bf39b7 | ||
|
|
0e08efc54a | ||
|
|
b019ea17ec | ||
|
|
eabc8f2c81 | ||
|
|
d8ecd21ff7 | ||
|
|
23a44a7ad6 | ||
|
|
85eb1e7e56 | ||
|
|
31fac119dc | ||
|
|
4ee706243c | ||
|
|
5cb01b5714 | ||
|
|
2dc953274d | ||
|
|
db1967957d | ||
|
|
7b1504ccb8 | ||
|
|
f875921176 | ||
|
|
af8c050bff | ||
|
|
b9a4aaad1e | ||
|
|
f106491fa2 | ||
|
|
1913b6e2fc | ||
|
|
3c28b335af | ||
|
|
004fa1441c | ||
|
|
4dc89fa875 | ||
|
|
97e02a8d52 | ||
|
|
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 | ||
|
|
74d36d44f2 | ||
|
|
6117afeeaa | ||
|
|
c7df832d7a | ||
|
|
1b4bd4c976 | ||
|
|
fc52af2736 | ||
|
|
29316f7bd0 | ||
|
|
3f37f20ddc | ||
|
|
e273c51287 | ||
|
|
6a60c64c6b | ||
|
|
3595b18793 | ||
|
|
5f38875807 | ||
|
|
af4da4be3d | ||
|
|
3588c91c7e | ||
|
|
286dbba2d2 | ||
|
|
f35c6c4fb9 | ||
|
|
9eb7fc5842 | ||
|
|
06707dd610 | ||
|
|
9c63fd8e76 | ||
|
|
8ef51cf15c | ||
|
|
41b2856bd4 | ||
|
|
e598b5b5c2 | ||
|
|
0d9556f948 | ||
|
|
4f6a85b3bd | ||
|
|
0eeb54cb89 | ||
|
|
ba7ba84f07 | ||
|
|
f29eaee30a | ||
|
|
03fa53a640 | ||
|
|
a1755ec426 | ||
|
|
fde5c34bd8 | ||
|
|
ef8e821cf2 | ||
|
|
8cd98a9a26 | ||
|
|
ea2fda46c3 | ||
|
|
028ec224b8 | ||
|
|
d0377a70e2 | ||
|
|
1837696580 | ||
|
|
d5a52d9b3e | ||
|
|
772351b0d5 | ||
|
|
9db9642db4 | ||
|
|
b9c078ea96 | ||
|
|
8f3f554053 | ||
|
|
12324c1693 | ||
|
|
bc8d832335 | ||
|
|
382b75f528 | ||
|
|
af1c6b93b7 | ||
|
|
9fd537965d | ||
|
|
65ce215641 | ||
|
|
c68c4bc7a4 | ||
|
|
b1093efa83 | ||
|
|
bdab0cf58c | ||
|
|
0050cf21ce | ||
|
|
e07c8e9123 | ||
|
|
1bcd3f26c0 | ||
|
|
9655d73f49 | ||
|
|
45beb88966 | ||
|
|
e422bebbdc | ||
|
|
579d011738 | ||
|
|
05fa0de6d8 | ||
|
|
92735bca31 | ||
|
|
22dfd73598 | ||
|
|
47753fa369 | ||
|
|
c3f95ef13f | ||
|
|
bdbfd2329a | ||
|
|
9c7722b7c5 | ||
|
|
cf78183fad | ||
|
|
de363e73ea | ||
|
|
331544bc37 | ||
|
|
b765385a3e | ||
|
|
0b886ad1bd | ||
|
|
e95568b78d | ||
|
|
fedd060d81 | ||
|
|
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 | ||
|
|
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 | ||
|
|
701e1f5254 | ||
|
|
ebeafe5b0b | ||
|
|
c32ad4594e | ||
|
|
6892cb056d | ||
|
|
50c85be6fc | ||
|
|
f00ffc6c00 | ||
|
|
f5a3dbea40 | ||
|
|
2acfa219aa | ||
|
|
64c0020ff8 | ||
|
|
6fe375c3bd | ||
|
|
12e5881c09 | ||
|
|
26227db843 | ||
|
|
951f7d35d6 | ||
|
|
0bf30d2b33 | ||
|
|
90d95b6323 | ||
|
|
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 | ||
|
|
ea53f183fc | ||
|
|
6ece1d747e | ||
|
|
c7441658da | ||
|
|
9af3c3c824 | ||
|
|
0e3947ef32 | ||
|
|
0ba5bacd0c | ||
|
|
b19811d5f4 | ||
|
|
249856d557 | ||
|
|
520198138a | ||
|
|
08492c952b | ||
|
|
9502ee3b5f | ||
|
|
5c83f797c5 | ||
|
|
2a919e396d | ||
|
|
dae3e10a5a | ||
|
|
47894585ae | ||
|
|
a75b45fcd3 | ||
|
|
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 | ||
|
|
b768a38b76 | ||
|
|
0783bcceef | ||
|
|
d65e959bae | ||
|
|
219abac227 | ||
|
|
70f6049f71 | ||
|
|
703db97d80 | ||
|
|
229c34f818 | ||
|
|
c283b3c569 | ||
|
|
451c3957fe | ||
|
|
16d5671943 | ||
|
|
4c6b210af0 | ||
|
|
0f5a2a82d9 | ||
|
|
c5532e188e | ||
|
|
7596a030c6 | ||
|
|
550c73f4c8 | ||
|
|
baf814f3da | ||
|
|
8b7b3be765 | ||
|
|
5204ca87e2 | ||
|
|
2bbfcd2d02 | ||
|
|
432d28d3bb | ||
|
|
896899e0d6 | ||
|
|
a54d2118be | ||
|
|
8ce04527f9 | ||
|
|
6062de265a | ||
|
|
3bbb49de55 | ||
|
|
e0873dafc5 | ||
|
|
07368a9e3c | ||
|
|
ad5f29b743 | ||
|
|
1d42878adb | ||
|
|
39471861d5 | ||
|
|
fab7858a35 | ||
|
|
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 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
src/*.exe
|
||||
src/bitcoin
|
||||
src/bitcoind
|
||||
src/test_bitcoin
|
||||
src/build.h
|
||||
.*.swp
|
||||
*.*~*
|
||||
@@ -20,3 +21,4 @@ qrc_*.cpp
|
||||
*.pro.user
|
||||
#mac specific
|
||||
.DS_Store
|
||||
build
|
||||
|
||||
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.
|
||||
@@ -1,19 +1,19 @@
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
VERSION = 0.6.1
|
||||
TARGET = bitcoin-qt
|
||||
VERSION = 0.7.0
|
||||
INCLUDEPATH += src src/json src/qt
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
|
||||
CONFIG += no_include_pwd
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
# 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 +30,9 @@ contains(RELEASE, 1) {
|
||||
}
|
||||
}
|
||||
|
||||
# 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) {
|
||||
@@ -68,6 +71,18 @@ contains(FIRST_CLASS_MESSAGING, 1) {
|
||||
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) {
|
||||
DEFINES += BITCOIN_NEED_QT_PLUGINS
|
||||
QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
|
||||
@@ -77,20 +92,20 @@ contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
# 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!
|
||||
# do not enable this on windows cross compile with mingw 4.2.x, 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; share/genbuild.sh $$OUT_PWD/build/build.h
|
||||
genbuild.target = genbuildhook
|
||||
PRE_TARGETDEPS += genbuildhook
|
||||
genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h
|
||||
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
|
||||
|
||||
# Input
|
||||
DEPENDPATH += src src/json src/qt
|
||||
@@ -100,15 +115,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 +175,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 +187,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 +206,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 +222,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 +237,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 +247,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 +283,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 +326,7 @@ isEmpty(BOOST_INCLUDE_PATH) {
|
||||
macx:BOOST_INCLUDE_PATH = /opt/local/include
|
||||
}
|
||||
|
||||
windows:LIBS += -lws2_32 -lshlwapi
|
||||
windows:LIBS += -lws2_32 -lshlwapi -lmswsock
|
||||
windows:DEFINES += WIN32
|
||||
windows:RC_FILE = src/qt/res/bitcoin-qt.rc
|
||||
|
||||
@@ -332,6 +360,7 @@ LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX
|
||||
# -lgdi32 has to happen after -lcrypto (see #681)
|
||||
windows:LIBS += -lole32 -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,
|
||||
@@ -35,7 +36,7 @@ Description: peer-to-peer network based digital currency - daemon
|
||||
By default connects to an IRC network to discover other peers.
|
||||
.
|
||||
Full transaction history is stored locally at each client. This
|
||||
requires 150+ MB of space, slowly growing.
|
||||
requires 2+ GB of space, slowly growing.
|
||||
.
|
||||
This package provides bitcoind, a combined daemon and CLI tool to
|
||||
interact with the daemon.
|
||||
@@ -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
|
||||
@@ -53,6 +54,6 @@ Description: peer-to-peer network based digital currency - QT GUI
|
||||
By default connects to an IRC network to discover other peers.
|
||||
.
|
||||
Full transaction history is stored locally at each client. This
|
||||
requires 150+ MB of space, slowly growing.
|
||||
requires 2+ GB of space, slowly growing.
|
||||
.
|
||||
This package provides bitcoin-qt, a GUI for Bitcoin based on QT.
|
||||
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.1b.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 'ftp://ftp.trolltech.com/qt/source/qt-everywhere-opensource-src-4.7.4.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
|
||||
|
||||
@@ -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"
|
||||
- "qt-win32-4.7.4-gitian-r1.zip"
|
||||
- "boost-win32-1.50.0-gitian2.zip"
|
||||
- "bitcoin-deps-0.0.4.zip"
|
||||
script: |
|
||||
#
|
||||
mkdir $HOME/qt
|
||||
cd $HOME/qt
|
||||
unzip ../build/qt-win32-4.7.4-gitian.zip
|
||||
unzip ../build/qt-win32-4.7.4-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
|
||||
@@ -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.1b OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1b/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1
|
||||
make $MAKEOPTS
|
||||
cp release/bitcoin-qt.exe $OUTDIR/
|
||||
#
|
||||
|
||||
@@ -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.7.4-gitian-r1.zip *
|
||||
|
||||
@@ -31,7 +31,7 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
71A3B16735405025D447E8F274810B012346C9A6:
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -31,7 +31,7 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
71A3B16735405025D447E8F274810B012346C9A6:
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.1 BETA
|
||||
Bitcoin 0.7.0 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.1 BETA
|
||||
Bitcoin 0.7.0 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
|
||||
|
||||
@@ -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,20 +28,16 @@ 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
|
||||
turned off by default. Set USE_UPNP to a different value to control this:
|
||||
USE_UPNP= No UPnP support - miniupnp not required
|
||||
USE_UPNP=- No UPnP support - miniupnp not required
|
||||
USE_UPNP=0 (the default) UPnP support turned off by default at runtime
|
||||
USE_UPNP=1 UPnP support turned on by default at runtime
|
||||
|
||||
libqrencode may be used for QRCode image generation. It can be downloaded
|
||||
from http://fukuchi.org/works/qrencode/index.html.en, or installed via
|
||||
your package manager. Set USE_QRCODE to control this:
|
||||
USE_QRCODE=0 (the default) No QRCode support - libarcode not required
|
||||
USE_QRCODE=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
|
||||
@@ -58,15 +54,27 @@ Versions used in this release:
|
||||
|
||||
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.nokia.com/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.nokia.com/downloads/sdk-windows-cpp
|
||||
.. _`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,7 +62,7 @@ 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
|
||||
.. _`MacPorts`: http://www.macports.org/install.php
|
||||
@@ -70,7 +71,7 @@ Mac OS X
|
||||
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:
|
||||
|
||||
117
doc/release-notes.txt
Normal file
117
doc/release-notes.txt
Normal file
@@ -0,0 +1,117 @@
|
||||
(note: this is a temporary file, to be added-to by anybody, and deleted at
|
||||
release time)
|
||||
|
||||
Building this from
|
||||
|
||||
$ git shortlog --no-merges v0.6.3..
|
||||
|
||||
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.
|
||||
|
||||
Incompatible Changes
|
||||
--------------------
|
||||
* Replaced the 'getmemorypool' RPC command with 'getblocktemplate/submitblock'
|
||||
and 'getrawmempool' commands.
|
||||
* Remove deprecated RPC 'getblocknumber'
|
||||
|
||||
Bitcoin Improvement Proposals implemented
|
||||
-----------------------------------------
|
||||
BIP 22 - 'getblocktemplate', 'submitblock' RPCs
|
||||
BIP 34 - block version 2, height in coinbase
|
||||
BIP 35 - 'mempool' message, extended 'getdata' message behavior
|
||||
|
||||
|
||||
Core bitcoin handling and blockchain database
|
||||
---------------------------------------------
|
||||
* Reduced CPU usage, by eliminating some redundant hash calculations
|
||||
* Cache signature verifications, to eliminate redundant signature checks
|
||||
* Transactions with zero-value outputs are considered non-standard
|
||||
* Mining: when creating new blocks, sort 'paid' area by fee-per-kb
|
||||
* Database: better validation of on-disk stored data
|
||||
* Database: minor optimizations and reliability improvements
|
||||
* -loadblock=FILE will import an external block file
|
||||
* Additional DoS (denial-of-service) prevention measures
|
||||
* New blockchain checkpoint at block 193,000
|
||||
* (Windows only): enable ASLR and DEP for bitcoind.exe
|
||||
|
||||
|
||||
JSON-RPC API
|
||||
------------
|
||||
* Internal HTTP server is now thread-per-connection, rather than
|
||||
a single-threaded queue that would stall on network I/O.
|
||||
* Internal HTTP server supports HTTP/1.1, pipelined requests and
|
||||
connection keep-alive.
|
||||
* Support JSON-RPC 2.0 batches, to encapsulate multiple JSON-RPC requests
|
||||
within a single HTTP request.
|
||||
* IPv6 support
|
||||
* Added raw transaction API. See https://gist.github.com/2839617
|
||||
* Added 'getrawmempool', to list contents of TX memory pool
|
||||
* Added 'getpeerinfo', to list data about each connected network peer
|
||||
* Added 'listaddressgroupings' for better coin control
|
||||
* Rework gettransaction, getblock calls. 'gettransaction' responds for
|
||||
non-wallet TXs now.
|
||||
* Remove deprecated RPC 'getblocknumber'
|
||||
* Remove superceded RPC 'getmemorypool' (see BIP 22, above)
|
||||
* listtransactions output now displays "smart" times for transactions,
|
||||
and 'blocktime' and 'timereceived' fields were added
|
||||
|
||||
|
||||
P2P networking
|
||||
--------------
|
||||
* IPv6 support
|
||||
* Tor hidden service support (see doc/Tor.txt)
|
||||
* Attempts to fix "stuck blockchain download" problems
|
||||
* Replace BDB database "addr.dat" with internally-managed "peers.dat"
|
||||
file containing peer address data.
|
||||
* Lower default send buffer from 10MB to 1MB
|
||||
* proxy: SOCKS5 by default
|
||||
* Support connecting by hostnames passed to proxy
|
||||
* Add -seednode connections, and use this instead of DNS seeds when proxied
|
||||
* Added -externalip and -discover
|
||||
* Add -onlynet to connect only to a given network (IPv4, IPv6, or Tor)
|
||||
* Separate listening sockets, -bind=<addr>
|
||||
|
||||
|
||||
Qt GUI
|
||||
------
|
||||
* Add UI RPC console / debug window
|
||||
* Re-Enable URI handling on Windows, add safety checks and tray-notifications
|
||||
* Harmonize the use of ellipsis ("...") to be used in menus, but not on buttons
|
||||
* Add 2 labels to the overviewpage that display Wallet and Transaction status (obsolete or current)
|
||||
* Extend the optionsdialog (e.g. language selection) and re-work it to a tabbed UI
|
||||
* Merge sign/verify message into a single window with tabbed UI
|
||||
* Ensure a changed bitcoin unit immediately updates all GUI elements that use units
|
||||
* Update QR Code dialog
|
||||
* Improve error reporting at startup
|
||||
* Fine-grained UI updates for a much smoother UI during block downloads
|
||||
* Remove autocorrection of 0/i in addresses in UI
|
||||
* Reorganize tray icon menu into more logical order
|
||||
* Persistently poll for balance change when number of blocks changed
|
||||
* Much better translations
|
||||
* Override progress bar design on platforms with segmented progress bars to assist with readability
|
||||
* Added 'immature balance' display on the overview page
|
||||
* (Windows only): enable ASLR and DEP for bitcoin-qt.exe
|
||||
* (Windows only): add meta-data to bitcoin-qt.exe (e.g. description and version)
|
||||
|
||||
Internal codebase
|
||||
-----------------
|
||||
* Additional unit tests
|
||||
* Compile warning fixes
|
||||
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
* Reopen debug.log upon SIGHUP
|
||||
* Bash programmable completion for bitcoind(1)
|
||||
* On supported OSes, each thread is given a useful name
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
* update (commit) version in sources
|
||||
bitcoin-qt.pro
|
||||
src/version.h
|
||||
src/clientversion.h
|
||||
share/setup.nsi
|
||||
doc/README*
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
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'
|
||||
@@ -29,15 +29,15 @@
|
||||
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://downloads.sourceforge.net/project/boost/boost/1.50.0/boost_1_50_0.tar.bz2'
|
||||
wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.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.7.4-gitian.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.3.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,11 +93,14 @@
|
||||
* 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
|
||||
|
||||
* update wiki download links
|
||||
|
||||
* update wiki changelog: https://en.bitcoin.it/wiki/Changelog
|
||||
|
||||
* Commit your signature to gitian.sigs:
|
||||
pushd gitian.sigs
|
||||
git add ${VERSION}/${SIGNER}
|
||||
|
||||
@@ -28,32 +28,55 @@ 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:
|
||||
|
||||
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 +86,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.1
|
||||
!define VERSION 0.7.0
|
||||
!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.1-win32-setup.exe
|
||||
OutFile bitcoin-0.7.0-win32-setup.exe
|
||||
InstallDir $PROGRAMFILES\Bitcoin
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
BrandingText " "
|
||||
ShowInstDetails show
|
||||
VIProductVersion 0.6.1.3
|
||||
VIProductVersion 0.7.0.3
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "addrman.h"
|
||||
|
||||
@@ -102,14 +102,19 @@ 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 < vRandom.size() && nRndPos2 < vRandom.size());
|
||||
|
||||
int nId1 = vRandom[nRndPos1];
|
||||
int nId2 = vRandom[nRndPos2];
|
||||
|
||||
assert(mapInfo.count(nId1) == 1);
|
||||
assert(mapInfo.count(nId2) == 1);
|
||||
|
||||
mapInfo[nId1].nRandomPos = nRndPos2;
|
||||
mapInfo[nId2].nRandomPos = nRndPos1;
|
||||
|
||||
@@ -124,26 +129,32 @@ int CAddrMan::SelectTried(int nKBucket)
|
||||
// random shuffle the first few elements (using the entire list)
|
||||
// find the least recently tried among them
|
||||
int64 nOldest = -1;
|
||||
int nOldestPos = -1;
|
||||
for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++)
|
||||
{
|
||||
int nPos = GetRandInt(vTried.size() - i) + i;
|
||||
int nTemp = vTried[nPos];
|
||||
vTried[nPos] = vTried[i];
|
||||
vTried[i] = nTemp;
|
||||
if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess)
|
||||
assert(nOldest == -1 || mapInfo.count(nTemp) == 1);
|
||||
if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) {
|
||||
nOldest = nTemp;
|
||||
nOldestPos = nPos;
|
||||
}
|
||||
}
|
||||
|
||||
return nOldest;
|
||||
return nOldestPos;
|
||||
}
|
||||
|
||||
int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// first look for deletable items
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
assert(mapInfo.count(*it));
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (info.IsTerrible())
|
||||
{
|
||||
@@ -168,11 +179,13 @@ int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
|
||||
{
|
||||
assert(nOldest == -1 || mapInfo.count(*it) == 1);
|
||||
if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
|
||||
nOldest = *it;
|
||||
}
|
||||
nI++;
|
||||
}
|
||||
assert(mapInfo.count(nOldest) == 1);
|
||||
CAddrInfo &info = mapInfo[nOldest];
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
@@ -189,6 +202,8 @@ int CAddrMan::ShrinkNew(int nUBucket)
|
||||
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
{
|
||||
assert(vvNew[nOrigin].count(nId) == 1);
|
||||
|
||||
// remove the entry from all new buckets
|
||||
for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
|
||||
{
|
||||
@@ -197,6 +212,8 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
}
|
||||
nNew--;
|
||||
|
||||
assert(info.nRefCount == 0);
|
||||
|
||||
// what tried bucket to move the entry to
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
@@ -214,6 +231,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
int nPos = SelectTried(nKBucket);
|
||||
|
||||
// find which new bucket it belongs to
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
@@ -385,13 +403,14 @@ CAddress CAddrMan::Select_(int nUnkBias)
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
if (vTried.size() == 0) continue;
|
||||
int nPos = GetRandInt(vTried.size());
|
||||
assert(mapInfo.count(vTried[nPos]) == 1);
|
||||
CAddrInfo &info = mapInfo[vTried[nPos]];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
} else {
|
||||
// use an new node
|
||||
// use a new node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
@@ -402,6 +421,7 @@ CAddress CAddrMan::Select_(int nUnkBias)
|
||||
std::set<int>::iterator it = vNew.begin();
|
||||
while (nPos--)
|
||||
it++;
|
||||
assert(mapInfo.count(*it) == 1);
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
@@ -481,6 +501,7 @@ void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr)
|
||||
{
|
||||
int nRndPos = GetRandInt(vRandom.size() - n) + n;
|
||||
SwapRandom(n, nRndPos);
|
||||
assert(mapInfo.count(vRandom[n]) == 1);
|
||||
vAddr.push_back(mapInfo[vRandom[n]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// Copyright (c) 2012 Pieter Wuille
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef _BITCOIN_ADDRMAN
|
||||
#define _BITCOIN_ADDRMAN 1
|
||||
|
||||
#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)
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
nRandomPos = -1;
|
||||
}
|
||||
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn)
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
168
src/allocators.h
168
src/allocators.h
@@ -1,12 +1,14 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_ALLOCATORS_H
|
||||
#define BITCOIN_ALLOCATORS_H
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -117,7 +252,6 @@ struct zero_after_free_allocator : public std::allocator<T>
|
||||
};
|
||||
|
||||
// This is exactly like std::string, but with a custom allocator.
|
||||
// (secure_allocator<> is defined in serialize.h)
|
||||
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
|
||||
|
||||
#endif
|
||||
|
||||
115
src/base58.h
115
src/base58.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
//
|
||||
@@ -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,15 +346,58 @@ 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
|
||||
{
|
||||
|
||||
22
src/bignum.h
22
src/bignum.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_BIGNUM_H
|
||||
#define BITCOIN_BIGNUM_H
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
@@ -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)
|
||||
|
||||
2680
src/bitcoinrpc.cpp
2680
src/bitcoinrpc.cpp
File diff suppressed because it is too large
Load Diff
105
src/bitcoinrpc.h
105
src/bitcoinrpc.h
@@ -1,21 +1,45 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef _BITCOINRPC_H_
|
||||
#define _BITCOINRPC_H_ 1
|
||||
|
||||
#include <string>
|
||||
#include <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"
|
||||
|
||||
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 +48,12 @@ public:
|
||||
std::string name;
|
||||
rpcfn_type actor;
|
||||
bool okSafeMode;
|
||||
bool unlocked;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitcoin RPC command dispatcher.
|
||||
*/
|
||||
class CRPCTable
|
||||
{
|
||||
private:
|
||||
@@ -34,8 +62,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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -25,37 +25,39 @@ namespace Checkpoints
|
||||
boost::assign::map_list_of
|
||||
( 11111, uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"))
|
||||
( 33333, uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6"))
|
||||
( 68555, uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a"))
|
||||
( 70567, uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a"))
|
||||
( 74000, uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20"))
|
||||
(105000, uint256("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97"))
|
||||
(118000, uint256("0x000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553"))
|
||||
(134444, uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"))
|
||||
(140700, uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd"))
|
||||
(168000, uint256("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763"))
|
||||
(193000, uint256("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317"))
|
||||
;
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_CHECKPOINT_H
|
||||
#define BITCOIN_CHECKPOINT_H
|
||||
|
||||
|
||||
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 0
|
||||
#define CLIENT_VERSION_BUILD 3
|
||||
|
||||
// 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
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef _BITCOIN_COMPAT_H
|
||||
#define _BITCOIN_COMPAT_H 1
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
544
src/db.cpp
544
src/db.cpp
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "db.h"
|
||||
#include "util.h"
|
||||
@@ -26,14 +26,9 @@ 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;
|
||||
@@ -47,24 +42,116 @@ static void EnvShutdown()
|
||||
{
|
||||
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
|
||||
}
|
||||
DbEnv(0).remove(GetDataDir().string().c_str(), 0);
|
||||
if (!fMockDb)
|
||||
DbEnv(0).remove(GetDataDir().string().c_str(), 0);
|
||||
}
|
||||
|
||||
class CDBInit
|
||||
CDBEnv::CDBEnv() : dbenv(0)
|
||||
{
|
||||
public:
|
||||
CDBInit()
|
||||
{
|
||||
}
|
||||
~CDBInit()
|
||||
{
|
||||
EnvShutdown();
|
||||
}
|
||||
}
|
||||
instance_of_cdbinit;
|
||||
|
||||
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;
|
||||
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(pathDataDir.string().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 %d opening database environment", 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;
|
||||
}
|
||||
|
||||
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)
|
||||
CDB::CDB(const char *pszFile, const char* pszMode) :
|
||||
pdb(NULL), activeTxn(NULL)
|
||||
{
|
||||
int ret;
|
||||
if (pszFile == NULL)
|
||||
@@ -77,50 +164,28 @@ 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_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
|
||||
@@ -130,10 +195,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL)
|
||||
{
|
||||
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));
|
||||
}
|
||||
@@ -146,40 +208,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);
|
||||
@@ -199,21 +267,20 @@ 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
|
||||
@@ -263,7 +330,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;
|
||||
@@ -271,10 +338,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;
|
||||
}
|
||||
@@ -289,11 +356,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;
|
||||
{
|
||||
@@ -310,9 +378,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++);
|
||||
@@ -320,13 +389,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,60 +448,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;
|
||||
ssKey >> strType >> hashItem >> pos;
|
||||
int nItemHeight;
|
||||
ssValue >> nItemHeight;
|
||||
|
||||
// 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);
|
||||
@@ -463,11 +479,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);
|
||||
@@ -510,62 +521,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
|
||||
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
|
||||
}
|
||||
}
|
||||
pcursor->close();
|
||||
|
||||
if (fRequestShutdown)
|
||||
return true;
|
||||
|
||||
@@ -596,7 +554,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);
|
||||
@@ -613,7 +573,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))
|
||||
@@ -715,7 +675,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);
|
||||
@@ -731,71 +691,171 @@ 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");
|
||||
|
||||
// de-serialize address data
|
||||
unsigned char pchMsgTmp[4];
|
||||
try {
|
||||
ssPeers >> FLATDATA(pchMsgTmp);
|
||||
ssPeers >> addr;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("CAddrman::Read() : I/O error or stream data corrupted");
|
||||
}
|
||||
|
||||
// finally, verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
|
||||
return error("CAddrman::Read() : invalid network magic number");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
130
src/db.h
130
src/db.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_DB_H
|
||||
#define BITCOIN_DB_H
|
||||
|
||||
@@ -25,21 +25,60 @@ 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;
|
||||
|
||||
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; };
|
||||
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);
|
||||
|
||||
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,14 +105,19 @@ 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;
|
||||
|
||||
// Unserialize value
|
||||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
|
||||
ssValue >> value;
|
||||
try {
|
||||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
|
||||
ssValue >> value;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear and free memory
|
||||
memset(datValue.get_data(), 0, datValue.get_size());
|
||||
@@ -102,7 +146,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());
|
||||
@@ -125,7 +169,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());
|
||||
@@ -145,7 +189,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());
|
||||
@@ -202,46 +246,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_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);
|
||||
}
|
||||
|
||||
@@ -279,37 +310,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
|
||||
|
||||
873
src/init.cpp
873
src/init.cpp
File diff suppressed because it is too large
Load Diff
10
src/init.h
10
src/init.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_INIT_H
|
||||
#define BITCOIN_INIT_H
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
void StartShutdown();
|
||||
void Shutdown(void* parg);
|
||||
bool AppInit(int argc, char* argv[]);
|
||||
bool AppInit2(int argc, char* argv[]);
|
||||
|
||||
bool GetStartOnSystemStartup();
|
||||
bool SetStartOnSystemStartup(bool fAutoStart);
|
||||
bool AppInit2();
|
||||
std::string HelpMessage();
|
||||
|
||||
#endif
|
||||
|
||||
49
src/irc.cpp
49
src/irc.cpp
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "irc.h"
|
||||
#include "net.h"
|
||||
@@ -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;
|
||||
@@ -192,6 +189,10 @@ 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 +202,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,10 +254,14 @@ 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
|
||||
// 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%u", GetRand(1000000000));
|
||||
|
||||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
|
||||
@@ -265,7 +275,7 @@ void ThreadIRCSeed2(void* parg)
|
||||
if (nRet == 2)
|
||||
{
|
||||
printf("IRC name already in use\n");
|
||||
fNameInUse = true;
|
||||
nNameRetry++;
|
||||
Wait(10);
|
||||
continue;
|
||||
}
|
||||
@@ -275,6 +285,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 +293,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);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_IRC_H
|
||||
#define BITCOIN_IRC_H
|
||||
|
||||
void ThreadIRCSeed(void* parg);
|
||||
|
||||
extern int nGotIRCAddresses;
|
||||
extern bool fGotExternalIP;
|
||||
|
||||
#endif
|
||||
|
||||
274
src/key.cpp
274
src/key.cpp
@@ -1,9 +1,13 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "key.h"
|
||||
|
||||
// Generate a private key from just the secret parameter
|
||||
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
@@ -44,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;
|
||||
@@ -115,3 +119,267 @@ err:
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CKey::SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
|
||||
void CKey::Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
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");
|
||||
fSet = false;
|
||||
}
|
||||
|
||||
CKey::CKey()
|
||||
{
|
||||
pkey = NULL;
|
||||
Reset();
|
||||
}
|
||||
|
||||
CKey::CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
|
||||
CKey& CKey::operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
CKey::~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
|
||||
bool CKey::IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
|
||||
bool CKey::IsCompressed() const
|
||||
{
|
||||
return fCompressedPubKey;
|
||||
}
|
||||
|
||||
void CKey::MakeNewKey(bool fCompressed)
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
if (fCompressed)
|
||||
SetCompressedPubKey();
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||
if (vchSecret.size() != 32)
|
||||
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
}
|
||||
BN_clear_free(bn);
|
||||
fSet = true;
|
||||
if (fCompressed || fCompressedPubKey)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret CKey::GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
int nBytes = BN_num_bytes(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
CPrivKey CKey::GetPrivKey() const
|
||||
{
|
||||
int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool CKey::SetPubKey(const CPubKey& vchPubKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPubKey.vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CPubKey CKey::GetPubKey() const
|
||||
{
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return CPubKey(vchPubKey);
|
||||
}
|
||||
|
||||
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
unsigned int nSize = ECDSA_size(pkey);
|
||||
vchSig.resize(nSize); // Make sure it is big enough
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
|
||||
{
|
||||
vchSig.clear();
|
||||
return false;
|
||||
}
|
||||
vchSig.resize(nSize); // Shrink to fit actual size
|
||||
return true;
|
||||
}
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
|
||||
if (sig==NULL)
|
||||
return false;
|
||||
vchSig.clear();
|
||||
vchSig.resize(65,0);
|
||||
int nBitsR = BN_num_bits(sig->r);
|
||||
int nBitsS = BN_num_bits(sig->s);
|
||||
if (nBitsR <= 256 && nBitsS <= 256)
|
||||
{
|
||||
int nRecId = -1;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
CKey keyRec;
|
||||
keyRec.fSet = true;
|
||||
if (fCompressedPubKey)
|
||||
keyRec.SetCompressedPubKey();
|
||||
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
|
||||
if (keyRec.GetPubKey() == this->GetPubKey())
|
||||
{
|
||||
nRecId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
|
||||
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
|
||||
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
|
||||
fOk = true;
|
||||
}
|
||||
ECDSA_SIG_free(sig);
|
||||
return fOk;
|
||||
}
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
BN_bin2bn(&vchSig[33],32,sig->s);
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (nV >= 31)
|
||||
{
|
||||
SetCompressedPubKey();
|
||||
nV -= 4;
|
||||
}
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
|
||||
{
|
||||
fSet = true;
|
||||
ECDSA_SIG_free(sig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetCompactSignature(hash, vchSig))
|
||||
return false;
|
||||
if (GetPubKey() != key.GetPubKey())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKey::IsValid()
|
||||
{
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
|
||||
326
src/key.h
326
src/key.h
@@ -1,19 +1,19 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEY_H
|
||||
#define BITCOIN_KEY_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "allocators.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_KEY definition
|
||||
|
||||
// secp160k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 192;
|
||||
@@ -38,15 +38,66 @@
|
||||
// see www.keylength.com
|
||||
// script supports up to 75 for single byte push
|
||||
|
||||
int extern EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key);
|
||||
int extern ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check);
|
||||
|
||||
class key_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
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) { }
|
||||
};
|
||||
|
||||
/** 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 serialize.h
|
||||
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
|
||||
@@ -62,267 +113,50 @@ protected:
|
||||
bool fSet;
|
||||
bool fCompressedPubKey;
|
||||
|
||||
void SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
void SetCompressedPubKey();
|
||||
|
||||
public:
|
||||
|
||||
void Reset()
|
||||
{
|
||||
fCompressedPubKey = false;
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
|
||||
fSet = false;
|
||||
}
|
||||
void Reset();
|
||||
|
||||
CKey()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
CKey();
|
||||
CKey(const CKey& b);
|
||||
|
||||
CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
|
||||
fSet = b.fSet;
|
||||
}
|
||||
CKey& operator=(const CKey& b);
|
||||
|
||||
CKey& operator=(const CKey& b)
|
||||
{
|
||||
if (!EC_KEY_copy(pkey, b.pkey))
|
||||
throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
|
||||
fSet = b.fSet;
|
||||
return (*this);
|
||||
}
|
||||
~CKey();
|
||||
|
||||
~CKey()
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
}
|
||||
bool IsNull() const;
|
||||
bool IsCompressed() const;
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return !fSet;
|
||||
}
|
||||
void MakeNewKey(bool fCompressed);
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey);
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false);
|
||||
CSecret GetSecret(bool &fCompressed) const;
|
||||
CPrivKey GetPrivKey() const;
|
||||
bool SetPubKey(const CPubKey& vchPubKey);
|
||||
CPubKey GetPubKey() const;
|
||||
|
||||
bool IsCompressed() const
|
||||
{
|
||||
return fCompressedPubKey;
|
||||
}
|
||||
|
||||
void MakeNewKey(bool fCompressed)
|
||||
{
|
||||
if (!EC_KEY_generate_key(pkey))
|
||||
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
|
||||
if (fCompressed)
|
||||
SetCompressedPubKey();
|
||||
fSet = true;
|
||||
}
|
||||
|
||||
bool SetPrivKey(const CPrivKey& vchPrivKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (pkey == NULL)
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
|
||||
if (vchSecret.size() != 32)
|
||||
throw key_error("CKey::SetSecret() : secret must be 32 bytes");
|
||||
BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::SetSecret() : BN_bin2bn failed");
|
||||
if (!EC_KEY_regenerate_key(pkey,bn))
|
||||
{
|
||||
BN_clear_free(bn);
|
||||
throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
|
||||
}
|
||||
BN_clear_free(bn);
|
||||
fSet = true;
|
||||
if (fCompressed || fCompressedPubKey)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
CSecret GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
|
||||
int nBytes = BN_num_bytes(bn);
|
||||
if (bn == NULL)
|
||||
throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
CPrivKey GetPrivKey() const
|
||||
{
|
||||
int nSize = i2d_ECPrivateKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
|
||||
CPrivKey vchPrivKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPrivKey[0];
|
||||
if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
|
||||
return vchPrivKey;
|
||||
}
|
||||
|
||||
bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
const unsigned char* pbegin = &vchPubKey[0];
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> GetPubKey() const
|
||||
{
|
||||
int nSize = i2o_ECPublicKey(pkey, NULL);
|
||||
if (!nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
|
||||
std::vector<unsigned char> vchPubKey(nSize, 0);
|
||||
unsigned char* pbegin = &vchPubKey[0];
|
||||
if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
|
||||
throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
|
||||
return vchPubKey;
|
||||
}
|
||||
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
unsigned int nSize = ECDSA_size(pkey);
|
||||
vchSig.resize(nSize); // Make sure it is big enough
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
|
||||
{
|
||||
vchSig.clear();
|
||||
return false;
|
||||
}
|
||||
vchSig.resize(nSize); // Shrink to fit actual size
|
||||
return true;
|
||||
}
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// create a compact signature (65 bytes), which allows reconstructing the used public key
|
||||
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
|
||||
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
|
||||
// 0x1D = second key with even y, 0x1E = second key with odd y
|
||||
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
|
||||
if (sig==NULL)
|
||||
return false;
|
||||
vchSig.clear();
|
||||
vchSig.resize(65,0);
|
||||
int nBitsR = BN_num_bits(sig->r);
|
||||
int nBitsS = BN_num_bits(sig->s);
|
||||
if (nBitsR <= 256 && nBitsS <= 256)
|
||||
{
|
||||
int nRecId = -1;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
CKey keyRec;
|
||||
keyRec.fSet = true;
|
||||
if (fCompressedPubKey)
|
||||
keyRec.SetCompressedPubKey();
|
||||
if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
|
||||
if (keyRec.GetPubKey() == this->GetPubKey())
|
||||
{
|
||||
nRecId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
|
||||
BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
|
||||
BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
|
||||
fOk = true;
|
||||
}
|
||||
ECDSA_SIG_free(sig);
|
||||
return fOk;
|
||||
}
|
||||
bool SignCompact(uint256 hash, std::vector<unsigned char>& vchSig);
|
||||
|
||||
// reconstruct public key from a compact signature
|
||||
// This is only slightly more CPU intensive than just verifying it.
|
||||
// If this function succeeds, the recovered public key is guaranteed to be valid
|
||||
// (the signature is a valid signature of the given data for that key)
|
||||
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
if (vchSig.size() != 65)
|
||||
return false;
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
BN_bin2bn(&vchSig[33],32,sig->s);
|
||||
bool SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (nV >= 31)
|
||||
{
|
||||
SetCompressedPubKey();
|
||||
nV -= 4;
|
||||
}
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1)
|
||||
{
|
||||
fSet = true;
|
||||
ECDSA_SIG_free(sig);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
// -1 = error, 0 = bad sig, 1 = good
|
||||
if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool Verify(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
// Verify a compact signature
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetCompactSignature(hash, vchSig))
|
||||
return false;
|
||||
if (GetPubKey() != key.GetPubKey())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig);
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
bool IsValid();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "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;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEYSTORE_H
|
||||
#define BITCOIN_KEYSTORE_H
|
||||
|
||||
#include "crypter.h"
|
||||
#include "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
|
||||
|
||||
908
src/main.cpp
908
src/main.cpp
File diff suppressed because it is too large
Load Diff
295
src/main.h
295
src/main.h
@@ -1,18 +1,15 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_MAIN_H
|
||||
#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)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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;
|
||||
@@ -551,7 +554,7 @@ public:
|
||||
if (nBlockSize == 1)
|
||||
{
|
||||
// Transactions under 10K are free
|
||||
// (about 4500bc if made of 50bc inputs)
|
||||
// (about 4500 BTC if made of 50 BTC inputs)
|
||||
if (nBytes < 10000)
|
||||
nMinFee = 0;
|
||||
}
|
||||
@@ -594,7 +597,13 @@ public:
|
||||
// Read transaction
|
||||
if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
|
||||
return error("CTransaction::ReadFromDisk() : fseek failed");
|
||||
filein >> *this;
|
||||
|
||||
try {
|
||||
filein >> *this;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Return file pointer
|
||||
if (pfileRet)
|
||||
@@ -811,6 +820,7 @@ class CBlock
|
||||
{
|
||||
public:
|
||||
// header
|
||||
static const int CURRENT_VERSION=2;
|
||||
int nVersion;
|
||||
uint256 hashPrevBlock;
|
||||
uint256 hashMerkleRoot;
|
||||
@@ -852,7 +862,7 @@ public:
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nVersion = CBlock::CURRENT_VERSION;
|
||||
hashPrevBlock = 0;
|
||||
hashMerkleRoot = 0;
|
||||
nTime = 0;
|
||||
@@ -953,13 +963,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;
|
||||
}
|
||||
@@ -976,7 +980,12 @@ public:
|
||||
filein.nType |= SER_BLOCKHEADERONLY;
|
||||
|
||||
// Read block
|
||||
filein >> *this;
|
||||
try {
|
||||
filein >> *this;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// Check the header
|
||||
if (!CheckProofOfWork(GetHash(), nBits))
|
||||
@@ -1009,11 +1018,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:
|
||||
@@ -1127,21 +1136,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
|
||||
@@ -1170,11 +1164,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=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d 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());
|
||||
@@ -1397,207 +1397,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:
|
||||
@@ -1607,8 +1406,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,20 +1,22 @@
|
||||
# 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"$(CURDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
-I"$(DEPSDIR)/boost_1_50_0" \
|
||||
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-I"$(DEPSDIR)/openssl-1.0.1b/include" \
|
||||
-I"$(DEPSDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
-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"
|
||||
|
||||
@@ -23,28 +25,38 @@ LIBS= \
|
||||
-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
|
||||
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 \
|
||||
@@ -69,7 +87,7 @@ OBJS= \
|
||||
all: bitcoind.exe
|
||||
|
||||
obj/build.h: FORCE
|
||||
../share/genbuild.sh obj/build.h
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.0d-mgw\include"
|
||||
-I"C:\openssl-1.0.1b-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.0d-mgw"
|
||||
-L"C:\openssl-1.0.1b-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
|
||||
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 \
|
||||
@@ -70,7 +87,7 @@ 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,7 +95,7 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -53,7 +54,7 @@ LIBS += \
|
||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||
endif
|
||||
|
||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0
|
||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE
|
||||
|
||||
ifdef RELEASE
|
||||
# Compile for maximum compatibility and smallest size.
|
||||
@@ -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,6 +110,10 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
all: bitcoind
|
||||
|
||||
# auto-generated dependencies:
|
||||
@@ -106,12 +121,12 @@ all: bitcoind
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/build.h: FORCE
|
||||
../share/genbuild.sh obj/build.h
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
|
||||
$(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 +138,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); \
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
# 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
|
||||
|
||||
DEFS=
|
||||
LINK:=$(CXX)
|
||||
|
||||
DEFS=-DBOOST_SPIRIT_THREADSAFE
|
||||
|
||||
DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||
@@ -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 \
|
||||
@@ -116,31 +137,31 @@ all: bitcoind
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/build.h: FORCE
|
||||
../share/genbuild.sh obj/build.h
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
|
||||
$(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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_MRUSET_H
|
||||
#define BITCOIN_MRUSET_H
|
||||
|
||||
@@ -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();
|
||||
|
||||
754
src/net.cpp
754
src/net.cpp
File diff suppressed because it is too large
Load Diff
90
src/net.h
90
src/net.h
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NET_H
|
||||
#define BITCOIN_NET_H
|
||||
|
||||
@@ -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,18 +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;
|
||||
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;
|
||||
@@ -157,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;
|
||||
@@ -168,8 +218,10 @@ public:
|
||||
nHeaderStart = -1;
|
||||
nMessageStart = -1;
|
||||
addr = addrIn;
|
||||
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
|
||||
nVersion = 0;
|
||||
strSubVer = "";
|
||||
fOneShot = false;
|
||||
fClient = false; // set by version message
|
||||
fInbound = fInboundIn;
|
||||
fNetworkNode = false;
|
||||
@@ -263,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;
|
||||
@@ -287,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()
|
||||
@@ -320,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);
|
||||
@@ -584,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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
645
src/netbase.cpp
645
src/netbase.cpp
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
@@ -11,20 +11,61 @@
|
||||
#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);
|
||||
typedef std::pair<CService, int> proxyType;
|
||||
static proxyType proxyInfo[NET_MAX];
|
||||
static proxyType nameproxyInfo;
|
||||
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 +74,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 +142,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 +170,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 +340,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 +352,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 +422,107 @@ 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;
|
||||
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetProxy(enum Network net, CService &addrProxy) {
|
||||
assert(net >= 0 && net < NET_MAX);
|
||||
if (!proxyInfo[net].second)
|
||||
return false;
|
||||
addrProxy = proxyInfo[net].first;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion) {
|
||||
if (nSocksVersion != 0 && nSocksVersion != 5)
|
||||
return false;
|
||||
if (nSocksVersion != 0 && !addrProxy.IsValid())
|
||||
return false;
|
||||
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNameProxy() {
|
||||
return nameproxyInfo.second != 0;
|
||||
}
|
||||
|
||||
bool IsProxy(const CNetAddr &addr) {
|
||||
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)
|
||||
{
|
||||
const proxyType &proxy = proxyInfo[addrDest.GetNetwork()];
|
||||
|
||||
// no proxy needed
|
||||
if (!proxy.second)
|
||||
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;
|
||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
|
||||
if (addrResolved.IsValid()) {
|
||||
addr = addrResolved;
|
||||
return ConnectSocket(addr, hSocketRet, nTimeout);
|
||||
}
|
||||
addr = CService("0.0.0.0:0");
|
||||
if (!nameproxyInfo.second)
|
||||
return false;
|
||||
if (!ConnectSocketDirectly(nameproxyInfo.first, hSocket, nTimeout))
|
||||
return false;
|
||||
|
||||
switch(nameproxyInfo.second)
|
||||
{
|
||||
default:
|
||||
case 4: return false;
|
||||
case 5:
|
||||
if (!Socks5(strDest, port, hSocket))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
@@ -305,6 +539,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();
|
||||
@@ -349,6 +609,11 @@ 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() && (
|
||||
@@ -405,6 +670,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 +702,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 +738,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 +827,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 +897,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 +910,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 +1024,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 +1092,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 +1135,16 @@ std::vector<unsigned char> CService::GetKey() const
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf(":%i", port);
|
||||
return strprintf("%i", 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NETBASE_H
|
||||
#define BITCOIN_NETBASE_H
|
||||
|
||||
@@ -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;
|
||||
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,19 @@ class CService : public CNetAddr
|
||||
)
|
||||
};
|
||||
|
||||
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, CService &addrProxy);
|
||||
bool IsProxy(const CNetAddr &addr);
|
||||
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
|
||||
bool GetNameProxy();
|
||||
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
|
||||
|
||||
34
src/noui.cpp
34
src/noui.cpp
@@ -1,44 +1,28 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This header can only be compiled as C++.
|
||||
@@ -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,6 +21,7 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddressBookPage),
|
||||
model(0),
|
||||
optionsModel(0),
|
||||
mode(mode),
|
||||
tab(tab)
|
||||
{
|
||||
@@ -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,14 +140,18 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(selectionChanged()));
|
||||
|
||||
if(mode == ForSending)
|
||||
{
|
||||
// Auto-select first row when in sending mode
|
||||
ui->tableView->selectRow(0);
|
||||
}
|
||||
// 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);
|
||||
@@ -171,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()
|
||||
@@ -184,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,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
|
||||
@@ -239,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);
|
||||
@@ -250,6 +278,7 @@ void AddressBookPage::selectionChanged()
|
||||
ui->showQRCode->setEnabled(false);
|
||||
ui->copyToClipboard->setEnabled(false);
|
||||
ui->signMessage->setEnabled(false);
|
||||
ui->verifyMessage->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,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
|
||||
@@ -328,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)
|
||||
@@ -158,7 +157,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 +177,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 +204,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();
|
||||
}
|
||||
@@ -215,7 +214,7 @@ bool AskPassphraseDialog::event(QEvent *event)
|
||||
|
||||
bool AskPassphraseDialog::eventFilter(QObject *, 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,7 +228,7 @@ 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();
|
||||
|
||||
@@ -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,6 +123,9 @@ 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);
|
||||
|
||||
@@ -187,32 +149,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 +207,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 +225,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,35 +240,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 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'
|
||||
@@ -21,21 +21,31 @@ BitcoinAddressValidator::BitcoinAddressValidator(QObject *parent) :
|
||||
QValidator::State BitcoinAddressValidator::validate(QString &input, int &pos) const
|
||||
{
|
||||
// Correction
|
||||
for(int idx=0; idx<input.size(); ++idx)
|
||||
for(int idx=0; idx<input.size();)
|
||||
{
|
||||
switch(input.at(idx).unicode())
|
||||
bool removeChar = false;
|
||||
QChar ch = input.at(idx);
|
||||
// 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');
|
||||
// Qt categorizes these as "Other_Format" not "Separator_Space"
|
||||
case 0x200B: // ZERO WIDTH SPACE
|
||||
case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
|
||||
removeChar = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Remove whitespace
|
||||
if(ch.isSpace())
|
||||
removeChar = true;
|
||||
// To next character
|
||||
if(removeChar)
|
||||
input.remove(idx, 1);
|
||||
else
|
||||
++idx;
|
||||
}
|
||||
|
||||
// Validation
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 20011-2012
|
||||
* The Bitcoin Developers 20011-2012
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2012
|
||||
*/
|
||||
#include "bitcoingui.h"
|
||||
#include "transactiontablemodel.h"
|
||||
#include "addressbookpage.h"
|
||||
#include "sendcoinsdialog.h"
|
||||
#include "messagepage.h"
|
||||
#include "signverifymessagedialog.h"
|
||||
#include "optionsdialog.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "clientmodel.h"
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "askpassphrasedialog.h"
|
||||
#include "notificator.h"
|
||||
#include "guiutil.h"
|
||||
#include "rpcconsole.h"
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#include "macdockiconhandler.h"
|
||||
@@ -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"));
|
||||
setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
|
||||
#ifndef Q_WS_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);
|
||||
@@ -113,7 +116,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
centralWidget->addWidget(receiveCoinsPage);
|
||||
centralWidget->addWidget(sendCoinsPage);
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
centralWidget->addWidget(messagePage);
|
||||
centralWidget->addWidget(signVerifyMessageDialog);
|
||||
#endif
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
@@ -146,6 +149,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,10 +166,19 @@ 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();
|
||||
}
|
||||
|
||||
@@ -199,17 +220,25 @@ void BitcoinGUI::createActions()
|
||||
tabGroup->addAction(receiveCoinsAction);
|
||||
|
||||
sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
|
||||
sendCoinsAction->setToolTip(tr("Send coins to a bitcoin address"));
|
||||
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"));
|
||||
signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
|
||||
signMessageAction->setToolTip(tr("Sign a message to prove you own a Bitcoin address"));
|
||||
tabGroup->addAction(signMessageAction);
|
||||
|
||||
verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
|
||||
verifyMessageAction->setToolTip(tr("Verify a message to ensure it was signed with a specified Bitcoin address"));
|
||||
tabGroup->addAction(verifyMessageAction);
|
||||
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
messageAction->setCheckable(true);
|
||||
firstClassMessagingAction = new QAction(QIcon(":/icons/edit"), tr("S&ignatures"), this);
|
||||
firstClassMessagingAction->setToolTip(signMessageAction->toolTip() + QString(". / ") + verifyMessageAction->toolTip() + QString("."));
|
||||
firstClassMessagingAction->setCheckable(true);
|
||||
tabGroup->addAction(firstClassMessagingAction);
|
||||
#endif
|
||||
tabGroup->addAction(messageAction);
|
||||
|
||||
connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
|
||||
@@ -221,33 +250,41 @@ void BitcoinGUI::createActions()
|
||||
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()));
|
||||
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
|
||||
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
connect(firstClassMessagingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
// Always start with the sign message tab for FIRST_CLASS_MESSAGING
|
||||
connect(firstClassMessagingAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
|
||||
#endif
|
||||
|
||||
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"));
|
||||
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
|
||||
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);
|
||||
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"));
|
||||
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()));
|
||||
@@ -274,7 +311,8 @@ void BitcoinGUI::createMenuBar()
|
||||
file->addAction(backupWalletAction);
|
||||
file->addAction(exportAction);
|
||||
#ifndef FIRST_CLASS_MESSAGING
|
||||
file->addAction(messageAction);
|
||||
file->addAction(signMessageAction);
|
||||
file->addAction(verifyMessageAction);
|
||||
#endif
|
||||
file->addSeparator();
|
||||
file->addAction(quitAction);
|
||||
@@ -286,6 +324,8 @@ void BitcoinGUI::createMenuBar()
|
||||
settings->addAction(optionsAction);
|
||||
|
||||
QMenu *help = appMenuBar->addMenu(tr("&Help"));
|
||||
help->addAction(openRPCConsoleAction);
|
||||
help->addSeparator();
|
||||
help->addAction(aboutAction);
|
||||
help->addAction(aboutQtAction);
|
||||
}
|
||||
@@ -300,7 +340,7 @@ void BitcoinGUI::createToolBars()
|
||||
toolbar->addAction(historyAction);
|
||||
toolbar->addAction(addressBookAction);
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
toolbar->addAction(messageAction);
|
||||
toolbar->addAction(firstClassMessagingAction);
|
||||
#endif
|
||||
|
||||
QToolBar *toolbar2 = addToolBar(tr("Actions toolbar"));
|
||||
@@ -313,31 +353,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);
|
||||
setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]"));
|
||||
#ifndef Q_WS_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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,12 +404,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)));
|
||||
|
||||
@@ -385,27 +433,28 @@ void BitcoinGUI::createTrayIcon()
|
||||
#else
|
||||
// Note: On Mac, the dock icon is used to provide the tray's functionality.
|
||||
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
|
||||
connect(dockIconHandler, SIGNAL(dockIconClicked()), toggleHideAction, SLOT(trigger()));
|
||||
trayIconMenu = dockIconHandler->dockMenu();
|
||||
#endif
|
||||
|
||||
// Configuration of the tray icon (or dock icon) icon menu
|
||||
trayIconMenu->addAction(toggleHideAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(messageAction);
|
||||
trayIconMenu->addAction(sendCoinsAction);
|
||||
trayIconMenu->addAction(receiveCoinsAction);
|
||||
#ifndef FIRST_CLASS_MESSAGING
|
||||
trayIconMenu->addSeparator();
|
||||
#endif
|
||||
trayIconMenu->addAction(receiveCoinsAction);
|
||||
trayIconMenu->addAction(sendCoinsAction);
|
||||
trayIconMenu->addAction(signMessageAction);
|
||||
trayIconMenu->addAction(verifyMessageAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(optionsAction);
|
||||
trayIconMenu->addAction(openRPCConsoleAction);
|
||||
#ifndef Q_WS_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
|
||||
@@ -413,34 +462,12 @@ 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())
|
||||
@@ -472,9 +499,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 progressBar and its label if we have no connection(s) to the network
|
||||
if (!clientModel || clientModel->getNumConnections() == 0)
|
||||
{
|
||||
progressBarLabel->setVisible(false);
|
||||
@@ -483,7 +510,7 @@ void BitcoinGUI::setNumBlocks(int count)
|
||||
return;
|
||||
}
|
||||
|
||||
int nTotalBlocks = clientModel->getNumBlocksOfPeers();
|
||||
QString strStatusBarWarnings = clientModel->getStatusBarWarnings();
|
||||
QString tooltip;
|
||||
|
||||
if(count < nTotalBlocks)
|
||||
@@ -491,7 +518,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);
|
||||
@@ -500,30 +527,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 progressBar, 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
|
||||
@@ -551,22 +576,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);
|
||||
@@ -625,7 +657,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);
|
||||
}
|
||||
@@ -713,24 +745,42 @@ 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);
|
||||
firstClassMessagingAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(signVerifyMessageDialog);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
|
||||
signVerifyMessageDialog->showTab_SM(false);
|
||||
#else
|
||||
messagePage->show();
|
||||
messagePage->setFocus();
|
||||
// call show() in showTab_SM()
|
||||
signVerifyMessageDialog->showTab_SM(true);
|
||||
#endif
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_SM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoMessagePage(QString addr)
|
||||
void BitcoinGUI::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
gotoMessagePage();
|
||||
messagePage->setAddress(addr);
|
||||
#ifdef FIRST_CLASS_MESSAGING
|
||||
firstClassMessagingAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(signVerifyMessageDialog);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
|
||||
signVerifyMessageDialog->showTab_VM(false);
|
||||
#else
|
||||
// call show() in showTab_VM()
|
||||
signVerifyMessageDialog->showTab_VM(true);
|
||||
#endif
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_VM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
|
||||
@@ -744,12 +794,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();
|
||||
@@ -757,13 +814,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)
|
||||
@@ -838,10 +896,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,9 @@ private:
|
||||
QAction *quitAction;
|
||||
QAction *sendCoinsAction;
|
||||
QAction *addressBookAction;
|
||||
QAction *messageAction;
|
||||
QAction *signMessageAction;
|
||||
QAction *verifyMessageAction;
|
||||
QAction *firstClassMessagingAction;
|
||||
QAction *aboutAction;
|
||||
QAction *receiveCoinsAction;
|
||||
QAction *optionsAction;
|
||||
@@ -87,16 +90,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 +112,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
|
||||
@@ -127,9 +132,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,6 +144,11 @@ 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 */
|
||||
@@ -161,12 +168,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,143 @@ 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", ""
|
||||
"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: 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", ""
|
||||
"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", ""
|
||||
"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", "An error occurred while setting up the RPC port %i for listening: %s"),
|
||||
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 blocks..."),
|
||||
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 JSON-RPC connections on <port> (default: 8332)"),
|
||||
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", "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!"),
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -27,8 +27,9 @@ void CSVModelWriter::addColumn(const QString &title, int column, int role)
|
||||
|
||||
static void writeValue(QTextStream &f, const QString &value)
|
||||
{
|
||||
// TODO: quoting if " or \n in string
|
||||
f << "\"" << value << "\"";
|
||||
QString escaped = value;
|
||||
escaped.replace('"', "\"\"");
|
||||
f << "\"" << escaped << "\"";
|
||||
}
|
||||
|
||||
static void writeSep(QTextStream &f)
|
||||
|
||||
@@ -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,14 +92,14 @@
|
||||
</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>
|
||||
@@ -104,6 +110,20 @@
|
||||
</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">
|
||||
|
||||
@@ -23,14 +23,11 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Passphrase Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="warningLabel">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
@@ -44,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>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user