mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
Compare commits
488 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1c3d8f14d | ||
|
|
f146061d24 | ||
|
|
dac1888c18 | ||
|
|
25c5eca893 | ||
|
|
f3f9da868e | ||
|
|
6293a9f87f | ||
|
|
83e914c1d5 | ||
|
|
94b5960ef3 | ||
|
|
9f18347034 | ||
|
|
7b2eecd428 | ||
|
|
8d29329f93 | ||
|
|
0ccb2c4f66 | ||
|
|
84560c41c7 | ||
|
|
dd675e01c4 | ||
|
|
be4502968e | ||
|
|
c698633447 | ||
|
|
c289d95d6b | ||
|
|
57de7cd603 | ||
|
|
bf5b80a8ae | ||
|
|
53cb1a49e7 | ||
|
|
a56881b005 | ||
|
|
e9f9282bde | ||
|
|
7b90edb5a6 | ||
|
|
6b8de05d0a | ||
|
|
4004b9a40b | ||
|
|
01a196e08d | ||
|
|
59e659fcc0 | ||
|
|
6eb339fae4 | ||
|
|
b3dbab33ca | ||
|
|
0ec76d834e | ||
|
|
bf1afb02ca | ||
|
|
a6aee96c7e | ||
|
|
439e1497e1 | ||
|
|
4a17e3e6b9 | ||
|
|
49e1501b5d | ||
|
|
958fe01c32 | ||
|
|
e12d131734 | ||
|
|
a6b4a11385 | ||
|
|
0e894be626 | ||
|
|
e53f03172a | ||
|
|
5cd806a03e | ||
|
|
ef12c2184d | ||
|
|
4538e45c46 | ||
|
|
100da73677 | ||
|
|
8f188ece3c | ||
|
|
4a43dfbf3e | ||
|
|
2e2c04e250 | ||
|
|
b2fe3a5ca6 | ||
|
|
3979a2ee6c | ||
|
|
2fac1028a8 | ||
|
|
c2b1ab072c | ||
|
|
a1a0469f91 | ||
|
|
6565f4e855 | ||
|
|
246c20e8a9 | ||
|
|
4046bdf18a | ||
|
|
0aa89c08ff | ||
|
|
89516bd4e0 | ||
|
|
7868808b2f | ||
|
|
ef14236539 | ||
|
|
eae82d8ee5 | ||
|
|
3f1bb1ac78 | ||
|
|
9aa459b294 | ||
|
|
d6b08f6f2c | ||
|
|
603061a7e5 | ||
|
|
4ac3eea027 | ||
|
|
8afd4699e6 | ||
|
|
7c4fabde60 | ||
|
|
bd9c6f88be | ||
|
|
0b99d1b574 | ||
|
|
aa3d4c0221 | ||
|
|
bb13d056ea | ||
|
|
840f69c582 | ||
|
|
652856fb63 | ||
|
|
44b69cf25e | ||
|
|
fa689db37b | ||
|
|
8864019f6d | ||
|
|
98ff031eb8 | ||
|
|
6c757e99f3 | ||
|
|
8e910c89b8 | ||
|
|
08ed96d856 | ||
|
|
f94177367a | ||
|
|
30dfc64f48 | ||
|
|
e318b99d99 | ||
|
|
89cccc83f8 | ||
|
|
d68dcf741e | ||
|
|
3cc0624932 | ||
|
|
336ba312a6 | ||
|
|
21e875c958 | ||
|
|
82a10c8170 | ||
|
|
4585d828b4 | ||
|
|
f8c478c4fb | ||
|
|
f2e81bad33 | ||
|
|
a206b0ea12 | ||
|
|
50abb5516d | ||
|
|
038fedccab | ||
|
|
95486d5c48 | ||
|
|
142e604184 | ||
|
|
722d9387be | ||
|
|
6dd5ae41ac | ||
|
|
d8a80af84a | ||
|
|
27adfb2e0c | ||
|
|
07ed49a472 | ||
|
|
21503e4556 | ||
|
|
c4341fa6ab | ||
|
|
46aa2a6bdd | ||
|
|
90d78142c0 | ||
|
|
fbbd42a535 | ||
|
|
42c8b56f62 | ||
|
|
3f8cb2c565 | ||
|
|
972060ce0e | ||
|
|
21ae37d215 | ||
|
|
3d2b5c53cb | ||
|
|
88c41c43ea | ||
|
|
4a10d4c6dc | ||
|
|
da9ab62fb7 | ||
|
|
71ba9abba6 | ||
|
|
db9f2e0117 | ||
|
|
1168d30b0a | ||
|
|
ec4efde40c | ||
|
|
5fee401fe1 | ||
|
|
8c12851ed4 | ||
|
|
fc4f4c2e9a | ||
|
|
35b327a520 | ||
|
|
3d0a0a9b9e | ||
|
|
34f8788915 | ||
|
|
5c03282521 | ||
|
|
6fe8c45375 | ||
|
|
e7e6ae2104 | ||
|
|
8c7358e1dd | ||
|
|
e1bad25fee | ||
|
|
de737806b5 | ||
|
|
1af97c95f3 | ||
|
|
f246fc648a | ||
|
|
c170d03e03 | ||
|
|
92d5864b80 | ||
|
|
18c0fa97d0 | ||
|
|
73aa0421a7 | ||
|
|
0d56f11ada | ||
|
|
f7b8f824de | ||
|
|
7b88a61706 | ||
|
|
f50f36d4db | ||
|
|
5a5cc6ac09 | ||
|
|
9fa042a96c | ||
|
|
3a4d81724e | ||
|
|
49355d9993 | ||
|
|
8a949dd6c3 | ||
|
|
ceaa13eff2 | ||
|
|
46245b4782 | ||
|
|
a3342d096f | ||
|
|
a09f101f14 | ||
|
|
e0b8d459b1 | ||
|
|
59b1b181e9 | ||
|
|
27a0ed8a0a | ||
|
|
fcfd7ff8f8 | ||
|
|
38067c18f8 | ||
|
|
9976cf070f | ||
|
|
0b807a417f | ||
|
|
e9a041c536 | ||
|
|
a06113b0c5 | ||
|
|
2d36b60f92 | ||
|
|
db1a5609a0 | ||
|
|
17690ea5a7 | ||
|
|
328512876a | ||
|
|
d3a4b85670 | ||
|
|
0a6b081cca | ||
|
|
25bc37f8a2 | ||
|
|
ec2ed58232 | ||
|
|
72075edafb | ||
|
|
f9f75f320e | ||
|
|
a3f3e54eee | ||
|
|
bc5e6b9f21 | ||
|
|
83d1d1a906 | ||
|
|
23b3cf9d10 | ||
|
|
39231e9105 | ||
|
|
d3896211d2 | ||
|
|
d64e124cf4 | ||
|
|
0f8cb5db73 | ||
|
|
b7c25e0c13 | ||
|
|
c59881eaee | ||
|
|
999b4cacaf | ||
|
|
2030fc6bc2 | ||
|
|
711d5038f5 | ||
|
|
7dcd200489 | ||
|
|
b03cb15789 | ||
|
|
32af6b16f1 | ||
|
|
cc201e01f8 | ||
|
|
25ab17585e | ||
|
|
303a47c095 | ||
|
|
c85c37acb1 | ||
|
|
4efbda3f25 | ||
|
|
1df182ff88 | ||
|
|
15b87b2ec4 | ||
|
|
d27b4576f3 | ||
|
|
2aa3429899 | ||
|
|
9f3de58d83 | ||
|
|
7c39b56c3b | ||
|
|
aa625ed6ed | ||
|
|
b0529ffd95 | ||
|
|
88bc5f9485 | ||
|
|
6af93ee2ea | ||
|
|
b25474d1be | ||
|
|
cd5ee3bbb4 | ||
|
|
402deef944 | ||
|
|
245484679a | ||
|
|
cce89ead18 | ||
|
|
26d9e2c19d | ||
|
|
b0cfef3214 | ||
|
|
2e5a781c64 | ||
|
|
baba6e7de2 | ||
|
|
74f28bf1fd | ||
|
|
328b26d40b | ||
|
|
a15bc17632 | ||
|
|
f1142dcc5b | ||
|
|
9909340f37 | ||
|
|
882164196e | ||
|
|
6bf4253a68 | ||
|
|
9d952d17bb | ||
|
|
3ad9f8a70f | ||
|
|
3ae0735553 | ||
|
|
0b452dff5e | ||
|
|
7bf8b7c25c | ||
|
|
0b9a05a2bc | ||
|
|
30999ec6f9 | ||
|
|
ab07866c8d | ||
|
|
f051ee5f96 | ||
|
|
aad945f9b1 | ||
|
|
0104e36d4b | ||
|
|
f118b5fc5d | ||
|
|
9d4b05c0dc | ||
|
|
f69b82e78a | ||
|
|
b04f301c8e | ||
|
|
5d1b8f1725 | ||
|
|
d2291cce92 | ||
|
|
8beb917c6c | ||
|
|
177dbcaace | ||
|
|
c52296a73e | ||
|
|
4477b17f15 | ||
|
|
68649bef93 | ||
|
|
2bc4fd609c | ||
|
|
91f43a33f8 | ||
|
|
70f55355e2 | ||
|
|
4c932cca6f | ||
|
|
b6a35d2d52 | ||
|
|
b25cc627a3 | ||
|
|
341519523f | ||
|
|
2a9b46cf4b | ||
|
|
34c69036da | ||
|
|
a702ceaafc | ||
|
|
9ef59797af | ||
|
|
b8056dc5d0 | ||
|
|
5e437f05c7 | ||
|
|
149f580c82 | ||
|
|
dc77dce07c | ||
|
|
ca9afa8401 | ||
|
|
198fb229a4 | ||
|
|
575bdcde93 | ||
|
|
137d0685a4 | ||
|
|
1240a1b0a8 | ||
|
|
7012b124bc | ||
|
|
c55fd06b99 | ||
|
|
aacefd2795 | ||
|
|
39f0d96860 | ||
|
|
b2f76e9ded | ||
|
|
9965e1d044 | ||
|
|
43cda5f325 | ||
|
|
06706ab8ef | ||
|
|
be4d08b261 | ||
|
|
b2a967cd0b | ||
|
|
c981d768b3 | ||
|
|
8498c59144 | ||
|
|
5dc090009e | ||
|
|
ab84512258 | ||
|
|
52a3d2635c | ||
|
|
29b7273153 | ||
|
|
b985efaac1 | ||
|
|
9e8818ec9d | ||
|
|
4063460534 | ||
|
|
8d7849b6db | ||
|
|
922e8e2929 | ||
|
|
d11a58a2d3 | ||
|
|
f290a649f9 | ||
|
|
10ba0a3efc | ||
|
|
b24e6e4d1b | ||
|
|
a1de57a063 | ||
|
|
340f0876ea | ||
|
|
6950bb6200 | ||
|
|
025d495481 | ||
|
|
3f64fa1369 | ||
|
|
afcf6f974f | ||
|
|
b43eaa5508 | ||
|
|
ebf9065c22 | ||
|
|
a4902c9e7c | ||
|
|
2e555237d3 | ||
|
|
7501d61633 | ||
|
|
b3974ec9d4 | ||
|
|
d4d9c734c3 | ||
|
|
11529c6e4f | ||
|
|
65c82be021 | ||
|
|
1684f98b27 | ||
|
|
67a42f929b | ||
|
|
7453497ee4 | ||
|
|
7486c64dd8 | ||
|
|
7d145a0f59 | ||
|
|
9a93c4c024 | ||
|
|
f7a9a11391 | ||
|
|
d237f62c23 | ||
|
|
96d3bcb996 | ||
|
|
af8c56f8be | ||
|
|
8677f9c751 | ||
|
|
112b0e97d4 | ||
|
|
73e86eedd5 | ||
|
|
daad9a9a71 | ||
|
|
0fcf91ea1e | ||
|
|
ecaa91d1df | ||
|
|
4231eb217c | ||
|
|
a75d7066b8 | ||
|
|
6ec76ca09e | ||
|
|
56c6e3696d | ||
|
|
625b56de64 | ||
|
|
6d6d392b22 | ||
|
|
89772f932a | ||
|
|
61977f956c | ||
|
|
60835d9627 | ||
|
|
6996a9d713 | ||
|
|
0b5d6f1e26 | ||
|
|
1194739745 | ||
|
|
cad5745138 | ||
|
|
56690a69d6 | ||
|
|
fe358165e3 | ||
|
|
8a53cb0b9d | ||
|
|
5ad2ca011e | ||
|
|
3a6ede13f8 | ||
|
|
c58e7d4e01 | ||
|
|
c4a4a4b886 | ||
|
|
e073457191 | ||
|
|
c75abc9f7e | ||
|
|
96b1e085c3 | ||
|
|
7415b805c4 | ||
|
|
2e17ac83c6 | ||
|
|
ce336fdc21 | ||
|
|
bde280b9a4 | ||
|
|
21d9f36781 | ||
|
|
781c06c0f5 | ||
|
|
595925592d | ||
|
|
f06e3e0ea6 | ||
|
|
f18a119ac0 | ||
|
|
77f21f1583 | ||
|
|
0e87f34bed | ||
|
|
387c8e3c5b | ||
|
|
74f5435e10 | ||
|
|
22123c85f3 | ||
|
|
9ef7fa3447 | ||
|
|
26ce92b352 | ||
|
|
bd846c0e56 | ||
|
|
3528650560 | ||
|
|
bafb43d6c1 | ||
|
|
9e470585b3 | ||
|
|
be237c119e | ||
|
|
2a45a494b0 | ||
|
|
a0871afb2b | ||
|
|
fae3e2aab6 | ||
|
|
d7062ef1bd | ||
|
|
3ae65166b5 | ||
|
|
e679ec969c | ||
|
|
cc40ba2151 | ||
|
|
bf798734db | ||
|
|
1466b8b78a | ||
|
|
7e55c1ab65 | ||
|
|
99a289f531 | ||
|
|
fc90967876 | ||
|
|
1f3bc1c239 | ||
|
|
f8ded588a2 | ||
|
|
cd2b8832fd | ||
|
|
95d888a6d1 | ||
|
|
30ab2c9c46 | ||
|
|
15a8590ecf | ||
|
|
93db3fceac | ||
|
|
4c6e22953e | ||
|
|
cce16fdc68 | ||
|
|
647734881c | ||
|
|
8214620178 | ||
|
|
f0a70570fe | ||
|
|
6e39e7c9b3 | ||
|
|
ab6c45372c | ||
|
|
fdaf1dfd2e | ||
|
|
4051e79887 | ||
|
|
8896c2d9d6 | ||
|
|
61a8c0569e | ||
|
|
dbbf1d4a48 | ||
|
|
a880b29cab | ||
|
|
b12fc3e112 | ||
|
|
7ca47cece7 | ||
|
|
01ea41b203 | ||
|
|
857aa73783 | ||
|
|
43421af2e4 | ||
|
|
5491c310a6 | ||
|
|
1d8b4cd544 | ||
|
|
7ad4ca9c17 | ||
|
|
93e92d3f44 | ||
|
|
ca287d66f2 | ||
|
|
94b97046fd | ||
|
|
189dbde982 | ||
|
|
45198af2be | ||
|
|
4dba26620c | ||
|
|
a22535144c | ||
|
|
8848a70ba1 | ||
|
|
f66eabd281 | ||
|
|
7915370cb9 | ||
|
|
3f9144d42c | ||
|
|
43ae68b5ef | ||
|
|
1c4aab926e | ||
|
|
5e1ddc4210 | ||
|
|
173efb1865 | ||
|
|
f81ce5bd6d | ||
|
|
43f20bb3c2 | ||
|
|
10fd7f6689 | ||
|
|
eb5fff9e16 | ||
|
|
a7120a3647 | ||
|
|
0305f60cad | ||
|
|
e1b1055b46 | ||
|
|
2bc6cecebb | ||
|
|
24911ac65d | ||
|
|
94f778bdeb | ||
|
|
d8b8640863 | ||
|
|
b790077c37 | ||
|
|
8787ee699c | ||
|
|
f4894d9793 | ||
|
|
e92e97f1ee | ||
|
|
50aa850fc8 | ||
|
|
4b53cff901 | ||
|
|
605ca141c7 | ||
|
|
795faa595c | ||
|
|
42eb76a054 | ||
|
|
92979f8288 | ||
|
|
0310cd6403 | ||
|
|
4ad4f66327 | ||
|
|
e6389c3229 | ||
|
|
67c454c67c | ||
|
|
fe9032709c | ||
|
|
a3c675d1a3 | ||
|
|
555d1cd02f | ||
|
|
c968b684ee | ||
|
|
aa1ed9265f | ||
|
|
459d3fb77b | ||
|
|
f53c5ede73 | ||
|
|
b2d3b2d65d | ||
|
|
1c15f88653 | ||
|
|
37971fcc76 | ||
|
|
1b93ea0e31 | ||
|
|
c4de918478 | ||
|
|
8d0923109d | ||
|
|
709c1b267f | ||
|
|
b6d11a3018 | ||
|
|
4585f7e2c1 | ||
|
|
d764d9161e | ||
|
|
9e9869d0fe | ||
|
|
e6a729d2d8 | ||
|
|
88a1b89452 | ||
|
|
af836ad588 | ||
|
|
66112ed6e6 | ||
|
|
15ceadf7a5 | ||
|
|
405ce5a876 | ||
|
|
19197d5e29 | ||
|
|
29c8b9416d | ||
|
|
0fe19a3a2c | ||
|
|
d2e21a9d74 | ||
|
|
6be6be2ed9 | ||
|
|
81dd7aa4c1 | ||
|
|
5a7321562d | ||
|
|
ba1fce94b5 | ||
|
|
5efee7da86 | ||
|
|
145b2d078e | ||
|
|
3c0baa68fa | ||
|
|
90b5aadf56 | ||
|
|
dead0ff8cd | ||
|
|
0fb0a38339 | ||
|
|
9bc9593df5 | ||
|
|
38f33ce4a3 | ||
|
|
2b814d6eb0 | ||
|
|
560078a768 | ||
|
|
e1739cbf38 | ||
|
|
09d7be3e63 | ||
|
|
7e91dd27da | ||
|
|
d825e6a31b | ||
|
|
1615c14756 | ||
|
|
f873b84d6e | ||
|
|
3083cf100a | ||
|
|
7298ebb432 |
2
COPYING
2
COPYING
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2011 Bitcoin Developers
|
||||
Copyright (c) 2009-2012 Bitcoin Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
VERSION = 0.5.0
|
||||
VERSION = 0.6.0
|
||||
INCLUDEPATH += src src/json src/qt
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
|
||||
CONFIG += no_include_pwd
|
||||
@@ -30,6 +30,14 @@ contains(RELEASE, 1) {
|
||||
}
|
||||
}
|
||||
|
||||
# use: qmake "USE_QRCODE=1"
|
||||
# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
|
||||
contains(USE_QRCODE, 1) {
|
||||
message(Building with QRCode support)
|
||||
DEFINES += USE_QRCODE
|
||||
LIBS += -lqrencode
|
||||
}
|
||||
|
||||
# use: qmake "USE_UPNP=1" ( enabled by default; default)
|
||||
# or: qmake "USE_UPNP=0" (disabled by default)
|
||||
# or: qmake "USE_UPNP=-" (not supported)
|
||||
@@ -60,9 +68,15 @@ contains(USE_SSL, 1) {
|
||||
DEFINES += USE_SSL
|
||||
}
|
||||
|
||||
# use: qmake "FIRST_CLASS_MESSAGING=1"
|
||||
contains(FIRST_CLASS_MESSAGING, 1) {
|
||||
message(Building with first-class messaging)
|
||||
DEFINES += FIRST_CLASS_MESSAGING
|
||||
}
|
||||
|
||||
contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
DEFINES += BITCOIN_NEED_QT_PLUGINS
|
||||
QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs
|
||||
QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
|
||||
}
|
||||
|
||||
!windows {
|
||||
@@ -83,11 +97,15 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/optionsdialog.h \
|
||||
src/qt/sendcoinsdialog.h \
|
||||
src/qt/addressbookpage.h \
|
||||
src/qt/messagepage.h \
|
||||
src/qt/aboutdialog.h \
|
||||
src/qt/editaddressdialog.h \
|
||||
src/qt/bitcoinaddressvalidator.h \
|
||||
src/addrman.h \
|
||||
src/base58.h \
|
||||
src/bignum.h \
|
||||
src/checkpoints.h \
|
||||
src/compat.h \
|
||||
src/util.h \
|
||||
src/uint256.h \
|
||||
src/serialize.h \
|
||||
@@ -101,6 +119,7 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/init.h \
|
||||
src/headers.h \
|
||||
src/irc.h \
|
||||
src/mruset.h \
|
||||
src/json/json_spirit_writer_template.h \
|
||||
src/json/json_spirit_writer.h \
|
||||
src/json/json_spirit_value.h \
|
||||
@@ -135,7 +154,8 @@ HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/qvaluecombobox.h \
|
||||
src/qt/askpassphrasedialog.h \
|
||||
src/protocol.h \
|
||||
src/qt/notificator.h
|
||||
src/qt/notificator.h \
|
||||
src/qt/qtipcserver.h
|
||||
|
||||
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/transactiontablemodel.cpp \
|
||||
@@ -143,15 +163,20 @@ 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/aboutdialog.cpp \
|
||||
src/qt/editaddressdialog.cpp \
|
||||
src/qt/bitcoinaddressvalidator.cpp \
|
||||
src/util.cpp \
|
||||
src/netbase.cpp \
|
||||
src/key.cpp \
|
||||
src/script.cpp \
|
||||
src/main.cpp \
|
||||
src/init.cpp \
|
||||
src/net.cpp \
|
||||
src/irc.cpp \
|
||||
src/checkpoints.cpp \
|
||||
src/addrman.cpp \
|
||||
src/db.cpp \
|
||||
src/json/json_spirit_writer.cpp \
|
||||
src/json/json_spirit_value.cpp \
|
||||
@@ -171,6 +196,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/transactionview.cpp \
|
||||
src/qt/walletmodel.cpp \
|
||||
src/bitcoinrpc.cpp \
|
||||
src/rpcdump.cpp \
|
||||
src/qt/overviewpage.cpp \
|
||||
src/qt/csvmodelwriter.cpp \
|
||||
src/crypter.cpp \
|
||||
@@ -180,7 +206,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||
src/qt/qvaluecombobox.cpp \
|
||||
src/qt/askpassphrasedialog.cpp \
|
||||
src/protocol.cpp \
|
||||
src/qt/notificator.cpp
|
||||
src/qt/notificator.cpp \
|
||||
src/qt/qtipcserver.cpp
|
||||
|
||||
RESOURCES += \
|
||||
src/qt/bitcoin.qrc
|
||||
@@ -188,6 +215,7 @@ RESOURCES += \
|
||||
FORMS += \
|
||||
src/qt/forms/sendcoinsdialog.ui \
|
||||
src/qt/forms/addressbookpage.ui \
|
||||
src/qt/forms/messagepage.ui \
|
||||
src/qt/forms/aboutdialog.ui \
|
||||
src/qt/forms/editaddressdialog.ui \
|
||||
src/qt/forms/transactiondescdialog.ui \
|
||||
@@ -195,6 +223,22 @@ FORMS += \
|
||||
src/qt/forms/sendcoinsentry.ui \
|
||||
src/qt/forms/askpassphrasedialog.ui
|
||||
|
||||
contains(USE_QRCODE, 1) {
|
||||
HEADERS += src/qt/qrcodedialog.h
|
||||
SOURCES += src/qt/qrcodedialog.cpp
|
||||
FORMS += src/qt/forms/qrcodedialog.ui
|
||||
}
|
||||
|
||||
contains(BITCOIN_QT_TEST, 1) {
|
||||
SOURCES += src/qt/test/test_main.cpp \
|
||||
src/qt/test/urltests.cpp
|
||||
HEADERS += src/qt/test/urltests.h
|
||||
DEPENDPATH += src/qt/test
|
||||
QT += testlib
|
||||
TARGET = bitcoin-qt_test
|
||||
DEFINES += BITCOIN_QT_TEST
|
||||
}
|
||||
|
||||
CODECFORTR = UTF-8
|
||||
|
||||
# for lrelease/lupdate
|
||||
@@ -202,7 +246,7 @@ CODECFORTR = UTF-8
|
||||
TRANSLATIONS = $$files(src/qt/locale/bitcoin_*.ts)
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\lrelease.exe
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
}
|
||||
isEmpty(TS_DIR):TS_DIR = src/qt/locale
|
||||
@@ -249,21 +293,39 @@ isEmpty(BOOST_INCLUDE_PATH) {
|
||||
macx:BOOST_INCLUDE_PATH = /opt/local/include
|
||||
}
|
||||
|
||||
windows:LIBS += -lws2_32 -lgdi32
|
||||
windows:LIBS += -lws2_32 -lshlwapi
|
||||
windows:DEFINES += WIN32
|
||||
windows:RC_FILE = src/qt/res/bitcoin-qt.rc
|
||||
|
||||
windows:!contains(MINGW_THREAD_BUGFIX, 0) {
|
||||
# At least qmake's win32-g++-cross profile is missing the -lmingwthrd
|
||||
# thread-safety flag. GCC has -mthreads to enable this, but it doesn't
|
||||
# work with static linking. -lmingwthrd must come BEFORE -lmingw, so
|
||||
# it is prepended to QMAKE_LIBS_QT_ENTRY.
|
||||
# It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes
|
||||
# any problems on some untested qmake profile now or in the future.
|
||||
DEFINES += _MT
|
||||
QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY
|
||||
}
|
||||
|
||||
!windows:!mac {
|
||||
DEFINES += LINUX
|
||||
LIBS += -lrt
|
||||
}
|
||||
|
||||
macx:HEADERS += src/qt/macdockiconhandler.h
|
||||
macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
|
||||
macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3
|
||||
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
|
||||
macx:ICON = src/qt/res/icons/bitcoin.icns
|
||||
macx:TARGET = "Bitcoin-Qt"
|
||||
|
||||
# Set libraries and includes at end, to use platform-defined defaults if not overridden
|
||||
INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH
|
||||
LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,)
|
||||
INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
|
||||
LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
|
||||
LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX
|
||||
# -lgdi32 has to happen after -lcrypto (see #681)
|
||||
windows:LIBS += -lole32 -luuid -lgdi32
|
||||
LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
|
||||
|
||||
contains(RELEASE, 1) {
|
||||
|
||||
16
contrib/debian/bin/bitcoin-qt
Executable file
16
contrib/debian/bin/bitcoin-qt
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/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 "$@"
|
||||
18
contrib/debian/bin/bitcoind
Executable file
18
contrib/debian/bin/bitcoind
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
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 "$@"
|
||||
10
contrib/debian/bitcoin-qt.desktop
Normal file
10
contrib/debian/bitcoin-qt.desktop
Normal file
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Name=Bitcoin
|
||||
Comment=Bitcoin P2P Cryptocurrency
|
||||
Exec=/usr/bin/bitcoin-qt
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=/usr/share/pixmaps/bitcoin80.xpm
|
||||
MimeType=x-scheme-handler/bitcoin;
|
||||
Categories=Office;
|
||||
6
contrib/debian/bitcoin-qt.install
Normal file
6
contrib/debian/bitcoin-qt.install
Normal file
@@ -0,0 +1,6 @@
|
||||
debian/bin/bitcoin-qt usr/bin
|
||||
bitcoin-qt usr/lib/bitcoin
|
||||
share/pixmaps/bitcoin32.xpm usr/share/pixmaps
|
||||
share/pixmaps/bitcoin80.xpm usr/share/pixmaps
|
||||
debian/bitcoin-qt.desktop usr/share/applications
|
||||
debian/bitcoin-qt.protocol usr/share/kde4/services/
|
||||
2
contrib/debian/bitcoin-qt.lintian-overrides
Normal file
2
contrib/debian/bitcoin-qt.lintian-overrides
Normal file
@@ -0,0 +1,2 @@
|
||||
# Linked code is Expat - only Debian packaging is GPL-2+
|
||||
bitcoin-qt: possible-gpl-code-linked-with-openssl
|
||||
11
contrib/debian/bitcoin-qt.protocol
Normal file
11
contrib/debian/bitcoin-qt.protocol
Normal file
@@ -0,0 +1,11 @@
|
||||
[Protocol]
|
||||
exec=bitcoin-qt '%u'
|
||||
protocol=bitcoin
|
||||
input=none
|
||||
output=none
|
||||
helper=true
|
||||
listing=
|
||||
reading=false
|
||||
writing=false
|
||||
makedir=false
|
||||
deleting=false
|
||||
1
contrib/debian/bitcoind.examples
Normal file
1
contrib/debian/bitcoind.examples
Normal file
@@ -0,0 +1 @@
|
||||
debian/examples/bitcoin.conf
|
||||
2
contrib/debian/bitcoind.install
Normal file
2
contrib/debian/bitcoind.install
Normal file
@@ -0,0 +1,2 @@
|
||||
debian/bin/bitcoind usr/bin
|
||||
src/bitcoind usr/lib/bitcoin
|
||||
2
contrib/debian/bitcoind.lintian-overrides
Normal file
2
contrib/debian/bitcoind.lintian-overrides
Normal file
@@ -0,0 +1,2 @@
|
||||
# Linked code is Expat - only Debian packaging is GPL-2+
|
||||
bitcoind: possible-gpl-code-linked-with-openssl
|
||||
2
contrib/debian/bitcoind.manpages
Normal file
2
contrib/debian/bitcoind.manpages
Normal file
@@ -0,0 +1,2 @@
|
||||
debian/manpages/bitcoind.1
|
||||
debian/manpages/bitcoin.conf.5
|
||||
277
contrib/debian/changelog
Normal file
277
contrib/debian/changelog
Normal file
@@ -0,0 +1,277 @@
|
||||
bitcoin (0.5.1-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
|
||||
|
||||
bitcoin (0.5.1-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Fri, 16 Dec 2011 13:27:00 -0500
|
||||
|
||||
bitcoin (0.5.0-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Mon, 21 Nov 2011 11:32:00 -0500
|
||||
|
||||
bitcoin (0.5.0~rc7-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release candidate.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Sun, 20 Nov 2011 17:08:00 -0500
|
||||
|
||||
bitcoin (0.5.0~rc3-natty0) natty; urgency=low
|
||||
|
||||
* New upstream release candidate.
|
||||
* Don't set rpcpassword for bitcoin-qt.
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Tue, 8 Nov 2011 11:56:00 -0400
|
||||
|
||||
bitcoin (0.5.0~rc1-natty1) natty; urgency=low
|
||||
|
||||
* Add test_bitcoin to build test
|
||||
* Fix clean
|
||||
* Remove uneccessary build-dependancies
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
|
||||
|
||||
bitcoin (0.5.0~rc1-natty0) natty; urgency=low
|
||||
|
||||
* Mark for natty
|
||||
* Fix broken build
|
||||
* Fix copyright listing
|
||||
* Remove bitcoin: URL handler until bitcoin actually has support for it (Oops)
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
|
||||
|
||||
bitcoin (0.5.0~rc1-2) experimental; urgency=low
|
||||
|
||||
* Add bitcoin-qt
|
||||
|
||||
-- Matt Corallo <matt@bluematt.me> Tue, 25 Oct 2011 15:24:18 -0400
|
||||
|
||||
bitcoin (0.5.0~rc1-1) experimental; urgency=low
|
||||
|
||||
* New upstream prerelease.
|
||||
* Add Github as alternate upstream source in watch file.
|
||||
* Stop build-depending on libcrypto++-dev, and drop patch 1000:
|
||||
Upstream no longer use crypto++.
|
||||
* Drop patch 1003: Upstream builds dynamic by default now.
|
||||
* Update copyright file: Drop notes on longer included sources.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Fri, 14 Oct 2011 00:16:18 +0200
|
||||
|
||||
bitcoin (0.4.0-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Stop repackaging source tarballs: No DFSG-violating stripping left.
|
||||
* Update copyright file:
|
||||
+ Add Github URL to Source.
|
||||
* Drop dpkg-source local-options hint: Declared options are default
|
||||
since dpkg-source 1.16.1.
|
||||
+ Add irc URL to Upstream-Contact.
|
||||
+ Add comment on Bitcoin Developers to catch-all Files section.
|
||||
+ Add Files sections for newly readded src/cryptopp/* (new custom
|
||||
BSD-like license), and newly added doc/build-osx.txt and
|
||||
src/makefile.osx (Expat).
|
||||
* Bump debhelper compatibility level to 7.
|
||||
* Suppress binary icns and gpg files.
|
||||
* Enable regression tests:
|
||||
+ Build-depend on libboost-test-dev.
|
||||
+ Extend patch 1003 to also dynamically link test binary.
|
||||
+ Build and invoke test binary unless tests are disabled.
|
||||
* Tighten build-dependency on cdbs: Recent version needed to support
|
||||
debhelper 7.
|
||||
* Relax build-depend unversioned on debhelper: needed version
|
||||
satisfied even in oldstable.
|
||||
* Stop suppress optional build-dependencies: Satisfied in stable.
|
||||
Build-depend on devscripts (enabling copyright-check).
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Wed, 05 Oct 2011 01:48:53 +0200
|
||||
|
||||
bitcoin (0.3.24~dfsg-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Jonas Smedegaard ]
|
||||
* Improve various usage hints:
|
||||
+ Explicitly mention in long description that bitcoind contains
|
||||
daemon and command-line interface.
|
||||
+ Extend README.Debian with section on lack of GUI, and add primary
|
||||
headline.
|
||||
+ Avoid installing upstream README: contains no parts relevant for
|
||||
Debian usage.
|
||||
Thanks to richard for suggestions (see bug#629443).
|
||||
* Favor final releases over prereleases in rules and watch file.
|
||||
Thanks to Jan Dittberner.
|
||||
* Track -src (not -linux) tarballs in rules and watch file.
|
||||
Thanks to Jan Dittberner.
|
||||
* Drop patches 1004 and 1005 (integrated upstream) and simplify
|
||||
CXXFLAGS in rules file.
|
||||
* Stop stripping no longer included source-less binaries from upstream
|
||||
tarballs.
|
||||
|
||||
[ Jan Dittberner ]
|
||||
* refresh debian/patches/1000_use_system_crypto++.patch
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Tue, 19 Jul 2011 15:08:54 +0200
|
||||
|
||||
bitcoin (0.3.21~dfsg-2) unstable; urgency=low
|
||||
|
||||
* Enable UPNP support:
|
||||
+ Drop patch 1006.
|
||||
+ Build-depend on libminiupnpc-dev.
|
||||
Thanks to Matt Corallo.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Sat, 28 May 2011 15:52:44 +0200
|
||||
|
||||
bitcoin (0.3.21~dfsg-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Refresh patches.
|
||||
* Drop patch 1002: no longer needed, as upstream use pkgconfig now.
|
||||
* Add patch 1006 to really unset USE_UPNP as aparently intended.
|
||||
* Adjust cleanup rule to preserve .gitignore files.
|
||||
* Update copyright file:
|
||||
+ Bump format to draft 174 of DEP-5.
|
||||
+ Shorten comments.
|
||||
* Bump policy compliance to standards-version 3.9.2.
|
||||
* Shorten Vcs-Browser paragraph in control file.
|
||||
* Fix mention daemon (not CLI tools) in short description.
|
||||
* Stop conflicting with or replace bitcoin-cli: Only transitional, no
|
||||
longer needed.
|
||||
* Link against unversioned berkeleydb. Update NEWS and README.Debian
|
||||
accordingly (and improve wording while at it).
|
||||
Closes: Bug#621425. Thanks to Ondřej Surý.
|
||||
* This release also implicitly updates linkage against libcrypto++,
|
||||
which closes: bug#626953, #627024.
|
||||
* Disable linkage against not yet Debian packaged MiniUPnP.
|
||||
* Silence seemingly harmless noise about unused variables.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Tue, 17 May 2011 15:31:24 +0200
|
||||
|
||||
bitcoin (0.3.20.2~dfsg-2) unstable; urgency=medium
|
||||
|
||||
* Fix have wrapper script execute real binary (not loop executing
|
||||
itself).
|
||||
Closes: bug#617290. Thanks to Philippe Gauthier and Etienne Laurin.
|
||||
* Set urgency=medium as the only (user-exposed) binary is useless
|
||||
without this fix and has been for some time.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Wed, 16 Mar 2011 09:11:06 +0100
|
||||
|
||||
bitcoin (0.3.20.2~dfsg-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Fix provide and replace former package name bitcoin-cli.
|
||||
Closes: bug#618439. Thanks to Shane Wegner.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Tue, 15 Mar 2011 11:41:43 +0100
|
||||
|
||||
bitcoin (0.3.20.01~dfsg-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
[ Micah Anderson ]
|
||||
* Add myself as uploader.
|
||||
|
||||
[ Jonas Smedegaard ]
|
||||
* Add wrapper for bitcoind to ease initial startup.
|
||||
* Update patches:
|
||||
+ Drop patch 2002: Applied upstream.
|
||||
+ Add patch 1005 to add phtread linker option.
|
||||
Closes: bug#615619. Thanks to Shane Wegner.
|
||||
+ Refresh patches.
|
||||
* Extend copyright years in rules file header.
|
||||
* Rewrite copyright file using draft svn166 of DEP5 format.
|
||||
* Rename binary package to bitcoind (from bincoin-cli).
|
||||
Closes: bug#614025. Thanks to Luke-Jr.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Tue, 01 Mar 2011 15:55:04 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-6) unstable; urgency=low
|
||||
|
||||
* Fix override agressive optimizations.
|
||||
* Fix tighten build-dependencies to really fit backporting to Lenny:
|
||||
+ Add fallback build-dependency on libdb4.6++-dev.
|
||||
+ Tighten unversioned Boost build-dependencies to recent versions,
|
||||
To force use of versioned Boost when backporting to Lenny.
|
||||
...needs more love, though: actual build fails.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 19:48:35 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-5) unstable; urgency=low
|
||||
|
||||
* Fix lower Boost fallback-build-dependencies to 1.35, really
|
||||
available in Lenny.
|
||||
* Correct comment in rules file regarding reason for versioned Boost
|
||||
fallback-build-dependency.
|
||||
* Add patch 2002 adding -mt decoration to Boost flags, to ease
|
||||
backporting to Lenny.
|
||||
* Respect DEB_BUILD_OPTIONS, and suppress arch-specific optimizations:
|
||||
+ Add patch 1004 to allow overriding optimization flags.
|
||||
+ Set optimization flags conditionally at build time.
|
||||
+ Drop patch 2002 unconditionally suppressing arch-optimizations.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 16:04:48 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-4) unstable; urgency=low
|
||||
|
||||
[ Micah Anderson ]
|
||||
* Provide example bitcoin.conf.
|
||||
* Add bitcoind(1) and bitcoin.conf(5) man pages.
|
||||
|
||||
[ Jonas Smedegaard ]
|
||||
* Ease backporting:
|
||||
+ Suppress optional build-dependencies.
|
||||
+ Add fallback build-dependencies on the most recent Boost libs
|
||||
available in Lenny (where unversioned Boost libs are missing).
|
||||
* Add Micah as copyright holder for manpages, licensed as GPL-3+.
|
||||
* Bump copyright format to Subversion candidate draft 162 of DEP5.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Mon, 17 Jan 2011 14:00:48 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-3) unstable; urgency=low
|
||||
|
||||
* Document in copyright file files excluded from repackaged source.
|
||||
* Update copyright file:
|
||||
+ Bump DEP5 format hint to Subversion draft rev. 153.
|
||||
+ Consistently wrap at 72 chars.
|
||||
+ Refer to GPL-2 file (not GPL symlink).
|
||||
* Link against Berkeley DB 4.8 (not 4.7):
|
||||
+ Build-depend on libdb4.8++-dev (and on on libdb4.7++-dev).
|
||||
+ Suggest libdb4.8-util and db4.7-util.
|
||||
+ Add README.Debian note on (untested) upgrade routine.
|
||||
+ Add NEWS entry on changed db version, referring to README.Debian.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Fri, 07 Jan 2011 22:50:57 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-2) unstable; urgency=low
|
||||
|
||||
* Adjust build options to use optimized miner only for amd64. Fixes
|
||||
FTBFS on i386 (and other archs, if compiling anywhere else at all).
|
||||
* Avoid static linking.
|
||||
* Adjust patch 2001 to avoid only arch-specific optimizations (keep
|
||||
-O3).
|
||||
* Extend long description to mention disk consumption and initial use
|
||||
of IRC.
|
||||
All of above changes thanks to Helmuth Grohne.
|
||||
* Add lintian override regarding OpenSSL and GPL: Linked code is Expat
|
||||
- only Debian packaging is GPL-2+.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Wed, 29 Dec 2010 00:27:54 +0100
|
||||
|
||||
bitcoin (0.3.19~dfsg-1) unstable; urgency=low
|
||||
|
||||
[ Jonas Smedegaard ]
|
||||
* Initial release.
|
||||
Closes: bug#578157.
|
||||
|
||||
-- Jonas Smedegaard <dr@jones.dk> Tue, 28 Dec 2010 15:49:22 +0100
|
||||
1
contrib/debian/compat
Normal file
1
contrib/debian/compat
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
58
contrib/debian/control
Normal file
58
contrib/debian/control
Normal file
@@ -0,0 +1,58 @@
|
||||
Source: bitcoin
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Maintainer: Jonas Smedegaard <dr@jones.dk>
|
||||
Uploaders: Micah Anderson <micah@debian.org>
|
||||
Build-Depends: debhelper,
|
||||
devscripts,
|
||||
libboost-system-dev (>> 1.35) | libboost-system1.35-dev,
|
||||
libdb4.8++-dev,
|
||||
libssl-dev,
|
||||
pkg-config,
|
||||
libminiupnpc8-dev,
|
||||
libboost-filesystem-dev (>> 1.35) | libboost-filesystem1.35-dev,
|
||||
libboost-program-options-dev (>> 1.35) | libboost-program-options1.35-dev,
|
||||
libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev,
|
||||
libboost-test-dev (>> 1.35) | libboost-test1.35-dev,
|
||||
qt4-qmake,
|
||||
libqt4-dev,
|
||||
libqrencode-dev
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: http://www.bitcoin.org/
|
||||
Vcs-Git: git://github.com/bitcoin/bitcoin.git
|
||||
Vcs-Browser: http://github.com/bitcoin/bitcoin
|
||||
|
||||
Package: bitcoind
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: peer-to-peer network based digital currency - daemon
|
||||
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
|
||||
transact directly with each other, with the help of a P2P network to
|
||||
check for double-spending.
|
||||
.
|
||||
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.
|
||||
.
|
||||
This package provides bitcoind, a combined daemon and CLI tool to
|
||||
interact with the daemon.
|
||||
|
||||
Package: bitcoin-qt
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
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
|
||||
transact directly with each other, with the help of a P2P network to
|
||||
check for double-spending.
|
||||
.
|
||||
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.
|
||||
.
|
||||
This package provides bitcoin-qt, a GUI for Bitcoin based on QT.
|
||||
167
contrib/debian/copyright
Normal file
167
contrib/debian/copyright
Normal file
@@ -0,0 +1,167 @@
|
||||
Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=174
|
||||
Upstream-Name: Bitcoin
|
||||
Upstream-Contact: Satoshi Nakamoto <satoshin@gmx.com>
|
||||
irc://#bitcoin@freenode.net
|
||||
Source: http://sourceforge.net/projects/bitcoin/files/
|
||||
https://github.com/bitcoin/bitcoin
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2011, 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.
|
||||
|
||||
Files: src/json/*
|
||||
Copyright: 2007-2009, John W. Wilkinson
|
||||
License: Expat
|
||||
|
||||
Files: src/strlcpy.h
|
||||
Copyright: 1998, Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
License: ISC
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2010-2011, Jonas Smedegaard <dr@jones.dk>
|
||||
2011, Matt Corallo <matt@bluematt.me>
|
||||
License: GPL-2+
|
||||
|
||||
Files: debian/manpages/*
|
||||
Copyright: Micah Anderson <micah@debian.org>
|
||||
License: GPL-3+
|
||||
|
||||
Files: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
|
||||
src/qt/res/src/*.svg
|
||||
Copyright: Wladimir van der Laan
|
||||
License: Expat
|
||||
|
||||
Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
|
||||
src/qt/res/icons/history.png, src/qt/res/icons/key.png,
|
||||
src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
|
||||
src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
|
||||
src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png
|
||||
Copyright: David Vignoni (david@icon-king.com)
|
||||
ICON KING - www.icon-king.com
|
||||
License: LGPL
|
||||
Comment: NUVOLA ICON THEME for KDE 3.x
|
||||
Original icons: kaddressbook, klipper_dock, view-list-text,
|
||||
key-password, encrypted/decrypted, go-home, go-down,
|
||||
go-next, dialog-ok
|
||||
Site: http://www.icon-king.com/projects/nuvola/
|
||||
|
||||
Files: src/qt/res/icons/connect*.png
|
||||
Copyright: schollidesign
|
||||
License: GPL-3+
|
||||
Comment: Icon Pack: Human-O2
|
||||
Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0
|
||||
|
||||
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
|
||||
|
||||
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,
|
||||
src/qt/res/icons/add.png, src/qt/res/icons/edit.png,
|
||||
src/qt/res/icons/remove.png
|
||||
Copyright: http://www.everaldo.com
|
||||
License: LGPL
|
||||
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
|
||||
|
||||
Files: scripts/img/reload.xcf, src/qt/res/movies/update_spinner.mng
|
||||
Copyright: Everaldo (Everaldo Coelho)
|
||||
License: GPL-3+
|
||||
Comment: Icon Pack: Kids
|
||||
Site: http://findicons.com/icon/17102/reload?id=17102
|
||||
|
||||
Files: src/qt/res/images/splash2.jpg
|
||||
License: PUB-DOM
|
||||
Copyright: Crobbo (forum)
|
||||
Comment: Site: https://bitcointalk.org/index.php?topic=32273.0
|
||||
|
||||
|
||||
License: Expat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
License: ISC
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
SOFTWARE.
|
||||
|
||||
License: GPL-2+
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
Comment:
|
||||
On Debian systems the GNU General Public License (GPL) version 2 is
|
||||
located in '/usr/share/common-licenses/GPL-2'.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
License: GPL-3+
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU General Public License, Version 3 or any
|
||||
later version published by the Free Software Foundation.
|
||||
Comment:
|
||||
On Debian systems the GNU General Public License (GPL) version 3 is
|
||||
located in '/usr/share/common-licenses/GPL-3'.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
License: LGPL
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Comment:
|
||||
On Debian systems the GNU Lesser General Public License (LGPL) is
|
||||
located in '/usr/share/common-licenses/LGPL'.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
License: PUB-DOM
|
||||
This work is in the public domain.
|
||||
88
contrib/debian/examples/bitcoin.conf
Normal file
88
contrib/debian/examples/bitcoin.conf
Normal file
@@ -0,0 +1,88 @@
|
||||
# bitcoin.conf configuration file. Lines beginning with # are comments.
|
||||
|
||||
|
||||
# Network-related settings:
|
||||
|
||||
# Run on the test network instead of the real bitcoin network.
|
||||
#testnet=1
|
||||
|
||||
# Connect via a socks4 proxy
|
||||
#proxy=127.0.0.1:9050
|
||||
|
||||
# Use as many addnode= settings as you like to connect to specific peers
|
||||
#addnode=69.164.218.197
|
||||
#addnode=10.0.0.2:8333
|
||||
|
||||
# ... or use as many connect= settings as you like to connect ONLY
|
||||
# to specific peers:
|
||||
#connect=69.164.218.197
|
||||
#connect=10.0.0.1:8333
|
||||
|
||||
# Do not use Internet Relay Chat (irc.lfnet.org #bitcoin channel) to
|
||||
# find other peers.
|
||||
#noirc=1
|
||||
|
||||
# Maximum number of inbound+outbound connections.
|
||||
#maxconnections=
|
||||
|
||||
|
||||
# JSON-RPC options (for controlling a running Bitcoin/bitcoind process)
|
||||
|
||||
# server=1 tells Bitcoin to accept JSON-RPC commands.
|
||||
#server=1
|
||||
|
||||
# You must set rpcuser and rpcpassword to secure the JSON-RPC api
|
||||
#rpcuser=Ulysseys
|
||||
#rpcpassword=YourSuperGreatPasswordNumber_385593
|
||||
|
||||
# By default, only RPC connections from localhost are allowed. Specify
|
||||
# as many rpcallowip= settings as you like to allow connections from
|
||||
# other hosts (and you may use * as a wildcard character):
|
||||
#rpcallowip=10.1.1.34
|
||||
#rpcallowip=192.168.1.*
|
||||
|
||||
# Listen for RPC connections on this TCP port:
|
||||
rpcport=8332
|
||||
|
||||
# You can use Bitcoin or bitcoind to send commands to Bitcoin/bitcoind
|
||||
# running on another host using this option:
|
||||
rpcconnect=127.0.0.1
|
||||
|
||||
# Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate
|
||||
# with Bitcoin -server or bitcoind
|
||||
#rpcssl=1
|
||||
|
||||
# OpenSSL settings used when rpcssl=1
|
||||
rpcsslciphers=TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH
|
||||
rpcsslcertificatechainfile=server.cert
|
||||
rpcsslprivatekeyfile=server.pem
|
||||
|
||||
|
||||
# Miscellaneous options
|
||||
|
||||
# Set gen=1 to attempt to generate bitcoins
|
||||
gen=0
|
||||
|
||||
# Use SSE instructions to try to generate bitcoins faster.
|
||||
#4way=1
|
||||
|
||||
# Pre-generate this many public/private key pairs, so wallet backups will be valid for
|
||||
# both prior transactions and several dozen future transactions.
|
||||
keypool=100
|
||||
|
||||
# Pay an optional transaction fee every time you send bitcoins. Transactions with fees
|
||||
# are more likely than free transactions to be included in generated blocks, so may
|
||||
# be validated sooner.
|
||||
paytxfee=0.00
|
||||
|
||||
# Allow direct connections for the 'pay via IP address' feature.
|
||||
#allowreceivebyip=1
|
||||
|
||||
|
||||
# User interface options
|
||||
|
||||
# Start Bitcoin minimized
|
||||
#min=1
|
||||
|
||||
# Minimize to the system tray
|
||||
#minimizetotray=1
|
||||
5
contrib/debian/gbp.conf
Normal file
5
contrib/debian/gbp.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
# Configuration file for git-buildpackage and friends
|
||||
|
||||
[DEFAULT]
|
||||
pristine-tar = True
|
||||
sign-tags = True
|
||||
94
contrib/debian/manpages/bitcoin.conf.5
Normal file
94
contrib/debian/manpages/bitcoin.conf.5
Normal file
@@ -0,0 +1,94 @@
|
||||
.TH BITCOIN.CONF "5" "January 2011" "bitcoin.conf 3.19"
|
||||
.SH NAME
|
||||
bitcoin.conf \- bitcoin configuration file
|
||||
.SH SYNOPSIS
|
||||
All command-line options (except for '-datadir' and '-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file.
|
||||
.TP
|
||||
The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character.
|
||||
.TP
|
||||
The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, bitcoind(1) will look for a file named bitcoin.conf(5) in the bitcoin data directory, but both the data directory and the configuration file path may be changed using the '-datadir' and '-conf' command-line arguments.
|
||||
.SH LOCATION
|
||||
bitcoin.conf should be located in $HOME/.bitcoin
|
||||
.SH NETWORK-RELATED SETTINGS
|
||||
.TP
|
||||
.TP
|
||||
\fBtestnet=\fR[\fI'1'\fR|\fI'0'\fR]
|
||||
Enable or disable run on the test network instead of the real *bitcoin* network.
|
||||
.TP
|
||||
\fBproxy=\fR\fI'127.0.0.1:9050'\fR
|
||||
Connect via a socks4 proxy.
|
||||
.TP
|
||||
\fBaddnode=\fR\fI'10.0.0.2:8333'\fR
|
||||
Use as many *addnode=* settings as you like to connect to specific peers.
|
||||
.TP
|
||||
\fBconnect=\fR\fI'10.0.0.1:8333'\fR
|
||||
Use as many *connect=* settings as you like to connect ONLY to specific peers.
|
||||
.TP
|
||||
\fBnoirc=\fR[\fI'1'\fR|\fI'0'\fR]
|
||||
Use or Do not use Internet Relay Chat (irc.lfnet.org #bitcoin channel) to find other peers.
|
||||
.TP
|
||||
\fRmaxconnections=\fR\fI'value'\fR
|
||||
Maximum number of inbound+outbound connections.
|
||||
.SH JSON-RPC OPTIONS
|
||||
.TP
|
||||
\fBserver=\fR[\fI'1'\fR|\fI'0'\fR]
|
||||
Tells *bitcoin* to accept or not accept JSON-RPC commands.
|
||||
.TP
|
||||
\fBrpcuser=\fR\fI'username'\fR
|
||||
You must set *rpcuser* to secure the JSON-RPC api.
|
||||
.TP
|
||||
\fBrpcpassword=\fR\fI'password'\fR
|
||||
You must set *rpcpassword* to secure the JSON-RPC api.
|
||||
.TP
|
||||
\fBrpctimeout=\fR\fI'30'\fR
|
||||
How many seconds *bitcoin* will wait for a complete RPC HTTP request, after the HTTP connection is established.
|
||||
.TP
|
||||
\fBrpcallowip=\fR\fI'192.168.1.*'\fR
|
||||
By default, only RPC connections from localhost are allowed. Specify as many *rpcallowip=* settings as you like to allow connections from other hosts (and you may use * as a wildcard character).
|
||||
.TP
|
||||
\fBrpcport=\fR\fI'8332'\fR
|
||||
Listen for RPC connections on this TCP port.
|
||||
.TP
|
||||
\fBrpcconnect=\fR\fI'127.0.0.1'\fR
|
||||
You can use *bitcoin* or *bitcoind(1)* to send commands to *bitcoin*/*bitcoind(1)* running on another host using this option.
|
||||
.TP
|
||||
\fBrpcssl=\fR\fI'1'\fR
|
||||
Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate with *bitcoin* '-server' or *bitcoind(1)*. Example of OpenSSL settings used when *rpcssl*='1':
|
||||
.TP
|
||||
\fBrpcsslciphers=\fR\fI'TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH'\fR
|
||||
.TP
|
||||
\fBrpcsslcertificatechainfile=\fR\fI'server.cert'\fR
|
||||
.TP
|
||||
\fBrpcsslprivatekeyfile=\fR\fI'server.pem'\fR
|
||||
.TP
|
||||
.SH MISCELLANEOUS OPTIONS
|
||||
.TP
|
||||
\fBgen=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable attempt to generate bitcoins.
|
||||
.TP
|
||||
\fB4way=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable use SSE instructions to try to generate bitcoins faster.
|
||||
.TP
|
||||
\fBkeypool=\fR\fI'100'\fR
|
||||
Pre-generate this many public/private key pairs, so wallet backups will be valid for both prior transactions and several dozen future transactions.
|
||||
.TP
|
||||
\fBpaytxfee=\fR\fI'0.00'\fR
|
||||
Pay an optional transaction fee every time you send bitcoins. Transactions with fees are more likely than free transactions to be included in generated blocks, so may be validated sooner.
|
||||
.TP
|
||||
\fBallowreceivebyip=\fR\fI'1'\fR
|
||||
Allow direct connections for the 'pay via IP address' feature.
|
||||
.TP
|
||||
.SH USER INTERFACE OPTIONS
|
||||
.TP
|
||||
\fBmin=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable start bitcoind minimized.
|
||||
.TP
|
||||
\fBminimizetotray=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable minimize to the system tray.
|
||||
.SH "SEE ALSO"
|
||||
bitcoind(1)
|
||||
.SH AUTHOR
|
||||
This manual page was written by Micah Anderson <micah@debian.org> for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation.
|
||||
|
||||
On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
|
||||
|
||||
209
contrib/debian/manpages/bitcoind.1
Normal file
209
contrib/debian/manpages/bitcoind.1
Normal file
@@ -0,0 +1,209 @@
|
||||
.TH BITCOIND "1" "January 2011" "bitcoind 3.19"
|
||||
.SH NAME
|
||||
bitcoind \- peer-to-peer network based digital currency
|
||||
.SH SYNOPSIS
|
||||
bitcoin [options] <command> [params]
|
||||
.TP
|
||||
bitcoin [options] help <command> - Get help for a command
|
||||
.SH DESCRIPTION
|
||||
This manual page documents the bitcoind program. Bitcoin is a peer-to-peer digital currency. Peer-to-peer (P2P) means that there is no central authority to issue new money or keep track of transactions. Instead, these tasks are managed collectively by the nodes of the network. Advantages:
|
||||
|
||||
Bitcoins can be sent easily through the Internet, without having to trust middlemen. Transactions are designed to be irreversible. Be safe from instability caused by fractional reserve banking and central banks. The limited inflation of the Bitcoin system’s money supply is distributed evenly (by CPU power) throughout the network, not monopolized by banks.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-conf=\fR<file>
|
||||
Specify configuration file (default: bitcoin.conf)
|
||||
.TP
|
||||
\fB\-gen\fR
|
||||
Generate coins
|
||||
.TP
|
||||
\fB\-gen\fR=\fI0\fR
|
||||
Don't generate coins
|
||||
.TP
|
||||
\fB\-min\fR
|
||||
Start minimized
|
||||
.TP
|
||||
\fB\-datadir=\fR<dir>
|
||||
Specify data directory
|
||||
.TP
|
||||
\fB\-proxy=\fR<ip:port>
|
||||
Connect through socks4 proxy
|
||||
.TP
|
||||
\fB\-addnode=\fR<ip>
|
||||
Add a node to connect to
|
||||
.TP
|
||||
\fB\-connect=\fR<ip>
|
||||
Connect only to the specified node
|
||||
.TP
|
||||
\fB\-paytxfee=\fR<amt>
|
||||
Fee per KB to add to transactions you send
|
||||
.TP
|
||||
\fB\-server\fR
|
||||
Accept command line and JSON\-RPC commands
|
||||
.TP
|
||||
\fB\-daemon\fR
|
||||
Run in the background as a daemon and accept commands
|
||||
.TP
|
||||
\fB\-testnet\fR
|
||||
Use the test network
|
||||
.TP
|
||||
\fB\-rpcuser=\fR<user>
|
||||
Username for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcpassword=\fR<pw>
|
||||
Password for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcport=\fR<port>
|
||||
Listen for JSON\-RPC connections on <port>
|
||||
.TP
|
||||
\fB\-rpcallowip=\fR<ip>
|
||||
Allow JSON\-RPC connections from specified IP address
|
||||
.TP
|
||||
\fB\-rpcconnect=\fR<ip>
|
||||
Send commands to node running on <ip>
|
||||
.PP
|
||||
SSL options: (see the Bitcoin Wiki for SSL setup instructions)
|
||||
.TP
|
||||
\fB\-rpcssl\fR=\fI1\fR
|
||||
Use OpenSSL (https) for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcsslcertificatchainfile=\fR<file.cert>
|
||||
Server certificate file (default: server.cert)
|
||||
.TP
|
||||
\fB\-rpcsslprivatekeyfile=\fR<file.pem>
|
||||
Server private key (default: server.pem)
|
||||
.TP
|
||||
\fB\-rpcsslciphers=\fR<ciphers>
|
||||
Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)
|
||||
.TP
|
||||
\-?
|
||||
This help message
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
\fBbackupwallet 'destination'\fR
|
||||
Safely copies *wallet.dat* to 'destination', which can be a directory or a path with filename.
|
||||
.TP
|
||||
\fBgetaccount 'bitcoinaddress'\fR
|
||||
Returns the account associated with the given address.
|
||||
.TP
|
||||
\fBsetaccount 'bitcoinaddress' ['account']\fR
|
||||
Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account'].
|
||||
.TP
|
||||
\fBgetaccountaddress 'account'\fR
|
||||
Returns a new bitcoin address for 'account'.
|
||||
.TP
|
||||
\fBgetaddressesbyaccount 'account'\fR
|
||||
Returns the list of addresses associated with the given 'account'.
|
||||
.TP
|
||||
\fBgetbalance 'account'\fR
|
||||
Returns the server's available balance, or the balance for 'account'.
|
||||
.TP
|
||||
\fBgetblockcount\fR
|
||||
Returns the number of blocks in the longest block chain.
|
||||
.TP
|
||||
\fBgetblocknumber\fR
|
||||
Returns the block number of the latest block in the longest block chain.
|
||||
.TP
|
||||
\fBgetconnectioncount\fR
|
||||
Returns the number of connections to other nodes.
|
||||
.TP
|
||||
\fBgetdifficulty\fR
|
||||
Returns the proof-of-work difficulty as a multiple of the minimum difficulty.
|
||||
.TP
|
||||
\fBgetgenerate\fR
|
||||
Returns boolean true if server is trying to generate bitcoins, false otherwise.
|
||||
.TP
|
||||
\fBsetgenerate 'generate' ['genproclimit']\fR
|
||||
Generation is limited to ['genproclimit'] processors, -1 is unlimited.
|
||||
.TP
|
||||
\fBgethashespersec\fR
|
||||
Returns a recent hashes per second performance measurement while generating.
|
||||
.TP
|
||||
\fBgetinfo\fR
|
||||
Returns an object containing server information.
|
||||
.TP
|
||||
\fBgetnewaddress 'account'\fR
|
||||
Returns a new bitcoin address for receiving payments. If 'account' is specified (recommended), it is added to the address book so payments received with the address will be credited to 'account'.
|
||||
.TP
|
||||
\fBgetreceivedbyaccount 'account' ['minconf=1']\fR
|
||||
Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations.
|
||||
.TP
|
||||
\fBgetreceivedbyaddress 'bitcoinaddress' ['minconf=1']\fR
|
||||
Returns the total amount received by 'bitcoinaddress' in transactions with at least ['minconf'] confirmations.
|
||||
.TP
|
||||
\fBgettransaction 'txid'\fR
|
||||
Returns information about a specific transaction, given hexadecimal transaction ID.
|
||||
.TP
|
||||
\fBgetwork 'data'\fR
|
||||
If 'data' is specified, tries to solve the block and returns true if it was successful. If 'data' is not specified, returns formatted hash 'data' to work on:
|
||||
|
||||
"midstate" : precomputed hash state after hashing the first half of the data.
|
||||
"data" : block data.
|
||||
"hash1" : formatted hash buffer for second hash.
|
||||
"target" : little endian hash target.
|
||||
.TP
|
||||
\fBhelp 'command'\fR
|
||||
List commands, or get help for a command.
|
||||
.TP
|
||||
\fBlistaccounts ['minconf=1']\fR
|
||||
List accounts and their current balances.
|
||||
*note: requires bitcoin 0.3.20 or later.
|
||||
.TP
|
||||
\fBlistreceivedbyaccount ['minconf=1'] ['includeempty=false']\fR
|
||||
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
|
||||
|
||||
"account" : the account of the receiving address.
|
||||
"amount" : total amount received by the address.
|
||||
"confirmations" : number of confirmations of the most recent transaction included.
|
||||
.TP
|
||||
\fBlistreceivedbyaddress ['minconf=1'] ['includeempty=false']\fR
|
||||
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
|
||||
|
||||
"address" : receiving address.
|
||||
"account" : the account of the receiving address.
|
||||
"amount" : total amount received by the address.
|
||||
"confirmations" : number of confirmations of the most recent transaction included.
|
||||
.TP
|
||||
\fBlisttransactions 'account' ['count=10']\fR
|
||||
Returns a list of the last ['count'] transactions for 'account' - for all accounts if 'account' is not specified or is "*". Each entry in the list may contain:
|
||||
|
||||
"category" : will be generate, send, receive, or move.
|
||||
"amount" : amount of transaction.
|
||||
"fee" : Fee (if any) paid (only for send transactions).
|
||||
"confirmations" : number of confirmations (only for generate/send/receive).
|
||||
"txid" : transaction ID (only for generate/send/receive).
|
||||
"otheraccount" : account funds were moved to or from (only for move).
|
||||
"message" : message associated with transaction (only for send).
|
||||
"to" : message-to associated with transaction (only for send).
|
||||
|
||||
*note: requires bitcoin 0.3.20 or later.
|
||||
.TP
|
||||
\fBmove <'fromaccount'> <'toaccount'> <'amount'> ['minconf=1'] ['comment']\fR
|
||||
Moves funds between accounts.
|
||||
.TP
|
||||
\fBsendfrom* <'account'> <'bitcoinaddress'> <'amount'> ['minconf=1'] ['comment'] ['comment-to']\fR
|
||||
Sends amount from account's balance to 'bitcoinaddress'. This method will fail if there is less than amount bitcoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success.
|
||||
.TP
|
||||
\fBsendtoaddress 'bitcoinaddress' 'amount' ['comment'] ['comment-to']\fR
|
||||
Sends amount from the server's available balance to 'bitcoinaddress'. amount is a real and is rounded to the nearest 0.01. Returns transaction id on success.
|
||||
.TP
|
||||
\fBstop\fR
|
||||
Stops the bitcoin server.
|
||||
.TP
|
||||
\fBvalidateaddress 'bitcoinaddress'\fR
|
||||
Checks that 'bitcoinaddress' looks like a proper bitcoin address. Returns an object containing:
|
||||
|
||||
"isvalid" : true or false.
|
||||
"ismine" : true if the address is in the server's wallet.
|
||||
"address" : bitcoinaddress.
|
||||
|
||||
*note: ismine and address are only returned if the address is valid.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
bitcoin.conf(5)
|
||||
.SH AUTHOR
|
||||
This manual page was written by Micah Anderson <micah@debian.org> for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation.
|
||||
|
||||
On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
|
||||
|
||||
26
contrib/debian/patches/1001_use_system_json-spirit.patch
Normal file
26
contrib/debian/patches/1001_use_system_json-spirit.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
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
|
||||
3
contrib/debian/patches/README
Normal file
3
contrib/debian/patches/README
Normal file
@@ -0,0 +1,3 @@
|
||||
0xxx: Grabbed from upstream development.
|
||||
1xxx: Possibly relevant for upstream adoption.
|
||||
2xxx: Only relevant for official Debian release.
|
||||
1
contrib/debian/patches/series
Normal file
1
contrib/debian/patches/series
Normal file
@@ -0,0 +1 @@
|
||||
#1001_use_system_json-spirit.patch
|
||||
33
contrib/debian/rules
Executable file
33
contrib/debian/rules
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- mode: makefile; coding: utf-8 -*-
|
||||
|
||||
#DEB_MAKE_CHECK_TARGET = test_bitcoin
|
||||
#build/bitcoind::
|
||||
# $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin)
|
||||
|
||||
DEB_INSTALL_EXAMPLES_bitcoind += debian/examples/*
|
||||
DEB_INSTALL_MANPAGES_bitcoind += debian/manpages/*
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_build:
|
||||
cd src; $(MAKE) -f makefile.unix bitcoind
|
||||
$(MAKE)
|
||||
|
||||
override_dh_auto_clean:
|
||||
if [ -f Makefile ]; then $(MAKE) clean; else rm -rf build/; rm -f bitcoin-qt; fi
|
||||
cd src; $(MAKE) -f makefile.unix clean
|
||||
|
||||
override_dh_auto_configure:
|
||||
qmake bitcoin-qt.pro USE_SSL=1 USE_QRCODE=1
|
||||
|
||||
override_dh_auto_test:
|
||||
cd src; $(MAKE) -f makefile.unix test_bitcoin
|
||||
src/test_bitcoin
|
||||
|
||||
# Ensure wrapper is set executable
|
||||
binary-post-install/bitcoind:
|
||||
chmod +x $(cdbs_curdestdir)usr/bin/bitcoind
|
||||
binary-post-install/bitcoin-qt:
|
||||
chmod +x $(cdbs_curdestdir)usr/bin/bitcoin-qt
|
||||
1
contrib/debian/source/format
Normal file
1
contrib/debian/source/format
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
7
contrib/debian/watch
Normal file
7
contrib/debian/watch
Normal file
@@ -0,0 +1,7 @@
|
||||
# Run the "uscan" command to check for upstream updates and more.
|
||||
version=3
|
||||
# use qa.debian.org redirector; see man uscan
|
||||
opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/;s/\-src//,dversionmangle=s/~dfsg\d*// \
|
||||
http://sf.net/bitcoin/bitcoin-(\d.*)-linux\.tar\.gz debian
|
||||
opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/,dversionmangle=s/~dfsg\d*// \
|
||||
http://githubredir.debian.net/github/bitcoin/bitcoin v(.*).tar.gz
|
||||
71
contrib/gitian-descriptors/deps-win32.yml
Normal file
71
contrib/gitian-descriptors/deps-win32.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: "bitcoin-deps"
|
||||
suites:
|
||||
- "lucid"
|
||||
architectures:
|
||||
- "i386"
|
||||
packages:
|
||||
- "mingw32"
|
||||
- "git-core"
|
||||
- "zip"
|
||||
- "faketime"
|
||||
- "wine"
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes: []
|
||||
files:
|
||||
- "openssl-1.0.0e.tar.gz"
|
||||
- "db-4.8.30.NC.tar.gz"
|
||||
- "miniupnpc-1.6.tar.gz"
|
||||
- "zlib-1.2.6.tar.gz"
|
||||
- "libpng-1.5.9.tar.gz"
|
||||
- "qrencode-3.2.0.tar.bz2"
|
||||
script: |
|
||||
#
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
#
|
||||
tar xzf openssl-1.0.0e.tar.gz
|
||||
cd openssl-1.0.0e
|
||||
./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
|
||||
make
|
||||
cd ..
|
||||
#
|
||||
tar xzf db-4.8.30.NC.tar.gz
|
||||
cd db-4.8.30.NC/build_unix
|
||||
../dist/configure --enable-mingw --enable-cxx --host=i586-mingw32msvc CFLAGS="-I/usr/i586-mingw32msvc/include"
|
||||
make $MAKEOPTS
|
||||
cd ../..
|
||||
#
|
||||
tar xzf miniupnpc-1.6.tar.gz
|
||||
cd miniupnpc-1.6
|
||||
sed 's/dllwrap -k --driver-name gcc/$(DLLWRAP) -k --driver-name $(CC)/' -i Makefile.mingw
|
||||
sed 's|wingenminiupnpcstrings $< $@|./wingenminiupnpcstrings $< $@|' -i Makefile.mingw
|
||||
make -f Makefile.mingw DLLWRAP=i586-mingw32msvc-dllwrap CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar
|
||||
cd ..
|
||||
mv miniupnpc-1.6 miniupnpc
|
||||
#
|
||||
tar xzf zlib-1.2.6.tar.gz
|
||||
cd zlib-1.2.6
|
||||
make -f win32/Makefile.gcc PREFIX=i586-mingw32msvc- $MAKEOPTS
|
||||
cd ..
|
||||
#
|
||||
tar xzf libpng-1.5.9.tar.gz
|
||||
cd libpng-1.5.9
|
||||
./configure -disable-shared CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld LDFLAGS="-L../zlib-1.2.6/" CFLAGS="-I../zlib-1.2.6/"
|
||||
make $MAKEOPTS
|
||||
cd ..
|
||||
#
|
||||
tar xjf qrencode-3.2.0.tar.bz2
|
||||
cd qrencode-3.2.0
|
||||
./configure CC=i586-mingw32msvc-cc AR=i586-mingw32msvc-ar STRIP=i586-mingw32msvc-strip RANLIB=i586-mingw32msvc-ranlib OBJDUMP=i586-mingw32msvc-objdump LD=i586-mingw32msvc-ld png_LIBS="../libpng-1.5.9/.libs/libpng15.a ../zlib-1.2.6/libz.a" png_CFLAGS="-I../libpng-1.5.9"
|
||||
make $MAKEOPTS
|
||||
cd ..
|
||||
#
|
||||
zip -r $OUTDIR/bitcoin-deps-0.0.3.zip \
|
||||
$(ls qrencode-*/{qrencode.h,.libs/libqrencode.{,l}a} | sort) \
|
||||
$(ls db-*/build_unix/{libdb_cxx.a,db.h,db_cxx.h,libdb.a,.libs/libdb_cxx-?.?.a} | sort) \
|
||||
$(find openssl-* -name '*.a' -o -name '*.h' | sort) \
|
||||
$(find miniupnpc -name '*.h' -o -name 'libminiupnpc.a' | sort)
|
||||
# Kill wine processes as gitian won't figure out we are done otherwise
|
||||
killall wineserver services.exe explorer.exe winedevice.exe
|
||||
@@ -10,7 +10,6 @@ packages:
|
||||
- "unzip"
|
||||
- "nsis"
|
||||
- "faketime"
|
||||
- "wine"
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
@@ -18,9 +17,7 @@ remotes:
|
||||
files:
|
||||
- "qt-win32-4.7.4-gitian.zip"
|
||||
- "boost-win32-1.47.0-gitian.zip"
|
||||
- "openssl-1.0.0e.tar.gz"
|
||||
- "db-4.8.30.NC.tar.gz"
|
||||
- "miniupnpc-1.6.tar.gz"
|
||||
- "bitcoin-deps-0.0.3.zip"
|
||||
script: |
|
||||
#
|
||||
mkdir $HOME/qt
|
||||
@@ -42,25 +39,9 @@ script: |
|
||||
mv include/boost .
|
||||
cd ..
|
||||
#
|
||||
tar xzf openssl-1.0.0e.tar.gz
|
||||
cd openssl-1.0.0e
|
||||
./Configure --cross-compile-prefix=i586-mingw32msvc- mingw
|
||||
make
|
||||
cd ..
|
||||
unzip bitcoin-deps-0.0.3.zip
|
||||
#
|
||||
tar xzf db-4.8.30.NC.tar.gz
|
||||
cd db-4.8.30.NC/build_unix
|
||||
../dist/configure --enable-mingw --enable-cxx --host=i586-mingw32msvc CFLAGS="-I/usr/i586-mingw32msvc/include"
|
||||
make $MAKEOPTS
|
||||
cd ../..
|
||||
#
|
||||
tar xzf miniupnpc-1.6.tar.gz
|
||||
cd miniupnpc-1.6
|
||||
sed 's/dllwrap -k --driver-name gcc/$(DLLWRAP) -k --driver-name $(CC)/' -i Makefile.mingw
|
||||
sed 's|wingenminiupnpcstrings $< $@|./wingenminiupnpcstrings $< $@|' -i Makefile.mingw
|
||||
make -f Makefile.mingw DLLWRAP=i586-mingw32msvc-dllwrap CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar
|
||||
cd ..
|
||||
mv miniupnpc-1.6 miniupnpc
|
||||
find -type f | xargs touch --date="$REFERENCE_DATETIME"
|
||||
#
|
||||
cd bitcoin
|
||||
mkdir -p $OUTDIR/src
|
||||
@@ -71,7 +52,7 @@ script: |
|
||||
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.0e OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.0e/include INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin
|
||||
$HOME/qt/src/bin/qmake -spec unsupported/win32-g++-cross USE_SSL=1 MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/boost_1_47_0/stage/lib BOOST_INCLUDE_PATH=$HOME/build/boost_1_47_0 BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.0e OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.0e/include QRENCODE_LIB_PATH=$HOME/build/qrencode-3.2.0/.libs QRENCODE_INCLUDE_PATH=$HOME/build/qrencode-3.2.0 USE_QRCODE=1 INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin QMAKE_LFLAGS=-frandom-seed=bitcoin
|
||||
make $MAKEOPTS
|
||||
cp release/bitcoin-qt.exe $OUTDIR/
|
||||
#
|
||||
@@ -80,7 +61,7 @@ script: |
|
||||
export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
|
||||
export FAKETIME=$REFERENCE_DATETIME
|
||||
export TZ=UTC
|
||||
make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_UPNP=0
|
||||
make -f makefile.linux-mingw $MAKEOPTS DEPSDIR=$HOME/build bitcoind.exe USE_SSL=1 USE_UPNP=0
|
||||
i586-mingw32msvc-strip bitcoind.exe
|
||||
makensis ../share/setup.nsi
|
||||
cp ../share/bitcoin-*-win32-setup.exe $OUTDIR/
|
||||
|
||||
@@ -16,12 +16,15 @@ packages:
|
||||
- "libssl-dev"
|
||||
- "git-core"
|
||||
- "unzip"
|
||||
- "pkg-config"
|
||||
- "libpng12-dev"
|
||||
reference_datetime: "2011-01-30 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
"dir": "bitcoin"
|
||||
files:
|
||||
- "miniupnpc-1.6.tar.gz"
|
||||
- "qrencode-3.2.0.tar.bz2"
|
||||
script: |
|
||||
INSTDIR="$HOME/install"
|
||||
export LIBRARY_PATH="$INSTDIR/lib"
|
||||
@@ -31,6 +34,12 @@ script: |
|
||||
INSTALLPREFIX=$INSTDIR make $MAKEOPTS install
|
||||
cd ..
|
||||
#
|
||||
tar xjf qrencode-3.2.0.tar.bz2
|
||||
cd qrencode-3.2.0
|
||||
./configure --prefix=$INSTDIR --enable-static --disable-shared
|
||||
make $MAKEOPTS install
|
||||
cd ..
|
||||
#
|
||||
cd bitcoin
|
||||
mkdir -p $OUTDIR/src
|
||||
cp -a . $OUTDIR/src
|
||||
@@ -39,10 +48,10 @@ script: |
|
||||
cp $OUTDIR/src/COPYING $OUTDIR
|
||||
cd src
|
||||
sed 's/$(DEBUGFLAGS)//' -i makefile.unix
|
||||
make -f makefile.unix STATIC=1 DEFS="-I$INSTDIR/include -L$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0
|
||||
make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$INSTDIR/include" OPENSSL_LIB_PATH="$INSTDIR/lib" $MAKEOPTS bitcoind USE_UPNP=0 USE_SSL=1
|
||||
mkdir -p $OUTDIR/bin/$GBUILD_BITS
|
||||
install -s bitcoind $OUTDIR/bin/$GBUILD_BITS
|
||||
cd ..
|
||||
qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" RELEASE=1
|
||||
qmake INCLUDEPATH="$INSTDIR/include" LIBS="-L$INSTDIR/lib" RELEASE=1 USE_SSL=1 USE_QRCODE=1
|
||||
make $MAKEOPTS
|
||||
install bitcoin-qt $OUTDIR/bin/$GBUILD_BITS
|
||||
|
||||
28
contrib/gitian-downloader/laanwj-key.pgp
Normal file
28
contrib/gitian-downloader/laanwj-key.pgp
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: SKS 1.1.0
|
||||
|
||||
mQENBE5UtMEBCADOUz2i9l/D8xYINCmfUDnxi+DXvX5LmZ39ZdvsoE+ugO0SRRGdIHEFO2is
|
||||
0xezX50wXu9aneb+tEqM0BuiLo6VxaXpxrkxHpr6c4jf37SkE/H0qsi/txEUp7337y3+4HMG
|
||||
lUjiuh802I72p1qusjsKBnmnnR0rwNouTcoDmGUDh7jpKCtzFv+2TR2dRthJn7vmmjq3+bG6
|
||||
PYfqoFY1yHrAGT1lrDBULZsQ/NBLI2+J4oo2LYv3GCq8GNnzrovqvTvui50VSROhLrOe58o2
|
||||
shE+sjQShAy5wYkPt1R1fQnpfx+5vf+TPnkxVwRb3h5GhCp0YL8XC/BXsd5vM4KlVH2rABEB
|
||||
AAG0K1dsYWRpbWlyIEouIHZhbiBkZXIgTGFhbiA8bGFhbndqQGdtYWlsLmNvbT6JATgEEwEC
|
||||
ACIFAk5UtMECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHSBCwEjRsmmy6YIAK09
|
||||
buNXyYQrJBsX16sXxEhx5QPKyF3uHJDFJv66SdnpvIkNoznsaPiRJkbTANop93FZmaGa6wVn
|
||||
zGDiz7jPA8Dpxx5aAYPhIT+zPJAdXWM3wJ/Gio9besRNzniai8Lwi5MZ9R/5yFGBobm6/AcN
|
||||
4sUoqA3NSV2U3I29R0Vwlzo8GVtmyi9ENSi6Oo7AcXNTRt69cxW4nAHkB+amwwDJlcAb31ex
|
||||
bogYXPhScwqQZixRr+JBkKxBjkTXXnQypT4KI5SegYwQVYfyiZmDP7UHKe/u6pSKKbVphLg8
|
||||
xLB5spcXse8/a2+onrbNlw6y8TXiJ++Z54PE7zztWTXf2huakeG5AQ0ETlS0wQEIAMNO3OkP
|
||||
xoPRKWzBLcI7JRITAW+HNaLTq3uN2+4WxA57DEjbL9EDoAv+7wTkDAL40f0T+xiu6GJcLFjw
|
||||
GJZu/tYu7+mErHjrdo+K4suCQt7w5EXCBvOLjhW4tyYMzNx8hP+oqzOW9iEC+6VV91+DYeqt
|
||||
EkJuyVXOI4vzBlTw8uGow8aMMsCq8XVvKUZFTPsjGl197Q5B3A+ZOFCR8xqiqdPjuz6MglVV
|
||||
oFdDNu3EZn8zkGsQlovXoE9ndVeVzx/XMNmsxFaMYsReUs253RIf1FEfgExID0fg2OnyLCjS
|
||||
2iFW1RgajS+/saIkKl+N1iuMzJA7wMAM0plhRueOG0MtZSsAEQEAAYkBHwQYAQIACQUCTlS0
|
||||
wQIbDAAKCRB0gQsBI0bJpmsDB/4waenn2CvSHXyomykfpwf5lMte1V5LvH3z5R2LY+1NopRv
|
||||
LSz3iC39x69XWiTbhywDfgafnGPW4pWBOff2/bu5/A6z1Hnan1vyrRRD/hx1uMJ7S6q+bIvZ
|
||||
iVIg1p0jH6tdIIhwX3cydhdRZHo7e9oSMgOUWsr6Ar59NRo9CENwGPE4U61HXfOnxWdrFWoA
|
||||
XdwZczBeLxmUy6Vo6sKqv+gE4bqrtAM0sY/MsQ9cU95x+52ox/sq44lQMwd3ZBYUP7B1qbHI
|
||||
hZSZuch6MLi5scLPeau0ZvCaljiaMeivP5+x0gWPRs0kI+9sZxInbqvrsJ6oOBJM3xYGhtn1
|
||||
zZ7qmZR7
|
||||
=si/k
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -27,4 +27,8 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
minimum_weight: 120
|
||||
|
||||
@@ -27,4 +27,8 @@ signers:
|
||||
weight: 40
|
||||
name: "Gavin Andresen"
|
||||
key: gavinandresen
|
||||
71A3B16735405025D447E8F274810B012346C9A6
|
||||
weight: 40
|
||||
name: "Wladimir J. van der Laan"
|
||||
key: laanwj
|
||||
minimum_weight: 120
|
||||
|
||||
@@ -17,16 +17,405 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import subprocess, sys, re, os, shutil, os.path
|
||||
import subprocess, sys, re, os, shutil, stat, os.path
|
||||
from time import sleep
|
||||
from argparse import ArgumentParser
|
||||
|
||||
# This is ported from the original macdeployqt with modifications
|
||||
|
||||
class FrameworkInfo(object):
|
||||
def __init__(self):
|
||||
self.frameworkDirectory = ""
|
||||
self.frameworkName = ""
|
||||
self.frameworkPath = ""
|
||||
self.binaryDirectory = ""
|
||||
self.binaryName = ""
|
||||
self.binaryPath = ""
|
||||
self.version = ""
|
||||
self.installName = ""
|
||||
self.deployedInstallName = ""
|
||||
self.sourceFilePath = ""
|
||||
self.destinationDirectory = ""
|
||||
self.sourceResourcesDirectory = ""
|
||||
self.destinationResourcesDirectory = ""
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.__class__ == other.__class__:
|
||||
return self.__dict__ == other.__dict__
|
||||
else:
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return """ Framework name: %s
|
||||
Framework directory: %s
|
||||
Framework path: %s
|
||||
Binary name: %s
|
||||
Binary directory: %s
|
||||
Binary path: %s
|
||||
Version: %s
|
||||
Install name: %s
|
||||
Deployed install name: %s
|
||||
Source file Path: %s
|
||||
Deployed Directory (relative to bundle): %s
|
||||
""" % (self.frameworkName,
|
||||
self.frameworkDirectory,
|
||||
self.frameworkPath,
|
||||
self.binaryName,
|
||||
self.binaryDirectory,
|
||||
self.binaryPath,
|
||||
self.version,
|
||||
self.installName,
|
||||
self.deployedInstallName,
|
||||
self.sourceFilePath,
|
||||
self.destinationDirectory)
|
||||
|
||||
def isDylib(self):
|
||||
return self.frameworkName.endswith(".dylib")
|
||||
|
||||
def isQtFramework(self):
|
||||
if self.isDylib():
|
||||
return self.frameworkName.startswith("libQt")
|
||||
else:
|
||||
return self.frameworkName.startswith("Qt")
|
||||
|
||||
reOLine = re.compile(r'^(.+) \(compatibility version [0-9.]+, current version [0-9.]+\)$')
|
||||
bundleFrameworkDirectory = "Contents/Frameworks"
|
||||
bundleBinaryDirectory = "Contents/MacOS"
|
||||
|
||||
@classmethod
|
||||
def fromOtoolLibraryLine(cls, line):
|
||||
# Note: line must be trimmed
|
||||
if line == "":
|
||||
return None
|
||||
|
||||
# Don't deploy system libraries (exception for libQtuitools and libQtlucene).
|
||||
if line.startswith("/System/Library/") or line.startswith("@executable_path") or (line.startswith("/usr/lib/") and "libQt" not in line):
|
||||
return None
|
||||
|
||||
m = cls.reOLine.match(line)
|
||||
if m is None:
|
||||
raise RuntimeError("otool line could not be parsed: " + line)
|
||||
|
||||
path = m.group(1)
|
||||
|
||||
info = cls()
|
||||
info.sourceFilePath = path
|
||||
info.installName = path
|
||||
|
||||
if path.endswith(".dylib"):
|
||||
dirname, filename = os.path.split(path)
|
||||
info.frameworkName = filename
|
||||
info.frameworkDirectory = dirname
|
||||
info.frameworkPath = path
|
||||
|
||||
info.binaryDirectory = dirname
|
||||
info.binaryName = filename
|
||||
info.binaryPath = path
|
||||
info.version = "-"
|
||||
|
||||
info.installName = path
|
||||
info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName
|
||||
info.sourceFilePath = path
|
||||
info.destinationDirectory = cls.bundleFrameworkDirectory
|
||||
else:
|
||||
parts = path.split("/")
|
||||
i = 0
|
||||
# Search for the .framework directory
|
||||
for part in parts:
|
||||
if part.endswith(".framework"):
|
||||
break
|
||||
i += 1
|
||||
if i == len(parts):
|
||||
raise RuntimeError("Could not find .framework or .dylib in otool line: " + line)
|
||||
|
||||
info.frameworkName = parts[i]
|
||||
info.frameworkDirectory = "/".join(parts[:i])
|
||||
info.frameworkPath = os.path.join(info.frameworkDirectory, info.frameworkName)
|
||||
|
||||
info.binaryName = parts[i+3]
|
||||
info.binaryDirectory = "/".join(parts[i+1:i+3])
|
||||
info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName)
|
||||
info.version = parts[i+2]
|
||||
|
||||
info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath)
|
||||
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
|
||||
|
||||
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
|
||||
info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources")
|
||||
|
||||
return info
|
||||
|
||||
class ApplicationBundleInfo(object):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
appName = os.path.splitext(os.path.basename(path))[0]
|
||||
self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
|
||||
if not os.path.exists(self.binaryPath):
|
||||
raise RuntimeError("Could not find bundle binary for " + path)
|
||||
self.resourcesPath = os.path.join(path, "Contents", "Resources")
|
||||
self.pluginPath = os.path.join(path, "Contents", "PlugIns")
|
||||
|
||||
class DeploymentInfo(object):
|
||||
def __init__(self):
|
||||
self.qtPath = None
|
||||
self.pluginPath = None
|
||||
self.deployedFrameworks = []
|
||||
|
||||
def detectQtPath(self, frameworkDirectory):
|
||||
parentDir = os.path.dirname(frameworkDirectory)
|
||||
if os.path.exists(os.path.join(parentDir, "translations")):
|
||||
# Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x"
|
||||
self.qtPath = parentDir
|
||||
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")
|
||||
|
||||
if self.qtPath is not None:
|
||||
pluginPath = os.path.join(self.qtPath, "plugins")
|
||||
if os.path.exists(pluginPath):
|
||||
self.pluginPath = pluginPath
|
||||
|
||||
def usesFramework(self, name):
|
||||
nameDot = "%s." % name
|
||||
libNameDot = "lib%s." % name
|
||||
for framework in self.deployedFrameworks:
|
||||
if framework.endswith(".framework"):
|
||||
if framework.startswith(nameDot):
|
||||
return True
|
||||
elif framework.endswith(".dylib"):
|
||||
if framework.startswith(libNameDot):
|
||||
return True
|
||||
return False
|
||||
|
||||
def getFrameworks(binaryPath, verbose):
|
||||
if verbose >= 3:
|
||||
print "Inspecting with otool: " + binaryPath
|
||||
otool = subprocess.Popen(["otool", "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
o_stdout, o_stderr = otool.communicate()
|
||||
if otool.returncode != 0:
|
||||
if verbose >= 1:
|
||||
sys.stderr.write(o_stderr)
|
||||
sys.stderr.flush()
|
||||
raise RuntimeError("otool failed with return code %d" % otool.returncode)
|
||||
|
||||
otoolLines = o_stdout.split("\n")
|
||||
otoolLines.pop(0) # First line is the inspected binary
|
||||
if ".framework" in binaryPath or binaryPath.endswith(".dylib"):
|
||||
otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency.
|
||||
|
||||
libraries = []
|
||||
for line in otoolLines:
|
||||
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
|
||||
if info is not None:
|
||||
if verbose >= 3:
|
||||
print "Found framework:"
|
||||
print info
|
||||
libraries.append(info)
|
||||
|
||||
return libraries
|
||||
|
||||
def runInstallNameTool(action, *args):
|
||||
subprocess.check_call(["install_name_tool", "-"+action] + list(args))
|
||||
|
||||
def changeInstallName(oldName, newName, binaryPath, verbose):
|
||||
if verbose >= 3:
|
||||
print "Using install_name_tool:"
|
||||
print " in", binaryPath
|
||||
print " change reference", oldName
|
||||
print " to", newName
|
||||
runInstallNameTool("change", oldName, newName, binaryPath)
|
||||
|
||||
def changeIdentification(id, binaryPath, verbose):
|
||||
if verbose >= 3:
|
||||
print "Using install_name_tool:"
|
||||
print " change identification in", binaryPath
|
||||
print " to", id
|
||||
runInstallNameTool("id", id, binaryPath)
|
||||
|
||||
def runStrip(binaryPath, verbose):
|
||||
if verbose >= 3:
|
||||
print "Using strip:"
|
||||
print " stripped", binaryPath
|
||||
subprocess.check_call(["strip", "-x", binaryPath])
|
||||
|
||||
def copyFramework(framework, path, verbose):
|
||||
fromPath = framework.sourceFilePath
|
||||
toDir = os.path.join(path, framework.destinationDirectory)
|
||||
toPath = os.path.join(toDir, framework.binaryName)
|
||||
|
||||
if not os.path.exists(fromPath):
|
||||
raise RuntimeError("No file at " + fromPath)
|
||||
|
||||
if os.path.exists(toPath):
|
||||
return None # Already there
|
||||
|
||||
if not os.path.exists(toDir):
|
||||
os.makedirs(toDir)
|
||||
|
||||
shutil.copy2(fromPath, toPath)
|
||||
if verbose >= 3:
|
||||
print "Copied:", fromPath
|
||||
print " to:", toPath
|
||||
|
||||
permissions = os.stat(toPath)
|
||||
if not permissions.st_mode & stat.S_IWRITE:
|
||||
os.chmod(toPath, permissions.st_mode | stat.S_IWRITE)
|
||||
|
||||
if not framework.isDylib(): # Copy resources for real frameworks
|
||||
fromResourcesDir = framework.sourceResourcesDirectory
|
||||
if os.path.exists(fromResourcesDir):
|
||||
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
|
||||
shutil.copytree(fromResourcesDir, toResourcesDir)
|
||||
if verbose >= 3:
|
||||
print "Copied resources:", fromResourcesDir
|
||||
print " to:", toResourcesDir
|
||||
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
|
||||
qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib")
|
||||
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
|
||||
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
|
||||
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath)
|
||||
if verbose >= 3:
|
||||
print "Copied for libQtGui:", qtMenuNibSourcePath
|
||||
print " to:", qtMenuNibDestinationPath
|
||||
|
||||
return toPath
|
||||
|
||||
def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploymentInfo=None):
|
||||
if deploymentInfo is None:
|
||||
deploymentInfo = DeploymentInfo()
|
||||
|
||||
while len(frameworks) > 0:
|
||||
framework = frameworks.pop(0)
|
||||
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
|
||||
|
||||
if verbose >= 2:
|
||||
print "Processing", framework.frameworkName, "..."
|
||||
|
||||
# Get the Qt path from one of the Qt frameworks
|
||||
if deploymentInfo.qtPath is None and framework.isQtFramework():
|
||||
deploymentInfo.detectQtPath(framework.frameworkDirectory)
|
||||
|
||||
if framework.installName.startswith("@executable_path"):
|
||||
if verbose >= 2:
|
||||
print framework.frameworkName, "already deployed, skipping."
|
||||
continue
|
||||
|
||||
# install_name_tool the new id into the binary
|
||||
changeInstallName(framework.installName, framework.deployedInstallName, binaryPath, verbose)
|
||||
|
||||
# Copy farmework to app bundle.
|
||||
deployedBinaryPath = copyFramework(framework, bundlePath, verbose)
|
||||
# Skip the rest if already was deployed.
|
||||
if deployedBinaryPath is None:
|
||||
continue
|
||||
|
||||
if strip:
|
||||
runStrip(deployedBinaryPath, verbose)
|
||||
|
||||
# install_name_tool it a new id.
|
||||
changeIdentification(framework.deployedInstallName, deployedBinaryPath, verbose)
|
||||
# Check for framework dependencies
|
||||
dependencies = getFrameworks(deployedBinaryPath, verbose)
|
||||
|
||||
for dependency in dependencies:
|
||||
changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath, verbose)
|
||||
|
||||
# Deploy framework if necessary.
|
||||
if dependency.frameworkName not in deploymentInfo.deployedFrameworks and dependency not in frameworks:
|
||||
frameworks.append(dependency)
|
||||
|
||||
return deploymentInfo
|
||||
|
||||
def deployFrameworksForAppBundle(applicationBundle, strip, verbose):
|
||||
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
|
||||
if len(frameworks) == 0 and verbose >= 1:
|
||||
print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path)
|
||||
return DeploymentInfo()
|
||||
else:
|
||||
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
|
||||
|
||||
def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
|
||||
# Lookup available plugins, exclude unneeded
|
||||
plugins = []
|
||||
for dirpath, dirnames, filenames in os.walk(deploymentInfo.pluginPath):
|
||||
pluginDirectory = os.path.relpath(dirpath, deploymentInfo.pluginPath)
|
||||
if pluginDirectory == "designer":
|
||||
# Skip designer plugins
|
||||
continue
|
||||
elif pluginDirectory == "phonon":
|
||||
# Deploy the phonon plugins only if phonon is in use
|
||||
if not deploymentInfo.usesFramework("phonon"):
|
||||
continue
|
||||
elif pluginDirectory == "sqldrivers":
|
||||
# Deploy the sql plugins only if QtSql is in use
|
||||
if not deploymentInfo.usesFramework("QtSql"):
|
||||
continue
|
||||
elif pluginDirectory == "script":
|
||||
# Deploy the script plugins only if QtScript is in use
|
||||
if not deploymentInfo.usesFramework("QtScript"):
|
||||
continue
|
||||
elif pluginDirectory == "qmltooling":
|
||||
# Deploy the qml plugins only if QtDeclarative is in use
|
||||
if not deploymentInfo.usesFramework("QtDeclarative"):
|
||||
continue
|
||||
elif pluginDirectory == "bearer":
|
||||
# Deploy the bearer plugins only if QtNetwork is in use
|
||||
if not deploymentInfo.usesFramework("QtNetwork"):
|
||||
continue
|
||||
|
||||
for pluginName in filenames:
|
||||
pluginPath = os.path.join(pluginDirectory, pluginName)
|
||||
if pluginName.endswith("_debug.dylib"):
|
||||
# Skip debug plugins
|
||||
continue
|
||||
elif pluginPath == "imageformats/libqsvg.dylib" or pluginPath == "iconengines/libqsvgicon.dylib":
|
||||
# Deploy the svg plugins only if QtSvg is in use
|
||||
if not deploymentInfo.usesFramework("QtSvg"):
|
||||
continue
|
||||
elif pluginPath == "accessible/libqtaccessiblecompatwidgets.dylib":
|
||||
# Deploy accessibility for Qt3Support only if the Qt3Support is in use
|
||||
if not deploymentInfo.usesFramework("Qt3Support"):
|
||||
continue
|
||||
elif pluginPath == "graphicssystems/libqglgraphicssystem.dylib":
|
||||
# Deploy the opengl graphicssystem plugin only if QtOpenGL is in use
|
||||
if not deploymentInfo.usesFramework("QtOpenGL"):
|
||||
continue
|
||||
|
||||
plugins.append((pluginDirectory, pluginName))
|
||||
|
||||
for pluginDirectory, pluginName in plugins:
|
||||
if verbose >= 2:
|
||||
print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..."
|
||||
|
||||
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
|
||||
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
|
||||
if not os.path.exists(destinationDirectory):
|
||||
os.makedirs(destinationDirectory)
|
||||
|
||||
destinationPath = os.path.join(destinationDirectory, pluginName)
|
||||
shutil.copy2(sourcePath, destinationPath)
|
||||
if verbose >= 3:
|
||||
print "Copied:", sourcePath
|
||||
print " to:", destinationPath
|
||||
|
||||
if strip:
|
||||
runStrip(destinationPath, verbose)
|
||||
|
||||
dependencies = getFrameworks(destinationPath, verbose)
|
||||
|
||||
for dependency in dependencies:
|
||||
changeInstallName(dependency.installName, dependency.deployedInstallName, destinationPath, verbose)
|
||||
|
||||
# Deploy framework if necessary.
|
||||
if dependency.frameworkName not in deploymentInfo.deployedFrameworks:
|
||||
deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo)
|
||||
|
||||
qt_conf="""[Paths]
|
||||
translations=Resources
|
||||
plugins=PlugIns
|
||||
"""
|
||||
|
||||
ap = ArgumentParser(description="""Front-end to macdeployqt with some additional functions.
|
||||
ap = ArgumentParser(description="""Improved version of macdeployqt.
|
||||
|
||||
Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file.
|
||||
Note, that the "dist" folder will be deleted before deploying on each run.
|
||||
@@ -69,22 +458,6 @@ for p in config.add_resources:
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
if len(config.add_qt_tr) == 0:
|
||||
add_qt_tr = []
|
||||
else:
|
||||
qt_tr_dir = os.path.join(os.getenv("QTDIR", ""), "translations")
|
||||
add_qt_tr = ["qt_%s.qm" % lng for lng in config.add_qt_tr[0].split(",")]
|
||||
for lng_file in add_qt_tr:
|
||||
p = os.path.join(qt_tr_dir, lng_file)
|
||||
if verbose >= 3:
|
||||
print "Checking for \"%s\"..." % p
|
||||
if not os.path.exists(p):
|
||||
if verbose >= 1:
|
||||
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file))
|
||||
sys.exit(1)
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
if len(config.fancy) == 1:
|
||||
if verbose >= 3:
|
||||
print "Fancy: Importing plistlib..."
|
||||
@@ -160,7 +533,6 @@ if os.path.exists("dist"):
|
||||
# ------------------------------------------------
|
||||
|
||||
target = os.path.join("dist", app_bundle)
|
||||
target_res = os.path.join(target, "Contents", "Resources")
|
||||
|
||||
if verbose >= 2:
|
||||
print "+ Copying source bundle +"
|
||||
@@ -170,27 +542,61 @@ if verbose >= 3:
|
||||
os.mkdir("dist")
|
||||
shutil.copytree(app_bundle, target)
|
||||
|
||||
applicationBundle = ApplicationBundleInfo(target)
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
macdeployqt_args = ["macdeployqt", target, "-verbose=%d" % verbose]
|
||||
if not config.plugins:
|
||||
macdeployqt_args.append("-no-plugins")
|
||||
if not config.strip:
|
||||
macdeployqt_args.append("-no-strip")
|
||||
|
||||
if verbose >= 2:
|
||||
print "+ Running macdeployqt +"
|
||||
print "+ Deploying frameworks +"
|
||||
|
||||
ret = subprocess.call(macdeployqt_args)
|
||||
if ret != 0:
|
||||
try:
|
||||
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
|
||||
if deploymentInfo.qtPath is None:
|
||||
deploymentInfo.qtPath = os.getenv("QTDIR", None)
|
||||
if deploymentInfo.qtPath is None:
|
||||
if verbose >= 1:
|
||||
sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
|
||||
config.plugins = False
|
||||
except RuntimeError as e:
|
||||
if verbose >= 1:
|
||||
sys.stderr.write("Error: %s\n" % str(e))
|
||||
sys.exit(ret)
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
if config.plugins:
|
||||
if verbose >= 2:
|
||||
print "+ Deploying plugins +"
|
||||
|
||||
try:
|
||||
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
|
||||
except RuntimeError as e:
|
||||
if verbose >= 1:
|
||||
sys.stderr.write("Error: %s\n" % str(e))
|
||||
sys.exit(ret)
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
if len(config.add_qt_tr) == 0:
|
||||
add_qt_tr = []
|
||||
else:
|
||||
qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations")
|
||||
add_qt_tr = ["qt_%s.qm" % lng for lng in config.add_qt_tr[0].split(",")]
|
||||
for lng_file in add_qt_tr:
|
||||
p = os.path.join(qt_tr_dir, lng_file)
|
||||
if verbose >= 3:
|
||||
print "Checking for \"%s\"..." % p
|
||||
if not os.path.exists(p):
|
||||
if verbose >= 1:
|
||||
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file))
|
||||
sys.exit(1)
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
if verbose >= 2:
|
||||
print "+ Installing qt.conf +"
|
||||
|
||||
f = open(os.path.join(target_res, "qt.conf"), "wb")
|
||||
f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb")
|
||||
f.write(qt_conf)
|
||||
f.close()
|
||||
|
||||
@@ -201,8 +607,8 @@ if len(add_qt_tr) > 0 and verbose >= 2:
|
||||
|
||||
for lng_file in add_qt_tr:
|
||||
if verbose >= 3:
|
||||
print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(target_res, lng_file)
|
||||
shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(target_res, lng_file))
|
||||
print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file)
|
||||
shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file))
|
||||
|
||||
# ------------------------------------------------
|
||||
|
||||
@@ -210,7 +616,7 @@ if len(config.add_resources) > 0 and verbose >= 2:
|
||||
print "+ Adding additional resources +"
|
||||
|
||||
for p in config.add_resources:
|
||||
t = os.path.join(target_res, os.path.basename(p))
|
||||
t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p))
|
||||
if verbose >= 3:
|
||||
print p, "->", t
|
||||
if os.path.isdir(p):
|
||||
|
||||
@@ -6,7 +6,7 @@ You will need the appscript package for the fancy disk image creation to work.
|
||||
Install it by invoking "sudo easy_install appscript".
|
||||
|
||||
Ths script should be invoked in the target directory like this:
|
||||
$source_dir/contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr de,es,ru -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist
|
||||
$source_dir/contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist -verbose 2
|
||||
|
||||
During the process, the disk image window will pop up briefly where the fancy
|
||||
settings are applied. This is normal, please do not interfere.
|
||||
@@ -19,7 +19,7 @@ Fill in the following.
|
||||
Enable custom process step: [x]
|
||||
Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus
|
||||
Working directory: %{buildDir}
|
||||
Command arguments: Bitcoin-Qt.app -add-qt-tr de,ru -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist
|
||||
Command arguments: Bitcoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist -verbose 2
|
||||
|
||||
After that you can start the deployment process through the menu with
|
||||
Build -> Deploy Project "bitcoin-qt"
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4
|
||||
# $Id$
|
||||
|
||||
PortSystem 1.0
|
||||
|
||||
name miniupnpc
|
||||
epoch 2
|
||||
version 1.6
|
||||
revision 2
|
||||
categories net
|
||||
platforms darwin
|
||||
license BSD
|
||||
maintainers singingwolfboy openmaintainer
|
||||
description Lightweight client for UPnP protocol
|
||||
long_description \
|
||||
${description}
|
||||
|
||||
homepage http://miniupnp.free.fr/
|
||||
master_sites http://miniupnp.free.fr/files/download.php?file=${distname}${extract.suffix}&dummy=
|
||||
checksums md5 88055f2d4a061cfd4cfe25a9eae22f67 \
|
||||
sha1 ef8f2edb17f2e7c5b8dc67ee80a65c199d823e0a \
|
||||
rmd160 d86b75b331a3fb5525c71708548f311977c0598f
|
||||
|
||||
use_configure no
|
||||
|
||||
variant universal {}
|
||||
if {[variant_isset universal]} {
|
||||
set archflags ${configure.universal_cflags}
|
||||
} else {
|
||||
set archflags ${configure.cc_archflags}
|
||||
}
|
||||
|
||||
build.args-append CC="${configure.cc} ${archflags}"
|
||||
|
||||
post-patch {
|
||||
reinplace "s|-Wl,-install_name,|-Wl,-install_name,${prefix}/lib/|" ${worksrcpath}/Makefile
|
||||
}
|
||||
|
||||
destroot.destdir PREFIX=${prefix} INSTALLPREFIX=${destroot}${prefix}
|
||||
|
||||
livecheck.type regex
|
||||
livecheck.url http://miniupnp.free.fr/files/
|
||||
livecheck.regex ${name}-(\\d+(\\.\\d{1,4})+)${extract.suffix}
|
||||
22
contrib/qt_translations.py
Executable file
22
contrib/qt_translations.py
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Helpful little script that spits out a comma-separated list of
|
||||
# language codes for Qt icons that should be included
|
||||
# in binary bitcoin distributions
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0])
|
||||
|
||||
d1 = sys.argv[1]
|
||||
d2 = sys.argv[2]
|
||||
|
||||
l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ])
|
||||
l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ])
|
||||
|
||||
print ",".join(sorted(l1.intersection(l2)))
|
||||
|
||||
1752
doc/Doxyfile
Normal file
1752
doc/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
Bitcoin 0.5.0 BETA
|
||||
Bitcoin 0.6.0 BETA
|
||||
|
||||
Copyright (c) 2009-2011 Bitcoin Developers
|
||||
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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Bitcoin 0.5.0 BETA
|
||||
Bitcoin 0.6.0 BETA
|
||||
|
||||
Copyright (c) 2009-2011 Bitcoin Developers
|
||||
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
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
|
||||
src/qt/res/src/*.svg
|
||||
Designer: Wladimir van der Laan
|
||||
License: Creative Commons Attribution
|
||||
License: MIT
|
||||
|
||||
Icon: src/qt/res/icons/send.png
|
||||
Icon Pack: Vista Style Arrow
|
||||
Designer: Icons Land
|
||||
License: Freeware Non-commercial
|
||||
Site: http://findicons.com/icon/231371/right3green
|
||||
Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
|
||||
src/qt/res/icons/history.png, src/qt/res/icons/key.png,
|
||||
src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
|
||||
src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
|
||||
src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png
|
||||
Icon Pack: NUVOLA ICON THEME for KDE 3.x
|
||||
Designer: David Vignoni (david@icon-king.com)
|
||||
ICON KING - www.icon-king.com
|
||||
License: LGPL
|
||||
Site: http://www.icon-king.com/projects/nuvola/
|
||||
|
||||
Icon: src/qt/res/icons/address-book.png
|
||||
Icon Pack: Farm-Fresh Web
|
||||
Designer: FatCow Web Hosting
|
||||
License: Creative Commons Attribution (by)
|
||||
Site: http://findicons.com/icon/163938/book_open
|
||||
|
||||
Icon: src/qt/res/icons/connect*.png, src/qt/res/icons/synced.png, src/qt/res/icons/lock_*.png
|
||||
Icon: src/qt/res/icons/connect*.png
|
||||
Icon Pack: Human-O2
|
||||
Designer: schollidesign
|
||||
License: GNU/GPL
|
||||
@@ -35,24 +34,11 @@ Designer: http://www.everaldo.com
|
||||
Icon Pack: Crystal SVG
|
||||
License: LGPL
|
||||
|
||||
Icon: src/qt/res/icons/receive.png, src/qt/res/icons/history.png,
|
||||
src/qt/res/icons/export.png
|
||||
Designer: Oxygen team
|
||||
Icon Pack: Oxygen
|
||||
License: Creative Common Attribution-ShareAlike 3.0 License or LGPL
|
||||
Site: http://www.oxygen-icons.org/
|
||||
|
||||
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
|
||||
|
||||
Icon: src/qt/res/icons/overview.png
|
||||
Icon Pack: Primo
|
||||
Designer: Jack Cai
|
||||
License: Creative Commons Attribution No Derivatives (by-nd)
|
||||
Site: http://findicons.com/icon/175944/home?id=176221#
|
||||
|
||||
Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng
|
||||
Icon Pack: Kids
|
||||
Designer: Everaldo (Everaldo Coelho)
|
||||
@@ -64,10 +50,3 @@ Designer: Crobbo (forum)
|
||||
Site: https://bitcointalk.org/index.php?topic=32273.0
|
||||
License: Public domain
|
||||
|
||||
Icon: src/qt/res/icons/key.png
|
||||
Designer: VisualPharm (Ivan Boyko)
|
||||
Icon Pack: Must Have
|
||||
Site: http://findicons.com/icon/51009/key?id=51009
|
||||
License: Creative Commons Attribution (by)
|
||||
|
||||
|
||||
|
||||
BIN
doc/bitcoin_logo_doxygen.png
Normal file
BIN
doc/bitcoin_logo_doxygen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2011 Bitcoin Developers
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2011 Bitcoin Developers
|
||||
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
|
||||
@@ -36,12 +36,10 @@ git clone git@github.com:bitcoin/bitcoin.git bitcoin
|
||||
|
||||
3. Install dependencies from MacPorts
|
||||
|
||||
sudo port install boost db48 openssl
|
||||
sudo port install boost db48 openssl miniupnpc
|
||||
|
||||
Install the right version of miniupnpc:
|
||||
pushd bitcoin/contrib/minipupnpc; sudo port install; popd
|
||||
(this will be unnecessary soon, you will just port install miniupnpc
|
||||
along with the rest of the dependencies).
|
||||
Optionally install qrencode (and set USE_QRCODE=1):
|
||||
sudo port install qrencode
|
||||
|
||||
4. Now you should be able to build bitcoind:
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
Copyright (c) 2011 Bitcoin Developers
|
||||
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
|
||||
@@ -23,12 +22,13 @@ the graphical bitcoin.
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Library Purpose Description
|
||||
------- ------- -----------
|
||||
libssl SSL Support Secure communications
|
||||
libdb4.8 Berkeley DB Blockchain & wallet storage
|
||||
libboost Boost C++ Library
|
||||
miniupnpc UPnP Support Optional firewall-jumping support
|
||||
Library Purpose Description
|
||||
------- ------- -----------
|
||||
libssl SSL Support Secure communications
|
||||
libdb4.8 Berkeley DB Blockchain & wallet storage
|
||||
libboost Boost C++ Library
|
||||
miniupnpc UPnP Support Optional firewall-jumping support
|
||||
libqrencode QRCode generation Optional QRCode generation
|
||||
|
||||
miniupnpc may be used for UPnP port mapping. It can be downloaded from
|
||||
http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and
|
||||
@@ -37,6 +37,12 @@ turned off by default. Set USE_UPNP to a different value to control this:
|
||||
USE_UPNP=0 (the default) UPnP support turned off by default at runtime
|
||||
USE_UPNP=1 UPnP support turned on by default at runtime
|
||||
|
||||
libqrencode may be used for QRCode image generation. It can be downloaded
|
||||
from http://fukuchi.org/works/qrencode/index.html.en, or installed via
|
||||
your package manager. Set USE_QRCODE to control this:
|
||||
USE_QRCODE=0 (the default) No QRCode support - libarcode not required
|
||||
USE_QRCODE=1 QRCode support enabled
|
||||
|
||||
Licenses of statically linked libraries:
|
||||
Berkeley DB New BSD license with additional requirement that linked
|
||||
software must be free open source
|
||||
@@ -50,7 +56,6 @@ Versions used in this release:
|
||||
Boost 1.37
|
||||
miniupnpc 1.6
|
||||
|
||||
|
||||
Dependency Build Instructions: Ubuntu & Debian
|
||||
----------------------------------------------
|
||||
sudo apt-get install build-essential
|
||||
@@ -59,6 +64,7 @@ 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
|
||||
|
||||
If using Boost 1.37, append -mt to the boost libraries in the makefile.
|
||||
|
||||
|
||||
@@ -1,39 +1,6 @@
|
||||
Bitcoin-qt: Qt4 GUI for Bitcoin
|
||||
===============================
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
- All functionality of the Wx GUI, including wallet encryption
|
||||
|
||||
- Compatibility with Linux (both GNOME and KDE), MacOSX and Windows
|
||||
|
||||
- Notification on incoming / outgoing transactions (compatible with FreeDesktop and other desktop notification schemes)
|
||||
|
||||
- General interface improvements: Splash screen, tabbed interface
|
||||
|
||||
- Overview page with current balance, unconfirmed balance, and such
|
||||
|
||||
- Better transaction list with status icons, real-time filtering and a context menu
|
||||
|
||||
- Asks for confirmation before sending coins, for your own safety
|
||||
|
||||
- CSV export of transactions and address book (for Excel bookkeeping)
|
||||
|
||||
- Shows alternative icon when connected to testnet, so you never accidentally send real coins during testing
|
||||
|
||||
- Shows a progress bar on initial block download, so that you don't have to wonder how many blocks it needs to download to be up to date
|
||||
|
||||
- Sendmany support, send to multiple recipients at the same time
|
||||
|
||||
- Multiple unit support, can show subdivided bitcoins (uBTC, mBTC) for users that like large numbers
|
||||
|
||||
- Support for English, German, Russian and Dutch languages
|
||||
|
||||
- Address books and transaction table can be sorted by any column
|
||||
|
||||
- Accepts "bitcoin:" URLs from browsers and other sources through drag and drop
|
||||
|
||||
Build instructions
|
||||
===================
|
||||
|
||||
@@ -92,7 +59,7 @@ Mac OS X
|
||||
::
|
||||
|
||||
sudo port selfupdate
|
||||
sudo port install boost db48
|
||||
sudo port install boost db48 miniupnpc
|
||||
|
||||
- Open the .pro file in Qt Creator and build as normal (cmd-B)
|
||||
|
||||
@@ -127,14 +94,6 @@ Set USE_UPNP to a different value to control this:
|
||||
| USE_UPNP=1 | build with UPnP support turned on by default at runtime. |
|
||||
+------------+--------------------------------------------------------------------------+
|
||||
|
||||
Mac OS X users: miniupnpc is currently outdated on MacPorts. An updated Portfile is provided in contrib/miniupnpc within this project.
|
||||
You can execute the following commands in a terminal to install it:
|
||||
|
||||
::
|
||||
|
||||
cd <location of bitcoin-qt>/contrib/miniupnpc
|
||||
sudo port install
|
||||
|
||||
Notification support for recent (k)ubuntu versions
|
||||
---------------------------------------------------
|
||||
|
||||
@@ -145,6 +104,20 @@ FreeDesktop notification interface through DBUS using the following qmake option
|
||||
|
||||
qmake "USE_DBUS=1"
|
||||
|
||||
Generation of QR codes
|
||||
-----------------------
|
||||
|
||||
libqrencode may be used to generate QRCode images for payment requests.
|
||||
It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Pass the USE_QRCODE
|
||||
flag to qmake to control this:
|
||||
|
||||
+--------------+--------------------------------------------------------------------------+
|
||||
| USE_QRCODE=0 | (the default) No QRCode support - libarcode not required |
|
||||
+--------------+--------------------------------------------------------------------------+
|
||||
| USE_QRCODE=1 | QRCode support enabled |
|
||||
+--------------+--------------------------------------------------------------------------+
|
||||
|
||||
|
||||
Berkely DB version warning
|
||||
==========================
|
||||
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
* update translations (ping tcatm on IRC for now)
|
||||
|
||||
* update (commit) version in sources
|
||||
src/serialize.h
|
||||
bitcoin-qt.pro
|
||||
src/main.h (CLIENT_VERSION : PROTOCOL_VERSION in serialize.h is updated only on protocol changes)
|
||||
share/setup.nsi
|
||||
|
||||
* update (commit) version in OSX app bundle
|
||||
contrib/Bitcoin.app/Contents/Info.plist
|
||||
|
||||
* CFBundleShortVersionString should have value like 0.5.0
|
||||
* CFBundleVersion should have value like 500
|
||||
doc/README*
|
||||
|
||||
* tag version in git
|
||||
|
||||
git tag -a v0.5.0
|
||||
git tag -a v0.5.1
|
||||
|
||||
* write release notes. git shortlog helps a lot:
|
||||
|
||||
git shortlog --no-merges v0.4.0..
|
||||
|
||||
* create source-only archive
|
||||
|
||||
git archive --format=tar --prefix=bitcoin-0.5.0/ HEAD | \
|
||||
gzip -9c > ~/tmp/bitcoin-0.5.0-src.tar.gz
|
||||
git shortlog --no-merges v0.5.0..
|
||||
|
||||
* perform gitian builds
|
||||
|
||||
* From a directory containing the bitcoin source, gitian-builder and gitian.sigs
|
||||
export SIGNER=(your gitian key, ie bluematt, sipa, etc)
|
||||
export VERSION=0.5.0
|
||||
export VERSION=0.5.1
|
||||
cd ./gitian-builder
|
||||
|
||||
* Fetch and build inputs:
|
||||
@@ -33,6 +26,9 @@
|
||||
wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz
|
||||
wget 'http://www.openssl.org/source/openssl-1.0.0e.tar.gz'
|
||||
wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
|
||||
wget 'http://zlib.net/zlib-1.2.6.tar.gz'
|
||||
wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.9.tar.gz'
|
||||
wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2'
|
||||
wget 'http://downloads.sourceforge.net/project/boost/boost/1.47.0/boost_1_47_0.tar.bz2'
|
||||
wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.tar.gz'
|
||||
cd ..
|
||||
@@ -40,92 +36,105 @@
|
||||
cp build/out/boost-win32-1.47.0-gitian.zip inputs/
|
||||
./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml
|
||||
cp 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/
|
||||
|
||||
* Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32:
|
||||
./bin/gbuild --commit bitcoin=v$VERSION ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
./bin/gsign --signer $SIGNER --release $VERSION --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
cd build/out
|
||||
zip bitcoin-$VERSION-linux-gitian.zip *
|
||||
mv bitcoin-$VERSION-linux-gitian.zip ../../
|
||||
./bin/gbuild --commit bitcoin=v$VERSION ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
|
||||
./bin/gsign --signer $SIGNER --release $VERSION-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
|
||||
cd build/out
|
||||
zip bitcoin-$VERSION-win32-gitian.zip *
|
||||
mv bitcoin-$VERSION-win32-gitian.zip ../../
|
||||
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
|
||||
pushd build/out
|
||||
zip -r bitcoin-${VERSION}-linux-gitian.zip *
|
||||
mv bitcoin-${VERSION}-linux-gitian.zip ../../
|
||||
popd
|
||||
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
|
||||
./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
|
||||
pushd build/out
|
||||
zip -r bitcoin-${VERSION}-win32-gitian.zip *
|
||||
mv bitcoin-${VERSION}-win32-gitian.zip ../../
|
||||
popd
|
||||
|
||||
Build output expected:
|
||||
1. linux 32-bit and 64-bit binaries + source (bitcoin-$VERSION-linux-gitian.zip)
|
||||
2. windows 32-bit binary, installer + source (bitcoin-$VERSION-win32-gitian.zip)
|
||||
3. Gitian signatures (in gitian.sigs/$VERSION[-win32]/(your gitian key)/
|
||||
1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip)
|
||||
2. windows 32-bit binary, installer + source (bitcoin-${VERSION}-win32-gitian.zip)
|
||||
3. Gitian signatures (in gitian.sigs/${VERSION}[-win32]/(your gitian key)/
|
||||
|
||||
* repackage gitian builds for release as stand-alone zip/tar/installer exe
|
||||
|
||||
* Linux .tar.gz:
|
||||
mkdir bitcoin-$VERSION-linux
|
||||
cd bitcoin-$VERSION-linux
|
||||
unzip bitcoin-$VERSION-linux-gitian.zip
|
||||
cd ..; tar czvf bitcoin-$VERSION-linux.tar.gz bitcoin-$VERSION-linux
|
||||
unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux
|
||||
tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux
|
||||
rm -rf bitcoin-${VERSION}-linux
|
||||
|
||||
* Windows .zip and setup.exe:
|
||||
mkdir bitcoin-$VERSION-win32
|
||||
cd bitcoin-$VERSION-win32
|
||||
unzip bitcoin-$VERSION-win32-gitian.zip
|
||||
mv bitcoin-$VERSION-win32-setup.exe ..
|
||||
cd ..; zip bitcoin-$VERSION-win32.zip bitcoin-$VERSION-win32
|
||||
|
||||
unzip bitcoin-${VERSION}-win32-gitian.zip -d bitcoin-${VERSION}-win32
|
||||
mv bitcoin-${VERSION}-win32/bitcoin-*-setup.exe .
|
||||
zip -r bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win32
|
||||
rm -rf bitcoin-${VERSION}-win32
|
||||
|
||||
* perform Mac build
|
||||
See this blog post for how Gavin set up his build environment and
|
||||
patched macdeployqt to build the OSX release:
|
||||
See this blog post for how Gavin set up his build environment to build the OSX
|
||||
release; note that a patched version of macdeployqt is not needed anymore, as
|
||||
the required functionality and fixes are implemented directly in macdeployqtplus:
|
||||
http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html
|
||||
qmake USE_SSL=1 USE_UPNP=1 bitcoin-qt.pro
|
||||
Gavin also had trouble with the macports py27-appscript package; he
|
||||
ended up installing a version that worked with: /usr/bin/easy_install-2.7 appscript
|
||||
|
||||
qmake RELEASE=1 USE_SSL=1 USE_UPNP=1 USE_QRCODE=1 bitcoin-qt.pro
|
||||
make
|
||||
export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files
|
||||
contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr de,es,ru -dmg -fancy contrib/macdeploy/fancy.plist
|
||||
T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale)
|
||||
python2.7 contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist
|
||||
|
||||
Build output expected:
|
||||
Bitcoin-Qt.dmg
|
||||
|
||||
* upload source and builds to SourceForge
|
||||
* upload builds to SourceForge
|
||||
|
||||
* create SHA1SUMS for builds, and PGP-sign it
|
||||
* create SHA256SUMS for builds, and PGP-sign it
|
||||
|
||||
* update bitcoin.org version
|
||||
|
||||
* update forum version
|
||||
|
||||
* update wiki
|
||||
|
||||
* update wiki download links
|
||||
|
||||
* release gitian-signed gitian archives
|
||||
* Commit your signature to gitian.sigs:
|
||||
pushd gitian.sigs
|
||||
git add ${VERSION}/${SIGNER}
|
||||
git add ${VERSION}-win32/${SIGNER}
|
||||
git commit -a
|
||||
git push # Assuming you can push to the gitian.sigs tree
|
||||
popd
|
||||
|
||||
* Collect enough gitian signatures to meet minimum_weight (see contrib/gitian-downloader/*-download-config)
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
* After 3 or more people have gitian-built, repackage gitian-signed zips:
|
||||
|
||||
* From a directory containing bitcoin source, gitian.sigs and gitian zips
|
||||
export VERSION=0.5.0
|
||||
mkdir bitcoin-$VERSION-linux-gitian; cd bitcoin-$VERSION-linux-gitian
|
||||
unzip ../bitcoin-$VERSION-linux-gitian.zip
|
||||
export VERSION=0.5.1
|
||||
mkdir bitcoin-${VERSION}-linux-gitian
|
||||
pushd bitcoin-${VERSION}-linux-gitian
|
||||
unzip ../bitcoin-${VERSION}-linux-gitian.zip
|
||||
mkdir gitian
|
||||
cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
|
||||
for file in `ls ../gitian.sigs/$VERSION/`; do
|
||||
cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert ./gitian/$file-build.assert
|
||||
cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert.sig ./gitian/$file-build.assert.sig
|
||||
for signer in $(ls ../gitian.sigs/${VERSION}/); do
|
||||
cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
|
||||
cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
|
||||
done
|
||||
zip bitcoin-$VERSION-linux-gitian.zip *
|
||||
cp bitcoin-$VERSION-linux-gitian.zip ../
|
||||
cd ..
|
||||
mkdir bitcoin-$VERSION-linux-gitian; cd bitcoin-$VERSION-linux-gitian
|
||||
unzip ../bitcoin-$VERSION-linux-gitian.zip
|
||||
zip -r bitcoin-${VERSION}-linux-gitian.zip *
|
||||
cp bitcoin-${VERSION}-linux-gitian.zip ../
|
||||
popd
|
||||
mkdir bitcoin-${VERSION}-win32-gitian
|
||||
pushd bitcoin-${VERSION}-win32-gitian
|
||||
unzip ../bitcoin-${VERSION}-win32-gitian.zip
|
||||
mkdir gitian
|
||||
cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
|
||||
for file in `ls ../gitian.sigs/$VERSION/`; do
|
||||
cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert ./gitian/$file-build.assert
|
||||
cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert.sig ./gitian/$file-build.assert.sig
|
||||
for signer in $(ls ../gitian.sigs/${VERSION}-win32/); do
|
||||
cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
|
||||
cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
|
||||
done
|
||||
zip bitcoin-$VERSION-linux-gitian.zip *
|
||||
cp bitcoin-$VERSION-linux-gitian.zip ../
|
||||
zip -r bitcoin-${VERSION}-win32-gitian.zip *
|
||||
cp bitcoin-${VERSION}-win32-gitian.zip ../
|
||||
popd
|
||||
|
||||
* Upload gitian zips to SourceForge
|
||||
|
||||
|
||||
|
||||
80
doc/translation_process.md
Normal file
80
doc/translation_process.md
Normal file
@@ -0,0 +1,80 @@
|
||||
Translations
|
||||
============
|
||||
|
||||
The Qt GUI can be easily translated into other languages. Here's how we
|
||||
handle those translations.
|
||||
|
||||
Files and Folders
|
||||
-----------------
|
||||
|
||||
### bitcoin-qt.pro
|
||||
|
||||
This file takes care of generating `.qm` files from `.ts` files. It is mostly
|
||||
automated.
|
||||
|
||||
### src/qt/bitcoin.qrc
|
||||
|
||||
This file must be updated whenever a new translation is added. Please note that
|
||||
files must end with `.qm`, not `.ts`.
|
||||
|
||||
<qresource prefix="/translations">
|
||||
<file alias="en">locale/bitcoin_en.qm</file>
|
||||
...
|
||||
</qresource>
|
||||
|
||||
### src/qt/locale/
|
||||
|
||||
This directory contains all translations. Filenames must adhere to this format:
|
||||
|
||||
bitcoin_xx_YY.ts or bitcoin_xx.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).
|
||||
|
||||
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.
|
||||
|
||||
Syncing with transifex
|
||||
----------------------
|
||||
|
||||
We are using http://transifex.net as a frontend for translating the client.
|
||||
|
||||
https://www.transifex.net/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.
|
||||
|
||||
### .tx/config
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.net
|
||||
|
||||
[bitcoin.tx]
|
||||
file_filter = src/qt/locale/bitcoin_<lang>.ts
|
||||
source_file = src/qt/locale/bitcoin_en.ts
|
||||
source_lang = en
|
||||
|
||||
### .tx/config (for Windows)
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.net
|
||||
|
||||
[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.
|
||||
|
||||
### Fetching new translations
|
||||
|
||||
1. `tx pull -a`
|
||||
2. update `src/qt/bitcoin.qrc` manually or via
|
||||
`ls src/qt/locale/*ts|xargs -n1 basename|sed 's/\(bitcoin_\(.*\)\).ts/<file alias="\2">locale/\1.qm<\/file>/'`
|
||||
3. `git add` new translations from `src/qt/locale/`
|
||||
232
share/pixmaps/bitcoin32.xpm
Normal file
232
share/pixmaps/bitcoin32.xpm
Normal file
@@ -0,0 +1,232 @@
|
||||
/* XPM */
|
||||
static const char * bitcoin32_xpm[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"32 32 194 2",
|
||||
" c #745305",
|
||||
". c #785704",
|
||||
"X c #7C5903",
|
||||
"o c #75560B",
|
||||
"O c #77590F",
|
||||
"+ c #7C5C0B",
|
||||
"@ c #795B12",
|
||||
"# c #7F631D",
|
||||
"$ c #825E07",
|
||||
"% c #825F0B",
|
||||
"& c #85610A",
|
||||
"* c #8C660C",
|
||||
"= c #8E680E",
|
||||
"- c #916B0F",
|
||||
"; c #856515",
|
||||
": c #8B6714",
|
||||
"> c #8F6A16",
|
||||
", c #816218",
|
||||
"< c #88691C",
|
||||
"1 c #926D12",
|
||||
"2 c #936F1C",
|
||||
"3 c #997417",
|
||||
"4 c #94721E",
|
||||
"5 c #9B761C",
|
||||
"6 c #9F781C",
|
||||
"7 c #A17B1E",
|
||||
"8 c #826622",
|
||||
"9 c #916E20",
|
||||
"0 c #967425",
|
||||
"q c #9D7420",
|
||||
"w c #9C7923",
|
||||
"e c #997728",
|
||||
"r c #99792C",
|
||||
"t c #A37D23",
|
||||
"y c #A37F2C",
|
||||
"u c #A68125",
|
||||
"i c #AB8225",
|
||||
"p c #A5832B",
|
||||
"a c #AA852C",
|
||||
"s c #B28A2C",
|
||||
"d c #A58233",
|
||||
"f c #AC8734",
|
||||
"g c #AE8C33",
|
||||
"h c #AC8C3C",
|
||||
"j c #B28C33",
|
||||
"k c #B98E34",
|
||||
"l c #B28D3D",
|
||||
"z c #B59136",
|
||||
"x c #BC9335",
|
||||
"c c #B3913E",
|
||||
"v c #BC933A",
|
||||
"b c #BF9A3D",
|
||||
"n c #C19235",
|
||||
"m c #C2953C",
|
||||
"M c #C39B3C",
|
||||
"N c #CA9C3D",
|
||||
"B c #B59343",
|
||||
"V c #BE9642",
|
||||
"C c #B69A44",
|
||||
"Z c #BD9A45",
|
||||
"A c #B49649",
|
||||
"S c #BB9A49",
|
||||
"D c #BB9F52",
|
||||
"F c #BFA256",
|
||||
"G c #C49C43",
|
||||
"H c #CA9D41",
|
||||
"J c #C59D4A",
|
||||
"K c #C99E4D",
|
||||
"L c #C3A144",
|
||||
"P c #CDA244",
|
||||
"I c #CFAA47",
|
||||
"U c #C3A14D",
|
||||
"Y c #CDA24A",
|
||||
"T c #CCAB49",
|
||||
"R c #D2A644",
|
||||
"E c #D2A54B",
|
||||
"W c #D6AA4C",
|
||||
"Q c #DAAE4E",
|
||||
"! c #DAB04F",
|
||||
"~ c #C7A656",
|
||||
"^ c #CDA452",
|
||||
"/ c #CFAC52",
|
||||
"( c #C0A65E",
|
||||
") c #CEA75A",
|
||||
"_ c #CCAC59",
|
||||
"` c #D2AB53",
|
||||
"' c #DCAF52",
|
||||
"] c #D6AD5A",
|
||||
"[ c #D9AE5B",
|
||||
"{ c #DCB556",
|
||||
"} c #DFB855",
|
||||
"| c #D6B25F",
|
||||
" . c #DCB35C",
|
||||
".. c #DEBE5E",
|
||||
"X. c #E2B656",
|
||||
"o. c #E1B55A",
|
||||
"O. c #E6BC5D",
|
||||
"+. c #E9BD5E",
|
||||
"@. c #C3AA63",
|
||||
"#. c #CCAD62",
|
||||
"$. c #D4AF62",
|
||||
"%. c #CDB565",
|
||||
"&. c #CEB46D",
|
||||
"*. c #D7B164",
|
||||
"=. c #DBB362",
|
||||
"-. c #D6BD64",
|
||||
";. c #DDBA64",
|
||||
":. c #D3B66C",
|
||||
">. c #DFB86B",
|
||||
",. c #CEB772",
|
||||
"<. c #D0B771",
|
||||
"1. c #D4BA73",
|
||||
"2. c #D9BE77",
|
||||
"3. c #D6BE79",
|
||||
"4. c #D8BF7A",
|
||||
"5. c #E4BB62",
|
||||
"6. c #E9BF64",
|
||||
"7. c #E4BC69",
|
||||
"8. c #E9BF69",
|
||||
"9. c #E0BB71",
|
||||
"0. c #E9C05E",
|
||||
"q. c #D2C279",
|
||||
"w. c #DBC27C",
|
||||
"e. c #E2C667",
|
||||
"r. c #EDC364",
|
||||
"t. c #E3C16E",
|
||||
"y. c #ECC46C",
|
||||
"u. c #EDCC6C",
|
||||
"i. c #F1C764",
|
||||
"p. c #F5CA66",
|
||||
"a. c #F9CD67",
|
||||
"s. c #F5CC6A",
|
||||
"d. c #F9CD6B",
|
||||
"f. c #FBD36F",
|
||||
"g. c #EDC572",
|
||||
"h. c #E5CF77",
|
||||
"j. c #ECCA74",
|
||||
"k. c #E0C67E",
|
||||
"l. c #EFCE78",
|
||||
"z. c #F6CE72",
|
||||
"x. c #FBCF71",
|
||||
"c. c #F4CE79",
|
||||
"v. c #F4D273",
|
||||
"b. c #FCD473",
|
||||
"n. c #F4DC75",
|
||||
"m. c #FEDA74",
|
||||
"M. c #F6D77C",
|
||||
"N. c #FBD47A",
|
||||
"B. c #F1DA7B",
|
||||
"V. c #FDDA7C",
|
||||
"C. c #FEE27D",
|
||||
"Z. c #DDC683",
|
||||
"A. c #DFC884",
|
||||
"S. c #E4CA84",
|
||||
"D. c #E3CC89",
|
||||
"F. c #E7D183",
|
||||
"G. c #EFD280",
|
||||
"H. c #EFDC82",
|
||||
"J. c #ECD48D",
|
||||
"K. c #EFDA8C",
|
||||
"L. c #F9D783",
|
||||
"P. c #F2DF83",
|
||||
"I. c #FCDB83",
|
||||
"U. c #F5DC8F",
|
||||
"Y. c #FADD8B",
|
||||
"T. c #EBD593",
|
||||
"R. c #EFDA99",
|
||||
"E. c #F3DD93",
|
||||
"W. c #F3DF9F",
|
||||
"Q. c #FFE385",
|
||||
"!. c #FEE986",
|
||||
"~. c #FDE48C",
|
||||
"^. c #FEEC8E",
|
||||
"/. c #ECE199",
|
||||
"(. c #F6E591",
|
||||
"). c #FEE494",
|
||||
"_. c #FEEB93",
|
||||
"`. c #FEE69A",
|
||||
"'. c #FFEB9B",
|
||||
"]. c #FFF197",
|
||||
"[. c #FFF39B",
|
||||
"{. c #FEF99B",
|
||||
"}. c #F6E2A2",
|
||||
"|. c #F9E5A5",
|
||||
" X c #F7E9A5",
|
||||
".X c #FEECA4",
|
||||
"XX c #FBE7A8",
|
||||
"oX c #FDEAAB",
|
||||
"OX c #F7F2AA",
|
||||
"+X c #FEF2AC",
|
||||
"@X c #FDF4B4",
|
||||
"#X c #FFFABA",
|
||||
"$X c #FFFEC2",
|
||||
"%X c None",
|
||||
/* pixels */
|
||||
"%X%X%X%X%X%X%X%X%X%X%X%Xp t 6 5 w t w %X%X%X%X%X%X%X%X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%X%X%X%Xu u x I X.0.s.u.0.W x 7 4 %X%X%X%X%X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%X%Xy i I i.a.f.m.m.b.f.s.a.s.i.W 7 > %X%X%X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%Xt M 0.a.m.m.m.m.f.d.p.p.p.f.d.f.i.b 1 < %X%X%X%X%X%X",
|
||||
"%X%X%X%X%X7 ! d.f.f.m.f.+.W P R I Q 5.v.V.V.z.f.{ 5 + %X%X%X%X%X",
|
||||
"%X%X%X%Xu X.f.m.m.f.' H s ~ V y _ Z J o.g.L.L.Q.!.e.5 X %X%X%X%X",
|
||||
"%X%X%Xu X.b.C.m.+.N m n t }.3.> }.w.V 5.y.y.Y.[.^.^.-.1 + %X%X%X",
|
||||
"%X%Xt P m.N.m.X.v v v k 6 }.1.: /.4.c 7.N.N.v.!.{.{.^.L & %X%X%X",
|
||||
"%X%Xg Y.Y.V.+.m k a t t : }.1.% }.1.r | l.B.M.b.!.{.^.n.7 X %X%X",
|
||||
"%Xp -._.'.Y.' Y n D.}.}.|.oXXX|.oX XT.w.F _ j.v.v._.^.C.T & @ %X",
|
||||
"%Xa (.'.'.9.[ [ K S.}.oXoXoXoXXXoXoXoXoX XD / s.d.v.!.C.v.3 o %X",
|
||||
"%XU '.'.Y.[ [ [ [ J f <.oXoX( 2 f S J.oXoXT.j r.s.i.C.C.C.z X %X",
|
||||
"p e.'.'.F. .=.=.=.=.) 1.oXoX@.f . .F oXoX}.a +.i.i.b.C.m.I X O ",
|
||||
"u w.'.[.j.5.8.7.7.7.] 2.oXoX@.y W c &.oXoXZ.k r.s.i.s.V.m.} = o ",
|
||||
"u H.[.{.y.8.y.g.8.g.7.2.oXoXA.@.&.D.oXoXT.e G +.O.O.5.V.m.0.- o ",
|
||||
"u !.].[.r.8.y.g.g.g.7.4.oXoXoXoXoXoXoXoXoX<.y W X.o.o.m.m.0.- o ",
|
||||
"u B._._.5.5.8.y.g.c.g.w.oXoX,.h A F <..XoXoX1.k ' ' ' V.N.r.- ",
|
||||
"u u.Q.~.r.6.z.N.V.I.v.k.oXoX@.B | _ c 1.oXoX}.a ' ' O.I.b.O.= o ",
|
||||
"u ..Q.Q.v.i.s.c.N.L.l.Z.oXoX@.B t.=.S &.oXoXXXy Y R +.N.b.Q % o ",
|
||||
"t T C.I.I.6.u.z.z.5.S 1.oXoX@.e B h D |.oXoXS.f Y Y 6.d.d.n X O ",
|
||||
"%Xs m.V.Q.r.r.z.5.<.}.oXoXoXXXW.}.oXoXoXoXW.h G H R a.p.s.7 %X",
|
||||
"%X7 O.V.V.v.+.r.` 4.oXoXoXoXoXoXoXoXXXR.<.h v N N o.a.p.Q = %X",
|
||||
"%Xw x v.v.v.r.+. .Z l d e }.Z.r }.3.d l V G n n R a.s.a.s X O %X",
|
||||
"%X%X6 { v.l.v.+.O.5.=.^ d }.4.9 }.1.f J G m m G d.d.x.Q = %X%X",
|
||||
"%X%X%Xs u.v.v.v.r.6.o. .l }.4.9 W.4.l ^ ^ J ) c.N.N.y.7 X O %X%X",
|
||||
"%X%X%X5 z v.v.M.I.g.;. .J 1.#.B 1.#.) 7.$.S..X'.W.Y.j $ %X%X%X",
|
||||
"%X%X%X%X5 b N.Y.~.).Y.j.5.$.=.=.$.*.2.J.@X$X#X#XoXC $ %X%X%X%X",
|
||||
"%X%X%X%X%X3 z U.@X+X`.`.`.(.E.E.E.|.@X@X#X#X#X/.j % %X%X%X%X%X",
|
||||
"%X%X%X%X%X%Xw a q.OX|.).`._.'.'.XX.X.X+X+X X%.w X o %X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%X%X%Xw a _ j.~.~.).).`.`.`.F._ t & . # %X%X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%X%X%X%X%X4 3 t z L U Z z t 1 $ . 8 %X%X%X%X%X%X%X%X%X",
|
||||
"%X%X%X%X%X%X%X%X%X%X%X%X%X< ; & + + , 8 %X%X%X%X%X%X%X%X%X%X%X%X"
|
||||
};
|
||||
292
share/pixmaps/bitcoin80.xpm
Normal file
292
share/pixmaps/bitcoin80.xpm
Normal file
@@ -0,0 +1,292 @@
|
||||
/* XPM */
|
||||
static const char * bitcoin80_xpm[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"80 80 206 2",
|
||||
" c #725203",
|
||||
". c #785706",
|
||||
"X c #7B5907",
|
||||
"o c #7C5A09",
|
||||
"O c #7F5F10",
|
||||
"+ c #815E0B",
|
||||
"@ c #85620C",
|
||||
"# c #89650F",
|
||||
"$ c #856313",
|
||||
"% c #896614",
|
||||
"& c #8D6913",
|
||||
"* c #886718",
|
||||
"= c #8D6B1B",
|
||||
"- c #926D14",
|
||||
"; c #926E1B",
|
||||
": c #967116",
|
||||
"> c #997317",
|
||||
", c #95711E",
|
||||
"< c #9B7419",
|
||||
"1 c #9F781B",
|
||||
"2 c #A27B1D",
|
||||
"3 c #8F6F22",
|
||||
"4 c #926F21",
|
||||
"5 c #947323",
|
||||
"6 c #9A7623",
|
||||
"7 c #9D7925",
|
||||
"8 c #957628",
|
||||
"9 c #9A7729",
|
||||
"0 c #9D7B2B",
|
||||
"q c #9D7F33",
|
||||
"w c #A47D23",
|
||||
"e c #A97F27",
|
||||
"r c #A37E2B",
|
||||
"t c #9F8030",
|
||||
"y c #A78021",
|
||||
"u c #AC8425",
|
||||
"i c #A5802D",
|
||||
"p c #AC842B",
|
||||
"a c #AF8829",
|
||||
"s c #B2872C",
|
||||
"d c #B28B2D",
|
||||
"f c #A68333",
|
||||
"g c #AA8633",
|
||||
"h c #AD8A36",
|
||||
"j c #A4863A",
|
||||
"k c #A88638",
|
||||
"l c #A7893B",
|
||||
"z c #AC8B3B",
|
||||
"x c #B28732",
|
||||
"c c #B48C32",
|
||||
"v c #B98E34",
|
||||
"b c #B28D3B",
|
||||
"n c #B88F3C",
|
||||
"m c #B69033",
|
||||
"M c #BD9235",
|
||||
"N c #B4913D",
|
||||
"B c #BC943A",
|
||||
"V c #BE993C",
|
||||
"C c #C19336",
|
||||
"Z c #C1953B",
|
||||
"A c #C49A3C",
|
||||
"S c #C99C3D",
|
||||
"D c #CDA13F",
|
||||
"F c #D0A33F",
|
||||
"G c #A88B40",
|
||||
"H c #B08F40",
|
||||
"J c #AE9142",
|
||||
"K c #AE944C",
|
||||
"L c #B49443",
|
||||
"P c #BB9542",
|
||||
"I c #B49946",
|
||||
"U c #BD9846",
|
||||
"Y c #B3964C",
|
||||
"T c #BB974A",
|
||||
"R c #B6994A",
|
||||
"E c #BF9C4A",
|
||||
"W c #B69B53",
|
||||
"Q c #B99D53",
|
||||
"! c #BCA055",
|
||||
"~ c #BDA25A",
|
||||
"^ c #C49742",
|
||||
"/ c #C49C43",
|
||||
"( c #CB9E42",
|
||||
") c #C49D4B",
|
||||
"_ c #C99E4C",
|
||||
"` c #C29F52",
|
||||
"' c #C5A244",
|
||||
"] c #CDA245",
|
||||
"[ c #C5A34C",
|
||||
"{ c #CCA34B",
|
||||
"} c #CCA94D",
|
||||
"| c #D2A445",
|
||||
" . c #D1A54B",
|
||||
".. c #D5AA4E",
|
||||
"X. c #DBAF4F",
|
||||
"o. c #C6A352",
|
||||
"O. c #CBA554",
|
||||
"+. c #C5AA57",
|
||||
"@. c #CEAC54",
|
||||
"#. c #C4A65A",
|
||||
"$. c #CDA458",
|
||||
"%. c #C2A85F",
|
||||
"&. c #CEAA5B",
|
||||
"*. c #D0A550",
|
||||
"=. c #D4AB53",
|
||||
"-. c #DBAE53",
|
||||
";. c #D0A75B",
|
||||
":. c #D4AC5A",
|
||||
">. c #D9AE5C",
|
||||
",. c #CEB25E",
|
||||
"<. c #D4B156",
|
||||
"1. c #DDB156",
|
||||
"2. c #D4B25C",
|
||||
"3. c #DCB35D",
|
||||
"4. c #D7B85C",
|
||||
"5. c #DCBA5E",
|
||||
"6. c #E2B355",
|
||||
"7. c #E2B65B",
|
||||
"8. c #E4BA5D",
|
||||
"9. c #EABD5E",
|
||||
"0. c #C5AA62",
|
||||
"q. c #CCAE63",
|
||||
"w. c #C6AE69",
|
||||
"e. c #D5AF62",
|
||||
"r. c #CEB167",
|
||||
"t. c #CCB36C",
|
||||
"y. c #D5B162",
|
||||
"u. c #DCB462",
|
||||
"i. c #D7B964",
|
||||
"p. c #DCBC64",
|
||||
"a. c #D2B66B",
|
||||
"s. c #DCB669",
|
||||
"d. c #D7BE69",
|
||||
"f. c #DFB86A",
|
||||
"g. c #D0B771",
|
||||
"h. c #D2BA74",
|
||||
"j. c #D5BE78",
|
||||
"k. c #E1B766",
|
||||
"l. c #E4BB63",
|
||||
"z. c #E9BE63",
|
||||
"x. c #E3BB6A",
|
||||
"c. c #E9BF6A",
|
||||
"v. c #E1BE72",
|
||||
"b. c #DDC16B",
|
||||
"n. c #DAC27E",
|
||||
"m. c #E4C164",
|
||||
"M. c #ECC264",
|
||||
"N. c #E4C36B",
|
||||
"B. c #EBC36C",
|
||||
"V. c #E7C96F",
|
||||
"C. c #EECA6E",
|
||||
"Z. c #F1C564",
|
||||
"A. c #F1C76A",
|
||||
"S. c #F5CB6C",
|
||||
"D. c #FACE6D",
|
||||
"F. c #F4D06F",
|
||||
"G. c #FCD06E",
|
||||
"H. c #E5C371",
|
||||
"J. c #EDC573",
|
||||
"K. c #E4CA73",
|
||||
"L. c #ECCC74",
|
||||
"P. c #E7CF7A",
|
||||
"I. c #EBCD7A",
|
||||
"U. c #F3CD73",
|
||||
"Y. c #F8CE71",
|
||||
"T. c #F3CD7A",
|
||||
"R. c #EDD076",
|
||||
"E. c #EDD17B",
|
||||
"W. c #F4D274",
|
||||
"Q. c #FBD274",
|
||||
"!. c #FED977",
|
||||
"~. c #F3D47B",
|
||||
"^. c #FDD47A",
|
||||
"/. c #F5DA7C",
|
||||
"(. c #FDDA7C",
|
||||
"). c #FFE07F",
|
||||
"_. c #DBC481",
|
||||
"`. c #DFC885",
|
||||
"'. c #E1CA86",
|
||||
"]. c #EACC80",
|
||||
"[. c #E4CD8A",
|
||||
"{. c #EED383",
|
||||
"}. c #E7D18F",
|
||||
"|. c #EAD38C",
|
||||
" X c #F4D680",
|
||||
".X c #FDD780",
|
||||
"XX c #F5DA83",
|
||||
"oX c #FCDC84",
|
||||
"OX c #F5DB8A",
|
||||
"+X c #FADE89",
|
||||
"@X c #EAD492",
|
||||
"#X c #EED896",
|
||||
"$X c #EFDA9A",
|
||||
"%X c #F1DD9D",
|
||||
"&X c #FDE283",
|
||||
"*X c #F6E18D",
|
||||
"=X c #FEE48D",
|
||||
"-X c #FFE692",
|
||||
";X c #FFE894",
|
||||
":X c #FBE799",
|
||||
">X c #FFEA98",
|
||||
",X c #F6E2A3",
|
||||
"<X c #FAE6A6",
|
||||
"1X c #FAE7A8",
|
||||
"2X c #FDEAAB",
|
||||
"3X c None",
|
||||
/* pixels */
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u u u u y y u y 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u u u u u u a u u u u u u a u u 2 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u u u u u s m V D ' { ' D M d u u a u u u u 2 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u u u M } m.~.oX=X=X=X=X=X-X-X=X&X/.m.=.V u u a u u w 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u u M 4.~.=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X/.5.Z u u u u u 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u ] V.&X=X=X&X=X=X=X=X=X=X=X=X=X&X=X=X=X=X=X=X=X=X=X=XW.} a u u u 2 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu a u u ' W.=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X+X=X=X=X&X=X=X=X~.} a u u u < 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u M N.=X&X=X=X=X=X=X=X=X-X=X=X=X=X&X=X=X=XoX=X=X=X=X&X+X=X=X=X=X=X=X=XL.M u u u < 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u u } XX=X=X=X&X=X=X=X=X=X=X=X=X=X=X=X=X=X=X=X*X=X=X=X=X=X=X=X=X=X=X=X=X=X=XoX<.a u u 2 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u s m.&X=X=X=X=X=X=X=X=X=X=X=X=X=X/.L.M.m.9.m.9.m.C.~.&X*X=X=X=X=X=X=X=X=X=X=X=X=XV.m u u 2 o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3Xu u u c R.=X=X=X=X=X=X=X=X=X=X=XoXC.1.| S S A S D D D D ] ] ..<.N./.=X-X=X-X=X=X=X=X=X=X=XXXZ u a 2 o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3Xu u u m XX=X=X=X=X=X=X=X=X=X=XW.3.| ^ A C M M M C S S A A A / ( { =.<.l.I.=X-X-X=X=X=X=X=X=X=X=XV a u 2 . 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3Xu u m /.=X=X=X-X=X=X=X=X=X~.1.D ] S Z v x p s u s d d v c c v V { =.7.8.7.l.T.=X-X=X-X-X-X-X-X=X=XV u a 1 3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3Xu u d /.=X=X=X=X=X=X=X=X&X8.^ A ( S M v e $.r.e.r.u w i a.a.a.&.b ^ =.l.l.l.c.z.z.XX-X-X-X-X=X-X-X;X&XV u u : 3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3Xu u s R.=X=X=X=X=X=X=X=XU.{ ^ Z C ( A M u w [.2X2X2X0 - 7 2X2X1X@Xi P *.l.x.B.U.C.z.z.W.-X-X-X-X-X-X=X-X*Xd a u # . 3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3Xu u u l.=X=X=X=X-X=X=X=Xm.Z Z Z Z n Z Z v e , '.2X2X2X5 & ; 2X2X2X}.7 b { 3.x.^.^.^.Y.A.z.R.-X;X;X;X;X-X;X-XP.a u y . 3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3Xu u } -X-X=X-X=X=X=X=Xl.M M Z C C C C C x e ; '.2X2X2X, $ = 2X2X2X}.6 h ) >.J..X.X.X.X(.W.Z.C.&X;X;X;X;X-X-X-X<.u u < 3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3Xu u c oX=X=X=X=X=X=X=Xl.Z C M M C C v v v s w = '.2X2X2X5 $ = 2X2X2X}.5 g ) u./.+X+X=X=X=X&XW.Z.F.=X;X;X;X;X-X-X*XV u y @ X 3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3Xu u u N.-X-X-X-X=X=X=XB.Z M C v v s e e e e w > % `.2X2X2X= + % 2X2X2X}.= r L 4.E.OX+X-X=X=X&X).W.M.R.;X;X;X-X-X-X;XR.u u y 3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3Xu u U -X-X-X-X-X-X=XW.^ C C C x e e r 6 5 4 ; = $ `.2X2X2X= O = 2X2X2X}.O = t Q ,.b.P./.*X=X&X&X).F.M.W.;X;X;X;X&X-X&X} u u O 3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xu u u R.-X-X-X-X-X-X=X=.{ ^ Z C x n 2X2X<X<X1X2X<X<X2X2X2X2X1X1X<X2X2X2X<X$X[.b.~ J I ~ b.P.&X&X&X).!.F.m.).;X;X;X;X;X&X).u y y 3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xu u U -X-X-X-X-X-X-Xc.=.=. ._ ^ x z 2X2X1X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X<Xn.l I ,.K./.).).).F.Z.Z.&X;X;X=X-X-X&X} u u O 3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xu u V.-X;X-X-X-X-XOX>.>.>.=.=._ n b 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X:XI N +.V./.).).F.F.9.W.;X=X;X-X-X-XR.u u > 3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xu u d =X;X-X-X-X-X-Xx.>.>.>.>.>...^ P 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X,Xl N 4.R.!.!.!.G.Z.M.&X;X=X=X-X-X-XB a u 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xu u @.;X;X-X;X;X;XXX>.:.>.>.>.>.>._ P ` Y Y W _.2X2X2X2X2X2X@XW W ~ 0.t.'.<X2X2X2X2X2X2X2X2X'.0 ' m./.!.!.Q.S.9.F.=X;X-X=X-X&X4.u u @ 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xu u P.;X;X;X;X-X:XN.>.>.>.>.>.>.>.=._ P z r 4 8 2X2X2X2X2X2X_.. $ , 6 1 3 t ~ 1X2X2X2X2X2X2X2Xt B 5.G.!.!.G.G.M.9.&X;X=X-X-X=X/.u u > 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3Xu u d =X;X;X=X;X;X=X3.>.>.>.e.>.3.3.>.:.*._ P r 9 2X2X2X2X2X1Xn.@ , c B N m h 8 ~ 2X2X2X2X2X2X2XI h <.F.!.G.G.F.M.9.W.;X=X-X-X=X=Xm u y . 3X3X3X3X3X3X",
|
||||
"3X3X3X3Xu u ' -X-X>X-X-X-X X>.>.>.>.>.>.>.u.u.u.u.3.$.P f 2X2X2X2X2X2X_.$ i / -.<.8.} h 8 1X2X2X2X2X2X2X! i <.S.G.G.G.G.Z.9.Z.=X-X=X-X&X-X} u u X 3X3X3X3X3X3X",
|
||||
"3X3X3X3Xu u 4.-X-X-X-X-X-XJ.3.>.>.k.k.k.k.k.u.k.u.u.:.U k 2X2X2X2X2X1X_.% f } 8.Z.F.8.U 8 ,X2X2X2X2X2X2XI g } Z.D.G.D.G.D.Z.9.&X-X=X=X=X-Xm.u u @ 3X3X3X3X3X3X",
|
||||
"3X3X3X3Xu u K.;X-X;X-X>X-Xk.3.k.k.k.k.k.k.k.k.k.k.u.e.U k 2X2X2X2X2X2X_.% f [ 8.F.M.<.b i 2X2X2X2X2X2X2Xt a X.Z.D.D.D.G.G.Z.9./.=X-X=X=X=XR.u u & 3X3X3X3X3X3X",
|
||||
"3X3X3X3Xu u E.;X-X;X-X-X=Xl.l.x.c.k.x.k.k.x.x.v.x.x.u.) z 2X2X2X2X2X2X_.$ 7 L <.<.} N 6 h.2X2X2X2X2X2X_.: V 1.S.D.D.G.D.S.M.6.W.-X=X-X=X=X&Xu u > X 3X3X3X3X3X",
|
||||
"3X3X3Xu a u =X;X;X;X;X;XoX7.z.c.c.c.c.c.c.c.c.c.x.k.u.) z 2X2X2X2X2X2Xn.o = i N h i l n.2X2X2X2X2X2X<Xt t D 7.M.Z.z.z.9.9.9.6.M.-X=X=X=X;X=Xm u 1 3X3X3X3X3X",
|
||||
"3X3X3Xy u a =X;X;X;X;X;XXXl.z.c.c.c.c.T.J.J.T.v.J.J.s.` z 2X2X2X2X2X2X#XW ~ ~ t.n.$X2X2X2X2X2X2X2X,Xt % t V X.8.9.8.9.9.9.6.6.M.-X=X=X=X=X&XM u 2 3X3X3X3X3X",
|
||||
"3X3X3Xu u m -X-X-X;X;X;X~.z.z.c.c.c.c..XJ.J.J.J.J.J.x.O.b 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2Xw.$ * y V X.7.8.8.9.7.8.7.6.8.=X=X-X-X=X-XV a y 3X3X3X3X3X",
|
||||
"3X3X3Xu a m -X-X-X;X;X;X~.7.z.c.c.c.c.c.c.J.T.J.T.J.B.O.b 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X,X~ , c ' X.6.6.7.6.6.6.6.8.=X=X=X-X&X-XV u y 3X3X3X3X3X",
|
||||
"3X3X3Xu u m -X-X-X-X-X-X/.8.l.z.c.T.c.J.c.J.T.v.J.J.x.O.G 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2Xn.r v { 6.6.6.6.6.6.-.7.&X-X=X=X=X-XD u y 3X3X3X3X3X",
|
||||
"3X3X3Xu u d =X-X-X-X-X-X~.7.z.z.c.c.c.c.c.J.c.T.T.^.T.y.R 2X2X2X2X2X2X@XK K W W W ~ h.#X1X2X2X2X2X2X2X2X2Xa.i Z ..X.6.6.-.-.6.7.-X-X-X-X-X-XD u 2 3X3X3X3X3X",
|
||||
"3X3X3Xw u a =X-X-X-X-X-X~.7.7.8.c.c.c.c.T..X.X+X+X+XXXi.R 2X2X2X2X2X2Xn.. * 5 8 5 3 = * q `.2X2X2X2X2X2X2X<Xk c | X.6.-.-.-.-.z.&X;X=X;X-X;XV u w 3X3X3X3X3X",
|
||||
"3X3X3Xu u u =X-X=X-X-X-X/.8.M.B.Y.T.^.^.^..X.XoXoX+XXXi.R 2X2X2X2X2X2X_.$ 0 b U U N l t 5 $ `.2X2X2X2X2X2X2X0.e Z .....-.-.6.c.;X=X;X=X;X-Xd u 1 3X3X3X3X3X",
|
||||
"3X3X3X3Xu a E.-X-X-X-X-X=Xz.S.D.Y.^.Q.^.^.^..XoX+X+XXXi.R 2X2X2X2X2X2X_.= l +.u.i.,.O.E h 5 G 2X2X2X2X2X2X2X_.0 n | . .*. .*.T.-X;X;X;X-X=Xa u : 3X3X3X3X3X",
|
||||
"3X3X3X3Xu u N.-X-X-X=X-X-XA.Z.S.Y.Q.Q.^.^..X.XoXoX&X.Xi.R 2X2X2X2X2X2X_.= N y.H.H.m.i.y.E f 8 2X2X2X2X2X2X2X'.6 n | . . . . ..X;X;X;X;X-X~.u u & 3X3X3X3X3X",
|
||||
"3X3X3X3Xu u <.-X-X=X=X-X-XW.Z.S.Y.Y.Q.^.^.^.(..XoX=XXXi.R 2X2X2X2X2X2X_.= L 4.H.J.H.x.i.o.k j 2X2X2X2X2X2X2X_.6 B . . . .{ =.-X;X-X;X-X-Xb.a u @ 3X3X3X3X3X",
|
||||
"3X3X3X3Xy a V =X=X-X-X=X-XXXZ.S.Y.Y.Y.Q.!.^..X.XoXoXE.y.I 2X2X2X2X2X2X_.= J y.b.H.N.p.&.P 0 g.2X2X2X2X2X2X2Xr.r B _ { .| ] l.-X;X;X-X-X;X..u u . . 3X3X3X3X3X",
|
||||
"3X3X3X3Xy u a =X=X=X=X-X=X-XM.Z.S.Y.Y.Q.Q.^.^.^.U.J.u.E l 2X2X2X2X2X2X_.* k o.e.e.$.` P q W 1X2X2X2X2X2X2X2XG i B ] | ] ] ( ~.=X;X;X;X;X;XM u y 3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xu u V.-X=X-X=X-X-XF.M.A.D.Y.Q.Y.Q.Y.B.2.[ N 0 j 2X2X2X2X2X2X_.O 5 l G z H H Q _.2X2X2X2X2X2X2X2X#X, g ^ ] ] | ] ..-X-X-X-X&X;X).u u : 3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xu u } =X=X=X=X-X=X&XM.Z.S.D.W.Q.Y.B.*.a.#X@X|.,X2X2X2X2X2X2X,X[.[.}.}.%X<X2X2X2X2X2X2X2X2X2X2X<Xj 6 b / ] ] ] ] M.-X-X-X-X-X-X4.u u O 3X3X3X3X3X3X",
|
||||
"3X3X3X3X3Xy u d =X=X=X=X=X=X-XS.M.A.S.S.U.A.u.) n.2X2X2X2X2X2X2X2X2X2X2X2X1X2X2X2X2X2X2X2X2X2X2X2X2X2X2XW ; i M ( S S S ] &X-X-X-X-X=X-Xm u y . X 3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xu u p.=X=X=X=X=X-X&X9.Z.C.S.S.M.:.b [.2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X%XG = r x v C D D D m.-X-X-X-X-X-XR.u u : 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xy u B =X=X=X=X=X=X=XF.9.M.A.C.M.=.h %X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X1X#X~ 4 ; r p v v M C A | &X-X-X-X-X-X-X] u u X 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3Xy u u N.=X=X-X=X-X=X=XM.z.M.M.M.1.V #X%X%X%X%X$X%X%X<X2X2X2X%X$X%X2X2X2X<X[.n.t.W q = , r i x v C C C M C W.-X-X-X-X-X-X/.u u 1 X 3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3Xu u V *X=X=X*X=X=X=XoX8.M.M.M.5.{ m r , ; $ $ o o `.2X2X2X3 o $ 2X2X2X[.o $ 4 9 0 r g x v m C M C C C 8.&X-X-X-X-X-X-X[ u u @ 3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X2 u u 5.=X=X=X=X=X=X=XI.8.M.M.z.3.O.) P b r 0 4 % `.2X2X2X3 $ * 2X2X2X[.$ 4 r e ^ n n Z Z Z C C C M | =X=X-X-X-X-X-XR.u u < 3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3Xy u d XX=X=X=X=X-X=X=XS.8.8.M.M.z.z.7.{ _ U g 5 `.2X2X2X8 = 3 2X2X2X}.3 0 x ^ _ ^ ^ ^ Z ^ B ^ C .&X-X-X-X-X-X-X=XB u u o 3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X1 u u ' =X=X*X=X=X*X=X=XW.8.M.M.A.S.l.u.>.o.L r [.2X2X2X9 = 8 2X2X2X}.4 r ^ _ *.*._ ) ) ^ ^ ^ O.oX=X-X-X-X-X-X-X<.u u : . 3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3Xy u u i.=X=X=X=X=X-X*X=XW.9.M.A.B.3.5.5.;.U f [.2X2X2Xq 4 8 2X2X2X}.r q _ _ ;.;.*._ _ ` _ e.+X-X-X-X-X-X-X-XR.a u 2 3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3Xu u u K.=X=X=X-X=X=X=X=XXXz.M.8.5.8.u.:.) h }.2X2X2Xj r f 2X2X2X@Xq T _ e.e.u.e.;.$.$.b.-X-X-X=X;X=X;X-X&Xa a u + 3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3Xu u d ~.=X=X=X=X=X-X=X-X+XC.3.5.7.7.2.@.) q.r.q.q.H H L g.r.w.q.T ` e.k.v.k.k.s.s.{.-X-X;X-X;X;X;X;X*XV u u & . 3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X2 u u c XX-X=X=X=X=X-X=X-X-X Xl.7.7.u.2.$.o.[ [ o.O.$.&.&.` ` ` q.s.k.v.k.k.x.{.%X>X>X>X;X>X;X>X>X*XV u u > 3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X2 u u m ~.=X-X-X-X=X-X-X-X-X-X Xc.7.5.u.3.e.y.u.s.f.k.s.e.e.s.s.k.k.k.v. X:X>X>X>X>X>X>X;X>X>X*XV u u < 3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u d R.-X=X-X=X-X-X-X-X-X-X-X+XI.v.u.s.l.k.k.x.x.x.s.s.s.s.j.].+X>X>X>X>X>X:X>X>X>X>X>XOXV u u 1 3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u a p.-X-X-X;X;X;X-X-X-X:X-X-X-X-XOX XL.J.J.J.L.I.].OX:X>X-X>X>X-X>X>X>X>X>X>X>X>XK.a a u < 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u @.=X;X;X>X;X-X-X>X-X-X-X-X;X-X-X-X-X-X>X>X-X>X-X>X>X>X>X;X>X>X>X-X>X-X-X:X<.u u u > 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u m n.>X;X>X>X-X-X-X-X>X-X-X-X;X;X;X-X-X-X-X-X>X-X-X>X-X>X>X-X>X>X>X>XK.B u u u & 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xw u u u / {.>X>X-X-X-X-X-X-X-X-X-X-X;X-X-X;X:X-X-X>X-X:X>X;X;X>X;X;X{.[ u u u w + 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u u ) K.-X-X-X-X:X-X-X-X-X-X-X-X-X-X-X-X-X>X-X-X-X-X-X-XE.[ u u u u - . 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u u m 2.E.-X+X:X-X-X-X-X-X-X-X-X-X:X-X-X-X;X-XOXi.B u u u u 1 o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X> u u u u u v [ l.I.OX-X-X-X-X-X-X-X-X+XI.f.@.m u u u u u 1 + o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X& 2 u u u u u u u d B V V V V B d u u u u u u u y - . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X+ - 1 u u u u u u u a u u u u u u u u 2 - o o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo . X # - > 1 2 2 2 1 2 > - # o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X",
|
||||
"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X"
|
||||
};
|
||||
@@ -5,7 +5,7 @@ SetCompressor /SOLID lzma
|
||||
|
||||
# General Symbol Definitions
|
||||
!define REGKEY "SOFTWARE\$(^Name)"
|
||||
!define VERSION 0.5.0
|
||||
!define VERSION 0.6.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.5.0-win32-setup.exe
|
||||
OutFile bitcoin-0.6.0-win32-setup.exe
|
||||
InstallDir $PROGRAMFILES\Bitcoin
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
BrandingText " "
|
||||
ShowInstDetails show
|
||||
VIProductVersion 0.5.0.0
|
||||
VIProductVersion 0.6.0.6
|
||||
VIAddVersionKey ProductName Bitcoin
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey CompanyName "${COMPANY}"
|
||||
@@ -75,6 +75,10 @@ Section -Main SEC0000
|
||||
File /r /x *.exe /x *.o ../src\*.*
|
||||
SetOutPath $INSTDIR
|
||||
WriteRegStr HKCU "${REGKEY}\Components" Main 1
|
||||
|
||||
# Remove old wxwidgets-based-bitcoin executable and locales:
|
||||
Delete /REBOOTOK $INSTDIR\bitcoin.exe
|
||||
RMDir /r /REBOOTOK $INSTDIR\locale
|
||||
SectionEnd
|
||||
|
||||
Section -post SEC0001
|
||||
@@ -94,6 +98,12 @@ 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"'
|
||||
SectionEnd
|
||||
|
||||
# Macro for selecting uninstaller sections
|
||||
@@ -131,6 +141,7 @@ Section -un.post UNSEC0001
|
||||
DeleteRegValue HKCU "${REGKEY}" Path
|
||||
DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
|
||||
DeleteRegKey /IfEmpty HKCU "${REGKEY}"
|
||||
DeleteRegKey HKCR "bitcoin"
|
||||
RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
|
||||
RmDir /REBOOTOK $INSTDIR
|
||||
Push $R0
|
||||
|
||||
506
src/addrman.cpp
Normal file
506
src/addrman.cpp
Normal file
@@ -0,0 +1,506 @@
|
||||
// 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.
|
||||
|
||||
#include "addrman.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH);
|
||||
std::vector<unsigned char> vchKey = GetKey();
|
||||
ss1 << nKey << vchKey;
|
||||
uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
ss2 << nKey << vchGroupKey << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP);
|
||||
uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
|
||||
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const
|
||||
{
|
||||
CDataStream ss1(SER_GETHASH);
|
||||
std::vector<unsigned char> vchGroupKey = GetGroup();
|
||||
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
|
||||
ss1 << nKey << vchGroupKey << vchSourceGroupKey;
|
||||
uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
|
||||
|
||||
CDataStream ss2(SER_GETHASH);
|
||||
ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP);
|
||||
uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
|
||||
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
bool CAddrInfo::IsTerrible(int64 nNow) const
|
||||
{
|
||||
if (nLastTry && nLastTry >= nNow-60) // never remove things tried the last minute
|
||||
return false;
|
||||
|
||||
if (nTime > nNow + 10*60) // came in a flying DeLorean
|
||||
return true;
|
||||
|
||||
if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*86400) // not seen in over a month
|
||||
return true;
|
||||
|
||||
if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried three times and never a success
|
||||
return true;
|
||||
|
||||
if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*86400 && nAttempts>=ADDRMAN_MAX_FAILURES) // 10 successive failures in the last week
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
double CAddrInfo::GetChance(int64 nNow) const
|
||||
{
|
||||
double fChance = 1.0;
|
||||
|
||||
int64 nSinceLastSeen = nNow - nTime;
|
||||
int64 nSinceLastTry = nNow - nLastTry;
|
||||
|
||||
if (nSinceLastSeen < 0) nSinceLastSeen = 0;
|
||||
if (nSinceLastTry < 0) nSinceLastTry = 0;
|
||||
|
||||
fChance *= 600.0 / (600.0 + nSinceLastSeen);
|
||||
|
||||
// deprioritize very recent attempts away
|
||||
if (nSinceLastTry < 60*10)
|
||||
fChance *= 0.01;
|
||||
|
||||
// deprioritize 50% after each failed attempt
|
||||
for (int n=0; n<nAttempts; n++)
|
||||
fChance /= 1.5;
|
||||
|
||||
return fChance;
|
||||
}
|
||||
|
||||
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int *pnId)
|
||||
{
|
||||
std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
|
||||
if (it == mapAddr.end())
|
||||
return NULL;
|
||||
if (pnId)
|
||||
*pnId = (*it).second;
|
||||
std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
|
||||
if (it2 != mapInfo.end())
|
||||
return &(*it2).second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId)
|
||||
{
|
||||
int nId = nIdCount++;
|
||||
mapInfo[nId] = CAddrInfo(addr, addrSource);
|
||||
mapAddr[addr] = nId;
|
||||
mapInfo[nId].nRandomPos = vRandom.size();
|
||||
vRandom.push_back(nId);
|
||||
if (pnId)
|
||||
*pnId = nId;
|
||||
return &mapInfo[nId];
|
||||
}
|
||||
|
||||
void CAddrMan::SwapRandom(int nRndPos1, int nRndPos2)
|
||||
{
|
||||
if (nRndPos1 == nRndPos2)
|
||||
return;
|
||||
|
||||
int nId1 = vRandom[nRndPos1];
|
||||
int nId2 = vRandom[nRndPos2];
|
||||
|
||||
mapInfo[nId1].nRandomPos = nRndPos2;
|
||||
mapInfo[nId2].nRandomPos = nRndPos1;
|
||||
|
||||
vRandom[nRndPos1] = nId2;
|
||||
vRandom[nRndPos2] = nId1;
|
||||
}
|
||||
|
||||
int CAddrMan::SelectTried(int nKBucket)
|
||||
{
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
|
||||
// random shuffle the first few elements (using the entire list)
|
||||
// find the least recently tried among them
|
||||
int64 nOldest = -1;
|
||||
for (int i=0; i<ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i<vTried.size(); i++)
|
||||
{
|
||||
int 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)
|
||||
nOldest = nTemp;
|
||||
}
|
||||
|
||||
return nOldest;
|
||||
}
|
||||
|
||||
int CAddrMan::ShrinkNew(int nUBucket)
|
||||
{
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// first look for deletable items
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (info.IsTerrible())
|
||||
{
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
SwapRandom(info.nRandomPos, vRandom.size()-1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(*it);
|
||||
nNew--;
|
||||
}
|
||||
vNew.erase(it);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, select four randomly, and pick the oldest of those to replace
|
||||
int n[4] = {GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size())};
|
||||
int nI = 0;
|
||||
int nOldest = -1;
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
|
||||
{
|
||||
if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
|
||||
nOldest = *it;
|
||||
}
|
||||
nI++;
|
||||
}
|
||||
CAddrInfo &info = mapInfo[nOldest];
|
||||
if (--info.nRefCount == 0)
|
||||
{
|
||||
SwapRandom(info.nRandomPos, vRandom.size()-1);
|
||||
vRandom.pop_back();
|
||||
mapAddr.erase(info);
|
||||
mapInfo.erase(nOldest);
|
||||
nNew--;
|
||||
}
|
||||
vNew.erase(nOldest);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
|
||||
{
|
||||
// remove the entry from all new buckets
|
||||
for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
|
||||
{
|
||||
if ((*it).erase(nId))
|
||||
info.nRefCount--;
|
||||
}
|
||||
nNew--;
|
||||
|
||||
// what tried bucket to move the entry to
|
||||
int nKBucket = info.GetTriedBucket(nKey);
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
|
||||
// first check whether there is place to just add it
|
||||
if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
|
||||
{
|
||||
vTried.push_back(nId);
|
||||
nTried++;
|
||||
info.fInTried = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, find an item to evict
|
||||
int nPos = SelectTried(nKBucket);
|
||||
|
||||
// find which new bucket it belongs to
|
||||
int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
|
||||
// remove the to-be-replaced tried entry from the tried set
|
||||
CAddrInfo& infoOld = mapInfo[vTried[nPos]];
|
||||
infoOld.fInTried = false;
|
||||
infoOld.nRefCount = 1;
|
||||
// do not update nTried, as we are going to move something else there immediately
|
||||
|
||||
// check whether there is place in that one,
|
||||
if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE)
|
||||
{
|
||||
// if so, move it back there
|
||||
vNew.insert(vTried[nPos]);
|
||||
} else {
|
||||
// otherwise, move it to the new bucket nId came from (there is certainly place there)
|
||||
vvNew[nOrigin].insert(vTried[nPos]);
|
||||
}
|
||||
nNew++;
|
||||
|
||||
vTried[nPos] = nId;
|
||||
// we just overwrote an entry in vTried; no need to update nTried
|
||||
info.fInTried = true;
|
||||
return;
|
||||
}
|
||||
|
||||
void CAddrMan::Good_(const CService &addr, int64 nTime)
|
||||
{
|
||||
// printf("Good: addr=%s\n", addr.ToString().c_str());
|
||||
|
||||
int nId;
|
||||
CAddrInfo *pinfo = Find(addr, &nId);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo &info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
info.nLastSuccess = nTime;
|
||||
info.nLastTry = nTime;
|
||||
info.nTime = nTime;
|
||||
info.nAttempts = 0;
|
||||
|
||||
// if it is already in the tried set, don't do anything else
|
||||
if (info.fInTried)
|
||||
return;
|
||||
|
||||
// find a bucket it is in now
|
||||
int nRnd = GetRandInt(vvNew.size());
|
||||
int nUBucket = -1;
|
||||
for (int n = 0; n < vvNew.size(); n++)
|
||||
{
|
||||
int nB = (n+nRnd) % vvNew.size();
|
||||
std::set<int> &vNew = vvNew[nB];
|
||||
if (vNew.count(nId))
|
||||
{
|
||||
nUBucket = nB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if no bucket is found, something bad happened;
|
||||
// TODO: maybe re-add the node, but for now, just bail out
|
||||
if (nUBucket == -1) return;
|
||||
|
||||
printf("Moving %s to tried\n", addr.ToString().c_str());
|
||||
|
||||
// move nId to the tried tables
|
||||
MakeTried(info, nId, nUBucket);
|
||||
}
|
||||
|
||||
bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty)
|
||||
{
|
||||
if (!addr.IsRoutable())
|
||||
return false;
|
||||
|
||||
bool fNew = false;
|
||||
int nId;
|
||||
CAddrInfo *pinfo = Find(addr, &nId);
|
||||
|
||||
if (pinfo)
|
||||
{
|
||||
// periodically update nTime
|
||||
bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
|
||||
int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
|
||||
if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty))
|
||||
pinfo->nTime = max((int64)0, addr.nTime - nTimePenalty);
|
||||
|
||||
// add services
|
||||
pinfo->nServices |= addr.nServices;
|
||||
|
||||
// do not update if no new information is present
|
||||
if (!addr.nTime || pinfo->nTime && addr.nTime <= pinfo->nTime)
|
||||
return false;
|
||||
|
||||
// do not update if the entry was already in the "tried" table
|
||||
if (pinfo->fInTried)
|
||||
return false;
|
||||
|
||||
// do not update if the max reference count is reached
|
||||
if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
|
||||
return false;
|
||||
|
||||
// stochastic test: previous nRefCount == N: 2^N times harder to increase it
|
||||
int nFactor = 1;
|
||||
for (int n=0; n<pinfo->nRefCount; n++)
|
||||
nFactor *= 2;
|
||||
if (nFactor > 1 && (GetRandInt(nFactor) != 0))
|
||||
return false;
|
||||
} else {
|
||||
pinfo = Create(addr, source, &nId);
|
||||
pinfo->nTime = max((int64)0, (int64)pinfo->nTime - nTimePenalty);
|
||||
// printf("Added %s [nTime=%fhr]\n", pinfo->ToString().c_str(), (GetAdjustedTime() - pinfo->nTime) / 3600.0);
|
||||
nNew++;
|
||||
fNew = true;
|
||||
}
|
||||
|
||||
int nUBucket = pinfo->GetNewBucket(nKey, source);
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
if (!vNew.count(nId))
|
||||
{
|
||||
pinfo->nRefCount++;
|
||||
if (vNew.size() == ADDRMAN_NEW_BUCKET_SIZE)
|
||||
ShrinkNew(nUBucket);
|
||||
vvNew[nUBucket].insert(nId);
|
||||
}
|
||||
return fNew;
|
||||
}
|
||||
|
||||
void CAddrMan::Attempt_(const CService &addr, int64 nTime)
|
||||
{
|
||||
CAddrInfo *pinfo = Find(addr);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo &info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
info.nLastTry = nTime;
|
||||
info.nAttempts++;
|
||||
}
|
||||
|
||||
CAddress CAddrMan::Select_(int nUnkBias)
|
||||
{
|
||||
if (size() == 0)
|
||||
return CAddress();
|
||||
|
||||
double nCorTried = sqrt(nTried) * (100.0 - nUnkBias);
|
||||
double nCorNew = sqrt(nNew) * nUnkBias;
|
||||
if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried)
|
||||
{
|
||||
// use a tried node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
int nKBucket = GetRandInt(vvTried.size());
|
||||
std::vector<int> &vTried = vvTried[nKBucket];
|
||||
if (vTried.size() == 0) continue;
|
||||
int nPos = GetRandInt(vTried.size());
|
||||
CAddrInfo &info = mapInfo[vTried[nPos]];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
} else {
|
||||
// use an new node
|
||||
double fChanceFactor = 1.0;
|
||||
while(1)
|
||||
{
|
||||
int nUBucket = GetRandInt(vvNew.size());
|
||||
std::set<int> &vNew = vvNew[nUBucket];
|
||||
if (vNew.size() == 0) continue;
|
||||
int nPos = GetRandInt(vNew.size());
|
||||
std::set<int>::iterator it = vNew.begin();
|
||||
while (nPos--)
|
||||
it++;
|
||||
CAddrInfo &info = mapInfo[*it];
|
||||
if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
|
||||
return info;
|
||||
fChanceFactor *= 1.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
int CAddrMan::Check_()
|
||||
{
|
||||
std::set<int> setTried;
|
||||
std::map<int, int> mapNew;
|
||||
|
||||
if (vRandom.size() != nTried + nNew) return -7;
|
||||
|
||||
for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++)
|
||||
{
|
||||
int n = (*it).first;
|
||||
CAddrInfo &info = (*it).second;
|
||||
if (info.fInTried)
|
||||
{
|
||||
|
||||
if (!info.nLastSuccess) return -1;
|
||||
if (info.nRefCount) return -2;
|
||||
setTried.insert(n);
|
||||
} else {
|
||||
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return -3;
|
||||
if (!info.nRefCount) return -4;
|
||||
mapNew[n] = info.nRefCount;
|
||||
}
|
||||
if (mapAddr[info] != n) return -5;
|
||||
if (info.nRandomPos<0 || info.nRandomPos>=vRandom.size() || vRandom[info.nRandomPos] != n) return -14;
|
||||
if (info.nLastTry < 0) return -6;
|
||||
if (info.nLastSuccess < 0) return -8;
|
||||
}
|
||||
|
||||
if (setTried.size() != nTried) return -9;
|
||||
if (mapNew.size() != nNew) return -10;
|
||||
|
||||
for (int n=0; n<vvTried.size(); n++)
|
||||
{
|
||||
std::vector<int> &vTried = vvTried[n];
|
||||
for (std::vector<int>::iterator it = vTried.begin(); it != vTried.end(); it++)
|
||||
{
|
||||
if (!setTried.count(*it)) return -11;
|
||||
setTried.erase(*it);
|
||||
}
|
||||
}
|
||||
|
||||
for (int n=0; n<vvNew.size(); n++)
|
||||
{
|
||||
std::set<int> &vNew = vvNew[n];
|
||||
for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
|
||||
{
|
||||
if (!mapNew.count(*it)) return -12;
|
||||
if (--mapNew[*it] == 0)
|
||||
mapNew.erase(*it);
|
||||
}
|
||||
}
|
||||
|
||||
if (setTried.size()) return -13;
|
||||
if (mapNew.size()) return -15;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr)
|
||||
{
|
||||
int nNodes = ADDRMAN_GETADDR_MAX_PCT*vRandom.size()/100;
|
||||
if (nNodes > ADDRMAN_GETADDR_MAX)
|
||||
nNodes = ADDRMAN_GETADDR_MAX;
|
||||
|
||||
// perform a random shuffle over the first nNodes elements of vRandom (selecting from all)
|
||||
for (int n = 0; n<nNodes; n++)
|
||||
{
|
||||
int nRndPos = GetRandInt(vRandom.size() - n) + n;
|
||||
SwapRandom(n, nRndPos);
|
||||
vAddr.push_back(mapInfo[vRandom[n]]);
|
||||
}
|
||||
}
|
||||
|
||||
void CAddrMan::Connected_(const CService &addr, int64 nTime)
|
||||
{
|
||||
CAddrInfo *pinfo = Find(addr);
|
||||
|
||||
// if not found, bail out
|
||||
if (!pinfo)
|
||||
return;
|
||||
|
||||
CAddrInfo &info = *pinfo;
|
||||
|
||||
// check whether we are talking about the exact same CService (including same port)
|
||||
if (info != addr)
|
||||
return;
|
||||
|
||||
// update info
|
||||
int64 nUpdateInterval = 20 * 60;
|
||||
if (nTime - info.nTime > nUpdateInterval)
|
||||
info.nTime = nTime;
|
||||
}
|
||||
500
src/addrman.h
Normal file
500
src/addrman.h
Normal file
@@ -0,0 +1,500 @@
|
||||
// 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.
|
||||
#ifndef _BITCOIN_ADDRMAN
|
||||
#define _BITCOIN_ADDRMAN 1
|
||||
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
||||
/** Extended statistics about a CAddress */
|
||||
class CAddrInfo : public CAddress
|
||||
{
|
||||
private:
|
||||
// where knowledge about this address first came from
|
||||
CNetAddr source;
|
||||
|
||||
// last succesfull connection by us
|
||||
int64 nLastSuccess;
|
||||
|
||||
// last try whatsoever by us:
|
||||
// int64 CAddress::nLastTry
|
||||
|
||||
// connection attempts since last succesful attempt
|
||||
int nAttempts;
|
||||
|
||||
// reference count in new sets (memory only)
|
||||
int nRefCount;
|
||||
|
||||
// in tried set? (memory only)
|
||||
bool fInTried;
|
||||
|
||||
// position in vRandom
|
||||
int nRandomPos;
|
||||
|
||||
friend class CAddrMan;
|
||||
|
||||
public:
|
||||
|
||||
IMPLEMENT_SERIALIZE(
|
||||
CAddress* pthis = (CAddress*)(this);
|
||||
READWRITE(*pthis);
|
||||
READWRITE(source);
|
||||
READWRITE(nLastSuccess);
|
||||
READWRITE(nAttempts);
|
||||
)
|
||||
|
||||
void Init()
|
||||
{
|
||||
nLastSuccess = 0;
|
||||
nLastTry = 0;
|
||||
nAttempts = 0;
|
||||
nRefCount = 0;
|
||||
fInTried = false;
|
||||
nRandomPos = -1;
|
||||
}
|
||||
|
||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddrInfo() : CAddress(), source()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// Calculate in which "tried" bucket this entry belongs
|
||||
int GetTriedBucket(const std::vector<unsigned char> &nKey) const;
|
||||
|
||||
// Calculate in which "new" bucket this entry belongs, given a certain source
|
||||
int GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const;
|
||||
|
||||
// Calculate in which "new" bucket this entry belongs, using its default source
|
||||
int GetNewBucket(const std::vector<unsigned char> &nKey) const
|
||||
{
|
||||
return GetNewBucket(nKey, source);
|
||||
}
|
||||
|
||||
// Determine whether the statistics about this entry are bad enough so that it can just be deleted
|
||||
bool IsTerrible(int64 nNow = GetAdjustedTime()) const;
|
||||
|
||||
// Calculate the relative chance this entry should be given when selecting nodes to connect to
|
||||
double GetChance(int64 nNow = GetAdjustedTime()) const;
|
||||
|
||||
};
|
||||
|
||||
// Stochastic address manager
|
||||
//
|
||||
// Design goals:
|
||||
// * Only keep a limited number of addresses around, so that addr.dat and memory requirements do not grow without bound.
|
||||
// * Keep the address tables in-memory, and asynchronously dump the entire to able in addr.dat.
|
||||
// * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
|
||||
//
|
||||
// To that end:
|
||||
// * Addresses are organized into buckets.
|
||||
// * Address that have not yet been tried go into 256 "new" buckets.
|
||||
// * Based on the address range (/16 for IPv4) of source of the information, 32 buckets are selected at random
|
||||
// * The actual bucket is chosen from one of these, based on the range the address itself is located.
|
||||
// * One single address can occur in up to 4 different buckets, to increase selection chances for addresses that
|
||||
// are seen frequently. The chance for increasing this multiplicity decreases exponentially.
|
||||
// * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
|
||||
// ones) is removed from it first.
|
||||
// * Addresses of nodes that are known to be accessible go into 64 "tried" buckets.
|
||||
// * Each address range selects at random 4 of these buckets.
|
||||
// * The actual bucket is chosen from one of these, based on the full address.
|
||||
// * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently
|
||||
// tried ones) is evicted from it, back to the "new" buckets.
|
||||
// * 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.
|
||||
|
||||
// total number of buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_COUNT 64
|
||||
|
||||
// maximum allowed number of entries in buckets for tried addresses
|
||||
#define ADDRMAN_TRIED_BUCKET_SIZE 64
|
||||
|
||||
// total number of buckets for new addresses
|
||||
#define ADDRMAN_NEW_BUCKET_COUNT 256
|
||||
|
||||
// maximum allowed number of entries in buckets for new addresses
|
||||
#define ADDRMAN_NEW_BUCKET_SIZE 64
|
||||
|
||||
// over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
|
||||
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4
|
||||
|
||||
// over how many buckets entries with new addresses originating from a single group are spread
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32
|
||||
|
||||
// in how many buckets for entries with new addresses a single address may occur
|
||||
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4
|
||||
|
||||
// how many entries in a bucket with tried addresses are inspected, when selecting one to replace
|
||||
#define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4
|
||||
|
||||
// how old addresses can maximally be
|
||||
#define ADDRMAN_HORIZON_DAYS 30
|
||||
|
||||
// after how many failed attempts we give up on a new node
|
||||
#define ADDRMAN_RETRIES 3
|
||||
|
||||
// how many successive failures are allowed ...
|
||||
#define ADDRMAN_MAX_FAILURES 10
|
||||
|
||||
// ... in at least this many days
|
||||
#define ADDRMAN_MIN_FAIL_DAYS 7
|
||||
|
||||
// the maximum percentage of nodes to return in a getaddr call
|
||||
#define ADDRMAN_GETADDR_MAX_PCT 23
|
||||
|
||||
// the maximum number of nodes to return in a getaddr call
|
||||
#define ADDRMAN_GETADDR_MAX 2500
|
||||
|
||||
/** Stochastical (IP) address manager */
|
||||
class CAddrMan
|
||||
{
|
||||
private:
|
||||
// critical section to protect the inner data structures
|
||||
mutable CCriticalSection cs;
|
||||
|
||||
// secret key to randomize bucket select with
|
||||
std::vector<unsigned char> nKey;
|
||||
|
||||
// last used nId
|
||||
int nIdCount;
|
||||
|
||||
// table with information about all nId's
|
||||
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
|
||||
std::vector<int> vRandom;
|
||||
|
||||
// number of "tried" entries
|
||||
int nTried;
|
||||
|
||||
// list of "tried" buckets
|
||||
std::vector<std::vector<int> > vvTried;
|
||||
|
||||
// number of (unique) "new" entries
|
||||
int nNew;
|
||||
|
||||
// list of "new" buckets
|
||||
std::vector<std::set<int> > vvNew;
|
||||
|
||||
protected:
|
||||
|
||||
// Find an entry.
|
||||
CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL);
|
||||
|
||||
// find an entry, creating it if necessary.
|
||||
// nTime and nServices of found node is updated, if necessary.
|
||||
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
|
||||
|
||||
// Swap two elements in vRandom.
|
||||
void SwapRandom(int nRandomPos1, int nRandomPos2);
|
||||
|
||||
// Return position in given bucket to replace.
|
||||
int SelectTried(int nKBucket);
|
||||
|
||||
// Remove an element from a "new" bucket.
|
||||
// This is the only place where actual deletes occur.
|
||||
// They are never deleted while in the "tried" table, only possibly evicted back to the "new" table.
|
||||
int ShrinkNew(int nUBucket);
|
||||
|
||||
// Move an entry from the "new" table(s) to the "tried" table
|
||||
// @pre vvUnkown[nOrigin].count(nId) != 0
|
||||
void MakeTried(CAddrInfo& info, int nId, int nOrigin);
|
||||
|
||||
// Mark an entry "good", possibly moving it from "new" to "tried".
|
||||
void Good_(const CService &addr, int64 nTime);
|
||||
|
||||
// Add an entry to the "new" table.
|
||||
bool Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty);
|
||||
|
||||
// Mark an entry as attempted to connect.
|
||||
void Attempt_(const CService &addr, int64 nTime);
|
||||
|
||||
// Select an address to connect to.
|
||||
// nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100)
|
||||
CAddress Select_(int nUnkBias);
|
||||
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
// Perform consistency check. Returns an error code or zero.
|
||||
int Check_();
|
||||
#endif
|
||||
|
||||
// Select several addresses at once.
|
||||
void GetAddr_(std::vector<CAddress> &vAddr);
|
||||
|
||||
// Mark an entry as currently-connected-to.
|
||||
void Connected_(const CService &addr, int64 nTime);
|
||||
|
||||
public:
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(({
|
||||
// serialized format:
|
||||
// * version byte (currently 0)
|
||||
// * nKey
|
||||
// * nNew
|
||||
// * nTried
|
||||
// * number of "new" buckets
|
||||
// * all nNew addrinfo's in vvNew
|
||||
// * all nTried addrinfo's in vvTried
|
||||
// * for each bucket:
|
||||
// * number of elements
|
||||
// * for each element: index
|
||||
//
|
||||
// Notice that vvTried, mapAddr and vVector are never encoded explicitly;
|
||||
// they are instead reconstructed from the other information.
|
||||
//
|
||||
// vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
|
||||
// otherwise it is reconstructed as well.
|
||||
//
|
||||
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
|
||||
// changes to the ADDRMAN_ parameters without breaking the on-disk structure.
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
unsigned char nVersion = 0;
|
||||
READWRITE(nVersion);
|
||||
READWRITE(nKey);
|
||||
READWRITE(nNew);
|
||||
READWRITE(nTried);
|
||||
|
||||
CAddrMan *am = const_cast<CAddrMan*>(this);
|
||||
if (fWrite)
|
||||
{
|
||||
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
|
||||
READWRITE(nUBuckets);
|
||||
std::map<int, int> mapUnkIds;
|
||||
int nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
|
||||
{
|
||||
if (nIds == nNew) break; // this means nNew was wrong, oh ow
|
||||
mapUnkIds[(*it).first] = nIds;
|
||||
CAddrInfo &info = (*it).second;
|
||||
if (info.nRefCount)
|
||||
{
|
||||
READWRITE(info);
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
nIds = 0;
|
||||
for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
|
||||
{
|
||||
if (nIds == nTried) break; // this means nTried was wrong, oh ow
|
||||
CAddrInfo &info = (*it).second;
|
||||
if (info.fInTried)
|
||||
{
|
||||
READWRITE(info);
|
||||
nIds++;
|
||||
}
|
||||
}
|
||||
for (std::vector<std::set<int> >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++)
|
||||
{
|
||||
const std::set<int> &vNew = (*it);
|
||||
int nSize = vNew.size();
|
||||
READWRITE(nSize);
|
||||
for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
|
||||
{
|
||||
int nIndex = mapUnkIds[*it2];
|
||||
READWRITE(nIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int nUBuckets = 0;
|
||||
READWRITE(nUBuckets);
|
||||
am->nIdCount = 0;
|
||||
am->mapInfo.clear();
|
||||
am->mapAddr.clear();
|
||||
am->vRandom.clear();
|
||||
am->vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
|
||||
am->vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
|
||||
for (int n = 0; n < am->nNew; n++)
|
||||
{
|
||||
CAddrInfo &info = am->mapInfo[n];
|
||||
READWRITE(info);
|
||||
am->mapAddr[info] = n;
|
||||
info.nRandomPos = vRandom.size();
|
||||
am->vRandom.push_back(n);
|
||||
if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
|
||||
{
|
||||
am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
|
||||
info.nRefCount++;
|
||||
}
|
||||
}
|
||||
am->nIdCount = am->nNew;
|
||||
int nLost = 0;
|
||||
for (int n = 0; n < am->nTried; n++)
|
||||
{
|
||||
CAddrInfo info;
|
||||
READWRITE(info);
|
||||
std::vector<int> &vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
|
||||
if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
|
||||
{
|
||||
info.nRandomPos = vRandom.size();
|
||||
info.fInTried = true;
|
||||
am->vRandom.push_back(am->nIdCount);
|
||||
am->mapInfo[am->nIdCount] = info;
|
||||
am->mapAddr[info] = am->nIdCount;
|
||||
vTried.push_back(am->nIdCount);
|
||||
am->nIdCount++;
|
||||
} else {
|
||||
nLost++;
|
||||
}
|
||||
}
|
||||
am->nTried -= nLost;
|
||||
for (int b = 0; b < nUBuckets; b++)
|
||||
{
|
||||
std::set<int> &vNew = am->vvNew[b];
|
||||
int nSize = 0;
|
||||
READWRITE(nSize);
|
||||
for (int n = 0; n < nSize; n++)
|
||||
{
|
||||
int nIndex = 0;
|
||||
READWRITE(nIndex);
|
||||
CAddrInfo &info = am->mapInfo[nIndex];
|
||||
if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
|
||||
{
|
||||
info.nRefCount++;
|
||||
vNew.insert(nIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});)
|
||||
|
||||
CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
|
||||
{
|
||||
nKey.resize(32);
|
||||
RAND_bytes(&nKey[0], 32);
|
||||
|
||||
nIdCount = 0;
|
||||
nTried = 0;
|
||||
nNew = 0;
|
||||
}
|
||||
|
||||
// Return the number of (unique) addresses in all tables.
|
||||
int size()
|
||||
{
|
||||
return vRandom.size();
|
||||
}
|
||||
|
||||
// Consistency check
|
||||
void Check()
|
||||
{
|
||||
#ifdef DEBUG_ADDRMAN
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
int err;
|
||||
if ((err=Check_()))
|
||||
printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Add a single address.
|
||||
bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
|
||||
{
|
||||
bool fRet = false;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
fRet |= Add_(addr, source, nTimePenalty);
|
||||
Check();
|
||||
}
|
||||
if (fRet)
|
||||
printf("Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
|
||||
return fRet;
|
||||
}
|
||||
|
||||
// Add multiple addresses.
|
||||
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
|
||||
{
|
||||
int nAdd = 0;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
|
||||
nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
|
||||
Check();
|
||||
}
|
||||
if (nAdd)
|
||||
printf("Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
|
||||
return nAdd > 0;
|
||||
}
|
||||
|
||||
// Mark an entry as accessible.
|
||||
void Good(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
Good_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
|
||||
// Mark an entry as connection attempted to.
|
||||
void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
Attempt_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
|
||||
// Choose an address to connect to.
|
||||
// nUnkBias determines how much "new" entries are favored over "tried" ones (0-100).
|
||||
CAddress Select(int nUnkBias = 50)
|
||||
{
|
||||
CAddress addrRet;
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
addrRet = Select_(nUnkBias);
|
||||
Check();
|
||||
}
|
||||
return addrRet;
|
||||
}
|
||||
|
||||
// Return a bunch of addresses, selected at random.
|
||||
std::vector<CAddress> GetAddr()
|
||||
{
|
||||
Check();
|
||||
std::vector<CAddress> vAddr;
|
||||
CRITICAL_BLOCK(cs)
|
||||
GetAddr_(vAddr);
|
||||
Check();
|
||||
return vAddr;
|
||||
}
|
||||
|
||||
// Mark an entry as currently-connected-to.
|
||||
void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
|
||||
{
|
||||
CRITICAL_BLOCK(cs)
|
||||
{
|
||||
Check();
|
||||
Connected_(addr, nTime);
|
||||
Check();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
121
src/base58.h
121
src/base58.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin Developers
|
||||
// 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.
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "bignum.h"
|
||||
#include "key.h"
|
||||
|
||||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
|
||||
// Encode a byte sequence as a base58-encoded string
|
||||
inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
@@ -62,11 +63,14 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char
|
||||
return str;
|
||||
}
|
||||
|
||||
// Encode a byte vector as a base58-encoded string
|
||||
inline std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
return EncodeBase58(&vch[0], &vch[0] + vch.size());
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string psz into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
@@ -113,6 +117,8 @@ inline bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string str into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58(str.c_str(), vchRet);
|
||||
@@ -121,7 +127,7 @@ inline bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vch
|
||||
|
||||
|
||||
|
||||
|
||||
// Encode a byte vector to a base58-encoded string, including checksum
|
||||
inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
|
||||
{
|
||||
// add 4-byte hash check to the end
|
||||
@@ -131,6 +137,8 @@ inline std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
|
||||
return EncodeBase58(vch);
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string psz that includes a checksum, into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
if (!DecodeBase58(psz, vchRet))
|
||||
@@ -150,6 +158,8 @@ inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRe
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decode a base58-encoded string str that includes a checksum, into byte vector vchRet
|
||||
// returns true if decoding is succesful
|
||||
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
|
||||
{
|
||||
return DecodeBase58Check(str.c_str(), vchRet);
|
||||
@@ -159,11 +169,14 @@ inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>
|
||||
|
||||
|
||||
|
||||
|
||||
/** Base class for all base58-encoded data */
|
||||
class CBase58Data
|
||||
{
|
||||
protected:
|
||||
// the version byte
|
||||
unsigned char nVersion;
|
||||
|
||||
// the actually encoded data
|
||||
std::vector<unsigned char> vchData;
|
||||
|
||||
CBase58Data()
|
||||
@@ -174,6 +187,7 @@ protected:
|
||||
|
||||
~CBase58Data()
|
||||
{
|
||||
// zero the memory, as it may contain sensitive data
|
||||
if (!vchData.empty())
|
||||
memset(&vchData[0], 0, vchData.size());
|
||||
}
|
||||
@@ -238,19 +252,38 @@ public:
|
||||
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
|
||||
};
|
||||
|
||||
|
||||
/** 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 : public CBase58Data
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
PUBKEY_ADDRESS = 0,
|
||||
SCRIPT_ADDRESS = 5,
|
||||
PUBKEY_ADDRESS_TEST = 111,
|
||||
SCRIPT_ADDRESS_TEST = 196,
|
||||
};
|
||||
|
||||
bool SetHash160(const uint160& hash160)
|
||||
{
|
||||
SetData(fTestNet ? 111 : 0, &hash160, 20);
|
||||
SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &hash160, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
void SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
return SetHash160(Hash160(vchPubKey));
|
||||
SetHash160(Hash160(vchPubKey));
|
||||
}
|
||||
|
||||
bool SetScriptHash160(const uint160& hash160)
|
||||
{
|
||||
SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &hash160, 20);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
@@ -259,10 +292,21 @@ public:
|
||||
bool fExpectTestNet = false;
|
||||
switch(nVersion)
|
||||
{
|
||||
case 0:
|
||||
case PUBKEY_ADDRESS:
|
||||
nExpectedSize = 20; // Hash of public key
|
||||
fExpectTestNet = false;
|
||||
break;
|
||||
case SCRIPT_ADDRESS:
|
||||
nExpectedSize = 20; // Hash of CScript
|
||||
fExpectTestNet = false;
|
||||
break;
|
||||
|
||||
case 111:
|
||||
case PUBKEY_ADDRESS_TEST:
|
||||
nExpectedSize = 20;
|
||||
fExpectTestNet = true;
|
||||
break;
|
||||
case SCRIPT_ADDRESS_TEST:
|
||||
nExpectedSize = 20;
|
||||
fExpectTestNet = true;
|
||||
break;
|
||||
|
||||
@@ -271,6 +315,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()
|
||||
{
|
||||
@@ -305,4 +357,53 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** A base58-encoded secret key */
|
||||
class CBitcoinSecret : public CBase58Data
|
||||
{
|
||||
public:
|
||||
void SetSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
assert(vchSecret.size() == 32);
|
||||
SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size());
|
||||
if (fCompressed)
|
||||
vchData.push_back(1);
|
||||
}
|
||||
|
||||
CSecret GetSecret(bool &fCompressedOut)
|
||||
{
|
||||
CSecret vchSecret;
|
||||
vchSecret.resize(32);
|
||||
memcpy(&vchSecret[0], &vchData[0], 32);
|
||||
fCompressedOut = vchData.size() == 33;
|
||||
return vchSecret;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
bool fExpectTestNet = false;
|
||||
switch(nVersion)
|
||||
{
|
||||
case 128:
|
||||
break;
|
||||
|
||||
case 239:
|
||||
fExpectTestNet = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
|
||||
}
|
||||
|
||||
CBitcoinSecret(const CSecret& vchSecret, bool fCompressed)
|
||||
{
|
||||
SetSecret(vchSecret, fCompressed);
|
||||
}
|
||||
|
||||
CBitcoinSecret()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
19
src/bignum.h
19
src/bignum.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_BIGNUM_H
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/** Errors thrown by the bignum class */
|
||||
class bignum_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
@@ -18,7 +19,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** RAII encapsulated BN_CTX (OpenSSL bignum context) */
|
||||
class CAutoBN_CTX
|
||||
{
|
||||
protected:
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** C++ wrapper for BIGNUM (OpenSSl bignum) */
|
||||
class CBigNum : public BIGNUM
|
||||
{
|
||||
public:
|
||||
@@ -115,9 +116,9 @@ public:
|
||||
{
|
||||
unsigned long n = BN_get_word(this);
|
||||
if (!BN_is_negative(this))
|
||||
return (n > INT_MAX ? INT_MAX : n);
|
||||
return (n > std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
|
||||
else
|
||||
return (n > INT_MAX ? INT_MIN : -(int)n);
|
||||
return (n > std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
|
||||
}
|
||||
|
||||
void setint64(int64 n)
|
||||
@@ -243,7 +244,7 @@ public:
|
||||
std::vector<unsigned char> getvch() const
|
||||
{
|
||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
||||
if (nSize < 4)
|
||||
if (nSize <= 4)
|
||||
return std::vector<unsigned char>();
|
||||
std::vector<unsigned char> vch(nSize);
|
||||
BN_bn2mpi(this, &vch[0]);
|
||||
@@ -338,19 +339,19 @@ public:
|
||||
return ToString(16);
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
|
||||
unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
{
|
||||
return ::GetSerializeSize(getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
|
||||
void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
{
|
||||
::Serialize(s, getvch(), nType, nVersion);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
|
||||
void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
|
||||
{
|
||||
std::vector<unsigned char> vch;
|
||||
::Unserialize(s, vch, nType, nVersion);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// 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.
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#include "init.h"
|
||||
#undef printf
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/iostreams/concepts.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#ifdef USE_SSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -36,9 +38,13 @@ void ThreadRPCServer2(void* parg);
|
||||
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
||||
extern map<string, rpcfn_type> mapCallTable;
|
||||
|
||||
static std::string strRPCUserColonPass;
|
||||
|
||||
static int64 nWalletUnlockTime;
|
||||
static CCriticalSection cs_nWalletUnlockTime;
|
||||
|
||||
extern Value dumpprivkey(const Array& params, bool fHelp);
|
||||
extern Value importprivkey(const Array& params, bool fHelp);
|
||||
|
||||
Object JSONRPCError(int code, const string& message)
|
||||
{
|
||||
@@ -48,22 +54,35 @@ Object JSONRPCError(int code, const string& message)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void PrintConsole(const std::string &format, ...)
|
||||
double GetDifficulty(const CBlockIndex* blockindex = NULL)
|
||||
{
|
||||
char buffer[50000];
|
||||
int limit = sizeof(buffer);
|
||||
va_list arg_ptr;
|
||||
va_start(arg_ptr, format);
|
||||
int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
|
||||
va_end(arg_ptr);
|
||||
if (ret < 0 || ret >= limit)
|
||||
// Floating point number that is a multiple of the minimum difficulty,
|
||||
// minimum difficulty = 1.0.
|
||||
if (blockindex == NULL)
|
||||
{
|
||||
ret = limit - 1;
|
||||
buffer[limit-1] = 0;
|
||||
if (pindexBest == NULL)
|
||||
return 1.0;
|
||||
else
|
||||
blockindex = pindexBest;
|
||||
}
|
||||
printf("%s", buffer);
|
||||
fprintf(stdout, "%s", buffer);
|
||||
|
||||
int nShift = (blockindex->nBits >> 24) & 0xff;
|
||||
|
||||
double dDiff =
|
||||
(double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
|
||||
|
||||
while (nShift < 29)
|
||||
{
|
||||
dDiff *= 256.0;
|
||||
nShift++;
|
||||
}
|
||||
while (nShift > 29)
|
||||
{
|
||||
dDiff /= 256.0;
|
||||
nShift--;
|
||||
}
|
||||
|
||||
return dDiff;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,9 +102,26 @@ Value ValueFromAmount(int64 amount)
|
||||
return (double)amount / (double)COIN;
|
||||
}
|
||||
|
||||
std::string
|
||||
HexBits(unsigned int nBits)
|
||||
{
|
||||
union {
|
||||
int32_t nBits;
|
||||
char cBits[4];
|
||||
} uBits;
|
||||
uBits.nBits = htonl((int32_t)nBits);
|
||||
return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
|
||||
}
|
||||
|
||||
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
||||
{
|
||||
entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
|
||||
int confirms = wtx.GetDepthInMainChain();
|
||||
entry.push_back(Pair("confirmations", confirms));
|
||||
if (confirms)
|
||||
{
|
||||
entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
|
||||
entry.push_back(Pair("blockindex", wtx.nIndex));
|
||||
}
|
||||
entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
|
||||
entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
|
||||
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
|
||||
@@ -100,6 +136,30 @@ string AccountFromValue(const Value& value)
|
||||
return strAccount;
|
||||
}
|
||||
|
||||
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||
{
|
||||
Object result;
|
||||
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
||||
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK)));
|
||||
result.push_back(Pair("height", blockindex->nHeight));
|
||||
result.push_back(Pair("version", block.nVersion));
|
||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||
result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
|
||||
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
|
||||
result.push_back(Pair("bits", HexBits(block.nBits)));
|
||||
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
|
||||
Array txhashes;
|
||||
BOOST_FOREACH (const CTransaction&tx, block.vtx)
|
||||
txhashes.push_back(tx.GetHash().GetHex());
|
||||
result.push_back(Pair("tx", txhashes));
|
||||
|
||||
if (blockindex->pprev)
|
||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||
if (blockindex->pnext)
|
||||
result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
@@ -126,6 +186,7 @@ Value help(const Array& params, bool fHelp)
|
||||
// We already filter duplicates, but these deprecated screw up the sort order
|
||||
if (strMethod == "getamountreceived" ||
|
||||
strMethod == "getallreceived" ||
|
||||
strMethod == "getblocknumber" || // deprecated
|
||||
(strMethod.find("label") != string::npos))
|
||||
continue;
|
||||
if (strCommand != "" && strMethod != strCommand)
|
||||
@@ -160,10 +221,13 @@ Value stop(const Array& params, bool fHelp)
|
||||
throw runtime_error(
|
||||
"stop\n"
|
||||
"Stop bitcoin server.");
|
||||
|
||||
#ifndef QT_GUI
|
||||
// Shutdown will take long enough that the response should get back
|
||||
CreateThread(Shutdown, NULL);
|
||||
return "bitcoin server stopping";
|
||||
#else
|
||||
throw runtime_error("NYI: cannot shut down GUI with RPC command");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -178,12 +242,13 @@ Value getblockcount(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
|
||||
// deprecated
|
||||
Value getblocknumber(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getblocknumber\n"
|
||||
"Returns the block number of the latest block in the longest block chain.");
|
||||
"Deprecated. Use getblockcount.");
|
||||
|
||||
return nBestHeight;
|
||||
}
|
||||
@@ -200,32 +265,6 @@ Value getconnectioncount(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
|
||||
double GetDifficulty()
|
||||
{
|
||||
// Floating point number that is a multiple of the minimum difficulty,
|
||||
// minimum difficulty = 1.0.
|
||||
|
||||
if (pindexBest == NULL)
|
||||
return 1.0;
|
||||
int nShift = (pindexBest->nBits >> 24) & 0xff;
|
||||
|
||||
double dDiff =
|
||||
(double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
|
||||
|
||||
while (nShift < 29)
|
||||
{
|
||||
dDiff *= 256.0;
|
||||
nShift++;
|
||||
}
|
||||
while (nShift > 29)
|
||||
{
|
||||
dDiff /= 256.0;
|
||||
nShift--;
|
||||
}
|
||||
|
||||
return dDiff;
|
||||
}
|
||||
|
||||
Value getdifficulty(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
@@ -244,7 +283,7 @@ Value getgenerate(const Array& params, bool fHelp)
|
||||
"getgenerate\n"
|
||||
"Returns true or false.");
|
||||
|
||||
return (bool)fGenerateBitcoins;
|
||||
return GetBoolArg("-gen");
|
||||
}
|
||||
|
||||
|
||||
@@ -263,13 +302,11 @@ Value setgenerate(const Array& params, bool fHelp)
|
||||
if (params.size() > 1)
|
||||
{
|
||||
int nGenProcLimit = params[1].get_int();
|
||||
fLimitProcessors = (nGenProcLimit != -1);
|
||||
WriteSetting("fLimitProcessors", fLimitProcessors);
|
||||
if (nGenProcLimit != -1)
|
||||
WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
|
||||
mapArgs["-genproclimit"] = itostr(nGenProcLimit);
|
||||
if (nGenProcLimit == 0)
|
||||
fGenerate = false;
|
||||
}
|
||||
mapArgs["-gen"] = (fGenerate ? "1" : "0");
|
||||
|
||||
GenerateBitcoins(fGenerate, pwalletMain);
|
||||
return Value::null;
|
||||
@@ -297,26 +334,47 @@ Value getinfo(const Array& params, bool fHelp)
|
||||
"Returns an object containing various state info.");
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("version", (int)VERSION));
|
||||
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
|
||||
obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
|
||||
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
|
||||
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
|
||||
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
|
||||
if (pwalletMain->IsCrypted())
|
||||
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
|
||||
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
Value getmininginfo(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getmininginfo\n"
|
||||
"Returns an object containing mining-related information.");
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
||||
obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize));
|
||||
obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx));
|
||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||
obj.push_back(Pair("generate", GetBoolArg("-gen")));
|
||||
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
|
||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||
obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
|
||||
obj.push_back(Pair("testnet", fTestNet));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
Value getnewaddress(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
@@ -525,8 +583,6 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
||||
static const string strMessageMagic = "Bitcoin Signed Message:\n";
|
||||
|
||||
Value signmessage(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
@@ -588,7 +644,7 @@ Value verifymessage(const Array& params, bool fHelp)
|
||||
if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
|
||||
return false;
|
||||
|
||||
return (key.GetAddress() == addr);
|
||||
return (CBitcoinAddress(key.GetPubKey()) == addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -655,7 +711,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
if (params.size() > 1)
|
||||
nMinDepth = params[1].get_int();
|
||||
|
||||
// Get the set of pub keys that have the label
|
||||
// Get the set of pub keys assigned to account
|
||||
string strAccount = AccountFromValue(params[0]);
|
||||
set<CBitcoinAddress> setAddress;
|
||||
GetAccountAddresses(strAccount, setAddress);
|
||||
@@ -671,7 +727,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
CBitcoinAddress address;
|
||||
if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
|
||||
if (ExtractAddress(txout.scriptPubKey, address) && pwalletMain->HaveKey(address) && setAddress.count(address))
|
||||
if (wtx.GetDepthInMainChain() >= nMinDepth)
|
||||
nAmount += txout.nValue;
|
||||
}
|
||||
@@ -924,6 +980,79 @@ Value sendmany(const Array& params, bool fHelp)
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
||||
Value addmultisigaddress(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 2 || params.size() > 3)
|
||||
{
|
||||
string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
|
||||
"Add a nrequired-to-sign multisignature address to the wallet\"\n"
|
||||
"each key is a bitcoin address or hex-encoded public key\n"
|
||||
"If [account] is specified, assign address to [account].";
|
||||
throw runtime_error(msg);
|
||||
}
|
||||
if (!fTestNet)
|
||||
throw runtime_error("addmultisigaddress available only when running -testnet\n");
|
||||
|
||||
int nRequired = params[0].get_int();
|
||||
const Array& keys = params[1].get_array();
|
||||
string strAccount;
|
||||
if (params.size() > 2)
|
||||
strAccount = AccountFromValue(params[2]);
|
||||
|
||||
// Gather public keys
|
||||
if (nRequired < 1 || keys.size() < nRequired)
|
||||
throw runtime_error(
|
||||
strprintf("wrong number of keys"
|
||||
"(got %d, need at least %d)", keys.size(), nRequired));
|
||||
std::vector<CKey> pubkeys;
|
||||
pubkeys.resize(keys.size());
|
||||
for (int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
const std::string& ks = keys[i].get_str();
|
||||
|
||||
// Case 1: bitcoin address and we have full public key:
|
||||
CBitcoinAddress address(ks);
|
||||
if (address.IsValid())
|
||||
{
|
||||
if (address.IsScript())
|
||||
throw runtime_error(
|
||||
strprintf("%s is a pay-to-script address",ks.c_str()));
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
if (!pwalletMain->GetPubKey(address, vchPubKey))
|
||||
throw runtime_error(
|
||||
strprintf("no full public key for address %s",ks.c_str()));
|
||||
if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
|
||||
throw runtime_error(" Invalid public key: "+ks);
|
||||
}
|
||||
|
||||
// Case 2: hex public key
|
||||
else if (IsHex(ks))
|
||||
{
|
||||
vector<unsigned char> vchPubKey = ParseHex(ks);
|
||||
if (vchPubKey.empty() || !pubkeys[i].SetPubKey(vchPubKey))
|
||||
throw runtime_error(" Invalid public key: "+ks);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw runtime_error(" Invalid public key: "+ks);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct using pay-to-script-hash:
|
||||
CScript inner;
|
||||
inner.SetMultisig(nRequired, pubkeys);
|
||||
|
||||
uint160 scriptHash = Hash160(inner);
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey.SetPayToScriptHash(inner);
|
||||
pwalletMain->AddCScript(inner);
|
||||
CBitcoinAddress address;
|
||||
address.SetScriptHash160(scriptHash);
|
||||
|
||||
pwalletMain->SetAddressBookName(address, strAccount);
|
||||
return address.ToString();
|
||||
}
|
||||
|
||||
|
||||
struct tallyitem
|
||||
{
|
||||
@@ -932,7 +1061,7 @@ struct tallyitem
|
||||
tallyitem()
|
||||
{
|
||||
nAmount = 0;
|
||||
nConf = INT_MAX;
|
||||
nConf = std::numeric_limits<int>::max();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -953,6 +1082,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
|
||||
if (wtx.IsCoinBase() || !wtx.IsFinal())
|
||||
continue;
|
||||
|
||||
@@ -963,7 +1093,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
{
|
||||
CBitcoinAddress address;
|
||||
if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
|
||||
if (!ExtractAddress(txout.scriptPubKey, address) || !pwalletMain->HaveKey(address) || !address.IsValid())
|
||||
continue;
|
||||
|
||||
tallyitem& item = mapTally[address];
|
||||
@@ -984,7 +1114,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
continue;
|
||||
|
||||
int64 nAmount = 0;
|
||||
int nConf = INT_MAX;
|
||||
int nConf = std::numeric_limits<int>::max();
|
||||
if (it != mapTally.end())
|
||||
{
|
||||
nAmount = (*it).second.nAmount;
|
||||
@@ -1003,7 +1133,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
obj.push_back(Pair("address", address.ToString()));
|
||||
obj.push_back(Pair("account", strAccount));
|
||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
||||
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
|
||||
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
|
||||
ret.push_back(obj);
|
||||
}
|
||||
}
|
||||
@@ -1017,7 +1147,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
||||
Object obj;
|
||||
obj.push_back(Pair("account", (*it).first));
|
||||
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
|
||||
obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
|
||||
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
|
||||
ret.push_back(obj);
|
||||
}
|
||||
}
|
||||
@@ -1062,6 +1192,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
|
||||
string strSentAccount;
|
||||
list<pair<CBitcoinAddress, int64> > listReceived;
|
||||
list<pair<CBitcoinAddress, int64> > listSent;
|
||||
|
||||
wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
|
||||
|
||||
bool fAllAccounts = (strAccount == string("*"));
|
||||
@@ -1309,7 +1440,7 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||
CBlockIndex *block;
|
||||
for (block = pindexBest;
|
||||
block && block->nHeight > target_height;
|
||||
block = block->pprev);
|
||||
block = block->pprev) { }
|
||||
|
||||
lastblock = block ? block->GetBlockHash() : 0;
|
||||
}
|
||||
@@ -1400,37 +1531,43 @@ void ThreadTopUpKeyPool(void* parg)
|
||||
|
||||
void ThreadCleanWalletPassphrase(void* parg)
|
||||
{
|
||||
int64 nMyWakeTime = GetTime() + *((int*)parg);
|
||||
int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
|
||||
|
||||
ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
|
||||
|
||||
if (nWalletUnlockTime == 0)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||
nWalletUnlockTime = nMyWakeTime;
|
||||
|
||||
do
|
||||
{
|
||||
nWalletUnlockTime = nMyWakeTime;
|
||||
}
|
||||
if (nWalletUnlockTime==0)
|
||||
break;
|
||||
int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
|
||||
if (nToSleep <= 0)
|
||||
break;
|
||||
|
||||
while (GetTime() < nWalletUnlockTime)
|
||||
Sleep(GetTime() - nWalletUnlockTime);
|
||||
LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
|
||||
Sleep(nToSleep);
|
||||
ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
|
||||
|
||||
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||
} while(1);
|
||||
|
||||
if (nWalletUnlockTime)
|
||||
{
|
||||
nWalletUnlockTime = 0;
|
||||
pwalletMain->Lock();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||
{
|
||||
if (nWalletUnlockTime < nMyWakeTime)
|
||||
nWalletUnlockTime = nMyWakeTime;
|
||||
}
|
||||
free(parg);
|
||||
return;
|
||||
if (nWalletUnlockTime < nMyWakeTime)
|
||||
nWalletUnlockTime = nMyWakeTime;
|
||||
}
|
||||
|
||||
pwalletMain->Lock();
|
||||
LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
|
||||
|
||||
delete (int*)parg;
|
||||
delete (int64*)parg;
|
||||
}
|
||||
|
||||
Value walletpassphrase(const Array& params, bool fHelp)
|
||||
@@ -1448,21 +1585,16 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
||||
throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
|
||||
|
||||
// Note that the walletpassphrase is stored in params[0] which is not mlock()ed
|
||||
string strWalletPass;
|
||||
SecureString strWalletPass;
|
||||
strWalletPass.reserve(100);
|
||||
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
strWalletPass = params[0].get_str();
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make params[0] mlock()'d to begin with.
|
||||
strWalletPass = params[0].get_str().c_str();
|
||||
|
||||
if (strWalletPass.length() > 0)
|
||||
{
|
||||
if (!pwalletMain->Unlock(strWalletPass))
|
||||
{
|
||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||
}
|
||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
}
|
||||
else
|
||||
throw runtime_error(
|
||||
@@ -1470,7 +1602,7 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
||||
"Stores the wallet decryption key in memory for <timeout> seconds.");
|
||||
|
||||
CreateThread(ThreadTopUpKeyPool, NULL);
|
||||
int* pnSleepTime = new int(params[1].get_int());
|
||||
int64* pnSleepTime = new int64(params[1].get_int64());
|
||||
CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
|
||||
|
||||
return Value::null;
|
||||
@@ -1488,15 +1620,15 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
|
||||
if (!pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
|
||||
|
||||
string strOldWalletPass;
|
||||
// TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make params[0] mlock()'d to begin with.
|
||||
SecureString strOldWalletPass;
|
||||
strOldWalletPass.reserve(100);
|
||||
mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
strOldWalletPass = params[0].get_str();
|
||||
strOldWalletPass = params[0].get_str().c_str();
|
||||
|
||||
string strNewWalletPass;
|
||||
SecureString strNewWalletPass;
|
||||
strNewWalletPass.reserve(100);
|
||||
mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
strNewWalletPass = params[1].get_str();
|
||||
strNewWalletPass = params[1].get_str().c_str();
|
||||
|
||||
if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
|
||||
throw runtime_error(
|
||||
@@ -1504,17 +1636,7 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
|
||||
"Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
|
||||
|
||||
if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
|
||||
{
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
|
||||
}
|
||||
fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
|
||||
fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
|
||||
munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
|
||||
munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
|
||||
|
||||
return Value::null;
|
||||
}
|
||||
@@ -1533,9 +1655,9 @@ Value walletlock(const Array& params, bool fHelp)
|
||||
if (!pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
|
||||
|
||||
pwalletMain->Lock();
|
||||
CRITICAL_BLOCK(cs_nWalletUnlockTime)
|
||||
{
|
||||
pwalletMain->Lock();
|
||||
nWalletUnlockTime = 0;
|
||||
}
|
||||
|
||||
@@ -1554,10 +1676,16 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
if (pwalletMain->IsCrypted())
|
||||
throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
|
||||
|
||||
string strWalletPass;
|
||||
#ifdef QT_GUI
|
||||
// shutting down via RPC while the GUI is running does not work (yet):
|
||||
throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
|
||||
#endif
|
||||
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make params[0] mlock()'d to begin with.
|
||||
SecureString strWalletPass;
|
||||
strWalletPass.reserve(100);
|
||||
mlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
strWalletPass = params[0].get_str();
|
||||
strWalletPass = params[0].get_str().c_str();
|
||||
|
||||
if (strWalletPass.length() < 1)
|
||||
throw runtime_error(
|
||||
@@ -1565,15 +1693,13 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
"Encrypts the wallet with <passphrase>.");
|
||||
|
||||
if (!pwalletMain->EncryptWallet(strWalletPass))
|
||||
{
|
||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
|
||||
}
|
||||
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
|
||||
munlock(&strWalletPass[0], strWalletPass.capacity());
|
||||
|
||||
return Value::null;
|
||||
// BDB seems to have a bad habit of writing old data into
|
||||
// slack space in .dat files; that is bad if the old data is
|
||||
// unencrypted private keys. So:
|
||||
CreateThread(Shutdown, NULL);
|
||||
return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
|
||||
}
|
||||
|
||||
|
||||
@@ -1595,14 +1721,42 @@ Value validateaddress(const Array& params, bool fHelp)
|
||||
// version of the address:
|
||||
string currentAddress = address.ToString();
|
||||
ret.push_back(Pair("address", currentAddress));
|
||||
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
|
||||
if (pwalletMain->HaveKey(address))
|
||||
{
|
||||
ret.push_back(Pair("ismine", true));
|
||||
std::vector<unsigned char> vchPubKey;
|
||||
pwalletMain->GetPubKey(address, vchPubKey);
|
||||
ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
|
||||
CKey key;
|
||||
key.SetPubKey(vchPubKey);
|
||||
ret.push_back(Pair("iscompressed", key.IsCompressed()));
|
||||
}
|
||||
else if (pwalletMain->HaveCScript(address.GetHash160()))
|
||||
{
|
||||
ret.push_back(Pair("isscript", true));
|
||||
CScript subscript;
|
||||
pwalletMain->GetCScript(address.GetHash160(), subscript);
|
||||
ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
|
||||
std::vector<CBitcoinAddress> addresses;
|
||||
txnouttype whichType;
|
||||
int nRequired;
|
||||
ExtractAddresses(subscript, whichType, addresses, nRequired);
|
||||
ret.push_back(Pair("script", GetTxnOutputType(whichType)));
|
||||
Array a;
|
||||
BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
|
||||
a.push_back(addr.ToString());
|
||||
ret.push_back(Pair("addresses", a));
|
||||
if (whichType == TX_MULTISIG)
|
||||
ret.push_back(Pair("sigsrequired", nRequired));
|
||||
}
|
||||
else
|
||||
ret.push_back(Pair("ismine", false));
|
||||
if (pwalletMain->mapAddressBook.count(address))
|
||||
ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Value getwork(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
@@ -1656,7 +1810,7 @@ Value getwork(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
// Update nTime
|
||||
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||
pblock->UpdateTime(pindexPrev);
|
||||
pblock->nNonce = 0;
|
||||
|
||||
// Update nExtraNonce
|
||||
@@ -1718,7 +1872,10 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
" \"previousblockhash\" : hash of current highest block\n"
|
||||
" \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
|
||||
" \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
|
||||
" \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
|
||||
" \"time\" : timestamp appropriate for next block\n"
|
||||
" \"mintime\" : minimum timestamp appropriate for next block\n"
|
||||
" \"curtime\" : current timestamp\n"
|
||||
" \"bits\" : compressed target of next block\n"
|
||||
"If [data] is specified, tries to solve the block and returns true if it was successful.");
|
||||
|
||||
@@ -1753,7 +1910,7 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
}
|
||||
|
||||
// Update nTime
|
||||
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||
pblock->UpdateTime(pindexPrev);
|
||||
pblock->nNonce = 0;
|
||||
|
||||
Array transactions;
|
||||
@@ -1772,14 +1929,11 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
|
||||
result.push_back(Pair("transactions", transactions));
|
||||
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
|
||||
result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
|
||||
result.push_back(Pair("time", (int64_t)pblock->nTime));
|
||||
|
||||
union {
|
||||
int32_t nBits;
|
||||
char cBits[4];
|
||||
} uBits;
|
||||
uBits.nBits = htonl((int32_t)pblock->nBits);
|
||||
result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
|
||||
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
|
||||
result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
|
||||
result.push_back(Pair("bits", HexBits(pblock->nBits)));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1794,6 +1948,44 @@ Value getmemorypool(const Array& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
Value getblockhash(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getblockhash <index>\n"
|
||||
"Returns hash of block in best-block-chain at <index>.");
|
||||
|
||||
int nHeight = params[0].get_int();
|
||||
if (nHeight < 0 || nHeight > nBestHeight)
|
||||
throw runtime_error("Block number out of range.");
|
||||
|
||||
CBlock block;
|
||||
CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
|
||||
while (pblockindex->nHeight > nHeight)
|
||||
pblockindex = pblockindex->pprev;
|
||||
return pblockindex->phashBlock->GetHex();
|
||||
}
|
||||
|
||||
Value getblock(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"getblock <hash>\n"
|
||||
"Returns details of a block with given block-hash.");
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(strHash);
|
||||
|
||||
if (mapBlockIndex.count(hash) == 0)
|
||||
throw JSONRPCError(-5, "Block not found");
|
||||
|
||||
CBlock block;
|
||||
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||
block.ReadFromDisk(pblockindex, true);
|
||||
|
||||
return blockToJSON(block, pblockindex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1820,6 +2012,7 @@ pair<string, rpcfn_type> pCallTable[] =
|
||||
make_pair("setgenerate", &setgenerate),
|
||||
make_pair("gethashespersec", &gethashespersec),
|
||||
make_pair("getinfo", &getinfo),
|
||||
make_pair("getmininginfo", &getmininginfo),
|
||||
make_pair("getnewaddress", &getnewaddress),
|
||||
make_pair("getaccountaddress", &getaccountaddress),
|
||||
make_pair("setaccount", &setaccount),
|
||||
@@ -1841,15 +2034,20 @@ pair<string, rpcfn_type> pCallTable[] =
|
||||
make_pair("move", &movecmd),
|
||||
make_pair("sendfrom", &sendfrom),
|
||||
make_pair("sendmany", &sendmany),
|
||||
make_pair("addmultisigaddress", &addmultisigaddress),
|
||||
make_pair("getblock", &getblock),
|
||||
make_pair("getblockhash", &getblockhash),
|
||||
make_pair("gettransaction", &gettransaction),
|
||||
make_pair("listtransactions", &listtransactions),
|
||||
make_pair("signmessage", &signmessage),
|
||||
make_pair("verifymessage", &verifymessage),
|
||||
make_pair("signmessage", &signmessage),
|
||||
make_pair("verifymessage", &verifymessage),
|
||||
make_pair("getwork", &getwork),
|
||||
make_pair("listaccounts", &listaccounts),
|
||||
make_pair("settxfee", &settxfee),
|
||||
make_pair("getmemorypool", &getmemorypool),
|
||||
make_pair("listsinceblock", &listsinceblock),
|
||||
make_pair("listsinceblock", &listsinceblock),
|
||||
make_pair("dumpprivkey", &dumpprivkey),
|
||||
make_pair("importprivkey", &importprivkey)
|
||||
};
|
||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||
|
||||
@@ -1858,13 +2056,14 @@ string pAllowInSafeMode[] =
|
||||
"help",
|
||||
"stop",
|
||||
"getblockcount",
|
||||
"getblocknumber",
|
||||
"getblocknumber", // deprecated
|
||||
"getconnectioncount",
|
||||
"getdifficulty",
|
||||
"getgenerate",
|
||||
"setgenerate",
|
||||
"gethashespersec",
|
||||
"getinfo",
|
||||
"getmininginfo",
|
||||
"getnewaddress",
|
||||
"getaccountaddress",
|
||||
"getaccount",
|
||||
@@ -2029,12 +2228,7 @@ bool HTTPAuthorized(map<string, string>& mapHeaders)
|
||||
return false;
|
||||
string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
|
||||
string strUserPass = DecodeBase64(strUserPass64);
|
||||
string::size_type nColon = strUserPass.find(":");
|
||||
if (nColon == string::npos)
|
||||
return false;
|
||||
string strUser = strUserPass.substr(0, nColon);
|
||||
string strPassword = strUserPass.substr(nColon+1);
|
||||
return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
|
||||
return strUserPass == strRPCUserColonPass;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -2149,15 +2343,15 @@ void ThreadRPCServer(void* parg)
|
||||
IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
|
||||
try
|
||||
{
|
||||
vnThreadsRunning[4]++;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]++;
|
||||
ThreadRPCServer2(parg);
|
||||
vnThreadsRunning[4]--;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]--;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
vnThreadsRunning[4]--;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]--;
|
||||
PrintException(&e, "ThreadRPCServer()");
|
||||
} catch (...) {
|
||||
vnThreadsRunning[4]--;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]--;
|
||||
PrintException(NULL, "ThreadRPCServer()");
|
||||
}
|
||||
printf("ThreadRPCServer exiting\n");
|
||||
@@ -2167,19 +2361,29 @@ void ThreadRPCServer2(void* parg)
|
||||
{
|
||||
printf("ThreadRPCServer started\n");
|
||||
|
||||
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
|
||||
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
|
||||
if (mapArgs["-rpcpassword"] == "")
|
||||
{
|
||||
unsigned char rand_pwd[32];
|
||||
RAND_bytes(rand_pwd, 32);
|
||||
string strWhatAmI = "To use bitcoind";
|
||||
if (mapArgs.count("-server"))
|
||||
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
|
||||
else if (mapArgs.count("-daemon"))
|
||||
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
|
||||
PrintConsole(
|
||||
_("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
|
||||
::error(
|
||||
_("%s, you must set a rpcpassword in the configuration file:\n %s\n"
|
||||
"It is recommended you use the following random password:\n"
|
||||
"rpcuser=bitcoinrpc\n"
|
||||
"rpcpassword=%s\n"
|
||||
"(you do not need to remember this password)\n"
|
||||
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
|
||||
strWhatAmI.c_str(),
|
||||
GetConfigFile().c_str());
|
||||
GetConfigFile().c_str(),
|
||||
EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
|
||||
#ifndef QT_GUI
|
||||
CreateThread(Shutdown, NULL);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2227,7 +2431,7 @@ void ThreadRPCServer2(void* parg)
|
||||
#endif
|
||||
|
||||
ip::tcp::endpoint peer;
|
||||
vnThreadsRunning[4]--;
|
||||
vnThreadsRunning[THREAD_RPCSERVER]--;
|
||||
#ifdef USE_SSL
|
||||
acceptor.accept(sslStream.lowest_layer(), peer);
|
||||
#else
|
||||
@@ -2265,12 +2469,14 @@ void ThreadRPCServer2(void* parg)
|
||||
}
|
||||
if (!HTTPAuthorized(mapHeaders))
|
||||
{
|
||||
// Deter brute-forcing short passwords
|
||||
if (mapArgs["-rpcpassword"].size() < 15)
|
||||
Sleep(50);
|
||||
printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
|
||||
/* Deter brute-forcing short passwords.
|
||||
If this results in a DOS the user really
|
||||
shouldn't have their RPC port exposed.*/
|
||||
if (mapArgs["-rpcpassword"].size() < 20)
|
||||
Sleep(250);
|
||||
|
||||
stream << HTTPReply(401, "") << std::flush;
|
||||
printf("ThreadRPCServer incorrect password attempt\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2466,6 +2672,7 @@ int CommandLineRPC(int argc, char *argv[])
|
||||
if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
|
||||
if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
|
||||
if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
|
||||
if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
|
||||
@@ -2484,6 +2691,15 @@ int CommandLineRPC(int argc, char *argv[])
|
||||
params[1] = v.get_obj();
|
||||
}
|
||||
if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
|
||||
if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "addmultisigaddress" && n > 1)
|
||||
{
|
||||
string s = params[1].get_str();
|
||||
Value v;
|
||||
if (!read_string(s, v) || v.type() != array_type)
|
||||
throw runtime_error("type mismatch "+s);
|
||||
params[1] = v.get_array();
|
||||
}
|
||||
|
||||
// Execute
|
||||
Object reply = CallRPC(strMethod, params);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// 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.
|
||||
|
||||
|
||||
65
src/checkpoints.cpp
Normal file
65
src/checkpoints.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "headers.h"
|
||||
#include "checkpoints.h"
|
||||
|
||||
namespace Checkpoints
|
||||
{
|
||||
typedef std::map<int, uint256> MapCheckpoints;
|
||||
|
||||
//
|
||||
// What makes a good checkpoint block?
|
||||
// + Is surrounded by blocks with reasonable timestamps
|
||||
// (no blocks before with a timestamp after, none after with
|
||||
// timestamp before)
|
||||
// + Contains no strange transactions
|
||||
//
|
||||
static MapCheckpoints mapCheckpoints =
|
||||
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"))
|
||||
;
|
||||
|
||||
bool CheckBlock(int nHeight, const uint256& hash)
|
||||
{
|
||||
if (fTestNet) return true; // Testnet has no checkpoints
|
||||
|
||||
MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
|
||||
if (i == mapCheckpoints.end()) return true;
|
||||
return hash == i->second;
|
||||
}
|
||||
|
||||
int GetTotalBlocksEstimate()
|
||||
{
|
||||
if (fTestNet) return 0;
|
||||
|
||||
return mapCheckpoints.rbegin()->first;
|
||||
}
|
||||
|
||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
|
||||
{
|
||||
if (fTestNet) return NULL;
|
||||
|
||||
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
|
||||
{
|
||||
const uint256& hash = i.second;
|
||||
std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
|
||||
if (t != mapBlockIndex.end())
|
||||
return t->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
28
src/checkpoints.h
Normal file
28
src/checkpoints.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_CHECKPOINT_H
|
||||
#define BITCOIN_CHECKPOINT_H
|
||||
|
||||
#include <map>
|
||||
#include "util.h"
|
||||
|
||||
class uint256;
|
||||
class CBlockIndex;
|
||||
|
||||
/** Block-chain checkpoints are compiled-in sanity checks.
|
||||
* They are updated every release or three.
|
||||
*/
|
||||
namespace Checkpoints
|
||||
{
|
||||
// Returns true if block passes checkpoint checks
|
||||
bool CheckBlock(int nHeight, const uint256& hash);
|
||||
|
||||
// Return conservative estimate of total number of blocks, 0 if unknown
|
||||
int GetTotalBlocksEstimate();
|
||||
|
||||
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
|
||||
}
|
||||
|
||||
#endif
|
||||
42
src/compat.h
Normal file
42
src/compat.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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.
|
||||
#ifndef _BITCOIN_COMPAT_H
|
||||
#define _BITCOIN_COMPAT_H 1
|
||||
|
||||
typedef u_int SOCKET;
|
||||
#ifdef WIN32
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define MSG_DONTWAIT 0
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include "errno.h"
|
||||
#define WSAGetLastError() errno
|
||||
#define WSAEINVAL EINVAL
|
||||
#define WSAEALREADY EALREADY
|
||||
#define WSAEWOULDBLOCK EWOULDBLOCK
|
||||
#define WSAEMSGSIZE EMSGSIZE
|
||||
#define WSAEINTR EINTR
|
||||
#define WSAEINPROGRESS EINPROGRESS
|
||||
#define WSAEADDRINUSE EADDRINUSE
|
||||
#define WSAENOTSOCK EBADF
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
inline int myclosesocket(SOCKET& hSocket)
|
||||
{
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return WSAENOTSOCK;
|
||||
#ifdef WIN32
|
||||
int ret = closesocket(hSocket);
|
||||
#else
|
||||
int ret = close(hSocket);
|
||||
#endif
|
||||
hSocket = INVALID_SOCKET;
|
||||
return ret;
|
||||
}
|
||||
#define closesocket(s) myclosesocket(s)
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2011 The Bitcoin Developers
|
||||
// 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.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
|
||||
bool CCrypter::SetKeyFromPassphrase(const std::string& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
|
||||
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
|
||||
{
|
||||
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
|
||||
return false;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Copyright (c) 2011 The Bitcoin Developers
|
||||
// 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 __CRYPTER_H__
|
||||
#define __CRYPTER_H__
|
||||
|
||||
#include "util.h" /* for SecureString */
|
||||
#include "key.h"
|
||||
|
||||
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
||||
@@ -13,17 +14,18 @@ const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
||||
Private key encryption is done based on a CMasterKey,
|
||||
which holds a salt and random encryption key.
|
||||
|
||||
CMasterKeys is encrypted using AES-256-CBC using a key
|
||||
CMasterKeys are encrypted using AES-256-CBC using a key
|
||||
derived using derivation method nDerivationMethod
|
||||
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.
|
||||
vchOtherDerivationParameters is provided for alternative algorithms
|
||||
which may require more parameters (such as scrypt).
|
||||
|
||||
Wallet Private Keys are then encrypted using AES-256-CBC
|
||||
with the double-sha256 of the private key as the IV, and the
|
||||
master key's key as the encryption key.
|
||||
with the double-sha256 of the public key as the IV, and the
|
||||
master key's key as the encryption key (see keystore.[ch]).
|
||||
*/
|
||||
|
||||
/** Master key for wallet encryption */
|
||||
class CMasterKey
|
||||
{
|
||||
public:
|
||||
@@ -57,6 +59,7 @@ public:
|
||||
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
|
||||
|
||||
/** Encryption/decryption context with key information */
|
||||
class CCrypter
|
||||
{
|
||||
private:
|
||||
@@ -65,7 +68,7 @@ private:
|
||||
bool fKeySet;
|
||||
|
||||
public:
|
||||
bool SetKeyFromPassphrase(const std::string &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
|
||||
bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
|
||||
bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
|
||||
bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
|
||||
bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
|
||||
|
||||
449
src/db.cpp
449
src/db.cpp
@@ -1,11 +1,12 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "db.h"
|
||||
#include "net.h"
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
@@ -27,6 +28,24 @@ static bool fDbEnvInit = false;
|
||||
DbEnv dbenv(0);
|
||||
static map<string, int> mapFileUseCount;
|
||||
static map<string, Db*> mapDb;
|
||||
static int64 nTxn = 0;
|
||||
|
||||
static void EnvShutdown()
|
||||
{
|
||||
if (!fDbEnvInit)
|
||||
return;
|
||||
|
||||
fDbEnvInit = false;
|
||||
try
|
||||
{
|
||||
dbenv.close(0);
|
||||
}
|
||||
catch (const DbException& e)
|
||||
{
|
||||
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
|
||||
}
|
||||
DbEnv(0).remove(GetDataDir().c_str(), 0);
|
||||
}
|
||||
|
||||
class CDBInit
|
||||
{
|
||||
@@ -36,11 +55,7 @@ public:
|
||||
}
|
||||
~CDBInit()
|
||||
{
|
||||
if (fDbEnvInit)
|
||||
{
|
||||
dbenv.close(0);
|
||||
fDbEnvInit = false;
|
||||
}
|
||||
EnvShutdown();
|
||||
}
|
||||
}
|
||||
instance_of_cdbinit;
|
||||
@@ -70,12 +85,16 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
|
||||
string strErrorFile = strDataDir + "/db.log";
|
||||
printf("dbenv.open strLogDir=%s strErrorFile=%s\n", strLogDir.c_str(), strErrorFile.c_str());
|
||||
|
||||
int nDbCache = GetArg("-dbcache", 25);
|
||||
dbenv.set_lg_dir(strLogDir.c_str());
|
||||
dbenv.set_lg_max(10000000);
|
||||
dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
|
||||
dbenv.set_lg_bsize(1048576);
|
||||
dbenv.set_lg_max(10485760);
|
||||
dbenv.set_lk_max_locks(10000);
|
||||
dbenv.set_lk_max_objects(10000);
|
||||
dbenv.set_errfile(fopen(strErrorFile.c_str(), "a")); /// debug
|
||||
dbenv.set_flags(DB_AUTO_COMMIT, 1);
|
||||
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
|
||||
ret = dbenv.open(strDataDir.c_str(),
|
||||
DB_CREATE |
|
||||
DB_INIT_LOCK |
|
||||
@@ -118,7 +137,7 @@ CDB::CDB(const char* pszFile, const char* pszMode) : pdb(NULL)
|
||||
{
|
||||
bool fTmp = fReadOnly;
|
||||
fReadOnly = false;
|
||||
WriteVersion(VERSION);
|
||||
WriteVersion(CLIENT_VERSION);
|
||||
fReadOnly = fTmp;
|
||||
}
|
||||
|
||||
@@ -142,8 +161,15 @@ void CDB::Close()
|
||||
nMinutes = 1;
|
||||
if (strFile == "addr.dat")
|
||||
nMinutes = 2;
|
||||
if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0)
|
||||
nMinutes = 1;
|
||||
if (strFile == "blkindex.dat" && IsInitialBlockDownload())
|
||||
nMinutes = 5;
|
||||
|
||||
if (nMinutes == 0 || nTxn > 200000)
|
||||
{
|
||||
nTxn = 0;
|
||||
nMinutes = 0;
|
||||
}
|
||||
|
||||
dbenv.txn_checkpoint(0, nMinutes, 0);
|
||||
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
@@ -165,6 +191,101 @@ void static CloseDb(const string& strFile)
|
||||
}
|
||||
}
|
||||
|
||||
bool CDB::Rewrite(const string& strFile, const char* pszSkip)
|
||||
{
|
||||
while (!fShutdown)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_db)
|
||||
{
|
||||
if (!mapFileUseCount.count(strFile) || 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);
|
||||
|
||||
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);
|
||||
|
||||
int ret = pdbCopy->open(NULL, // Txn pointer
|
||||
strFileRes.c_str(), // Filename
|
||||
"main", // Logical db name
|
||||
DB_BTREE, // Database type
|
||||
DB_CREATE, // Flags
|
||||
0);
|
||||
if (ret > 0)
|
||||
{
|
||||
printf("Cannot create database file %s\n", strFileRes.c_str());
|
||||
fSuccess = false;
|
||||
}
|
||||
|
||||
Dbc* pcursor = db.GetCursor();
|
||||
if (pcursor)
|
||||
while (fSuccess)
|
||||
{
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
|
||||
if (ret == DB_NOTFOUND)
|
||||
{
|
||||
pcursor->close();
|
||||
break;
|
||||
}
|
||||
else if (ret != 0)
|
||||
{
|
||||
pcursor->close();
|
||||
fSuccess = false;
|
||||
break;
|
||||
}
|
||||
if (pszSkip &&
|
||||
strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
|
||||
continue;
|
||||
if (strncmp(&ssKey[0], "\x07version", 8) == 0)
|
||||
{
|
||||
// Update version:
|
||||
ssValue.clear();
|
||||
ssValue << CLIENT_VERSION;
|
||||
}
|
||||
Dbt datKey(&ssKey[0], ssKey.size());
|
||||
Dbt datValue(&ssValue[0], ssValue.size());
|
||||
int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
|
||||
if (ret2 > 0)
|
||||
fSuccess = false;
|
||||
}
|
||||
if (fSuccess)
|
||||
{
|
||||
db.Close();
|
||||
CloseDb(strFile);
|
||||
if (pdbCopy->close(0))
|
||||
fSuccess = false;
|
||||
delete pdbCopy;
|
||||
}
|
||||
}
|
||||
if (fSuccess)
|
||||
{
|
||||
Db dbA(&dbenv, 0);
|
||||
if (dbA.remove(strFile.c_str(), NULL, 0))
|
||||
fSuccess = false;
|
||||
Db dbB(&dbenv, 0);
|
||||
if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
|
||||
fSuccess = false;
|
||||
}
|
||||
if (!fSuccess)
|
||||
printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
|
||||
return fSuccess;
|
||||
}
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DBFlush(bool fShutdown)
|
||||
{
|
||||
// Flush log data to the actual data file
|
||||
@@ -196,9 +317,10 @@ void DBFlush(bool fShutdown)
|
||||
{
|
||||
char** listp;
|
||||
if (mapFileUseCount.empty())
|
||||
{
|
||||
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
|
||||
dbenv.close(0);
|
||||
fDbEnvInit = false;
|
||||
EnvShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,6 +344,7 @@ bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
|
||||
bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
|
||||
{
|
||||
assert(!fClient);
|
||||
nTxn++;
|
||||
return Write(make_pair(string("tx"), hash), txindex);
|
||||
}
|
||||
|
||||
@@ -232,6 +355,7 @@ bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeigh
|
||||
// Add to tx index
|
||||
uint256 hash = tx.GetHash();
|
||||
CTxIndex txindex(pos, tx.vout.size());
|
||||
nTxn++;
|
||||
return Write(make_pair(string("tx"), hash), txindex);
|
||||
}
|
||||
|
||||
@@ -470,19 +594,114 @@ bool CTxDB::LoadBlockIndex()
|
||||
ReadBestInvalidWork(bnBestInvalidWork);
|
||||
|
||||
// Verify blocks in the best chain
|
||||
int nCheckLevel = GetArg("-checklevel", 1);
|
||||
int nCheckDepth = GetArg( "-checkblocks", 2500);
|
||||
if (nCheckDepth == 0)
|
||||
nCheckDepth = 1000000000; // suffices until the year 19000
|
||||
if (nCheckDepth > nBestHeight)
|
||||
nCheckDepth = nBestHeight;
|
||||
printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
|
||||
CBlockIndex* pindexFork = NULL;
|
||||
map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
|
||||
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
|
||||
{
|
||||
if (pindex->nHeight < nBestHeight-2500 && !mapArgs.count("-checkblocks"))
|
||||
if (pindex->nHeight < nBestHeight-nCheckDepth)
|
||||
break;
|
||||
CBlock block;
|
||||
if (!block.ReadFromDisk(pindex))
|
||||
return error("LoadBlockIndex() : block.ReadFromDisk failed");
|
||||
if (!block.CheckBlock())
|
||||
// check level 1: verify block validity
|
||||
if (nCheckLevel>0 && !block.CheckBlock())
|
||||
{
|
||||
printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
// check level 2: verify transaction index validity
|
||||
if (nCheckLevel>1)
|
||||
{
|
||||
pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
|
||||
mapBlockPos[pos] = pindex;
|
||||
BOOST_FOREACH(const CTransaction &tx, block.vtx)
|
||||
{
|
||||
uint256 hashTx = tx.GetHash();
|
||||
CTxIndex txindex;
|
||||
if (ReadTxIndex(hashTx, txindex))
|
||||
{
|
||||
// check level 3: checker transaction hashes
|
||||
if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
|
||||
{
|
||||
// either an error or a duplicate transaction
|
||||
CTransaction txFound;
|
||||
if (!txFound.ReadFromDisk(txindex.pos))
|
||||
{
|
||||
printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
else
|
||||
if (txFound.GetHash() != hashTx) // not a duplicate tx
|
||||
{
|
||||
printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
}
|
||||
// check level 4: check whether spent txouts were spent within the main chain
|
||||
int nOutput = 0;
|
||||
if (nCheckLevel>3)
|
||||
BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
|
||||
{
|
||||
if (!txpos.IsNull())
|
||||
{
|
||||
pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
|
||||
if (!mapBlockPos.count(posFind))
|
||||
{
|
||||
printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
// check level 6: check whether spent txouts were spent by a valid transaction that consume them
|
||||
if (nCheckLevel>5)
|
||||
{
|
||||
CTransaction txSpend;
|
||||
if (!txSpend.ReadFromDisk(txpos))
|
||||
{
|
||||
printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
else if (!txSpend.CheckTransaction())
|
||||
{
|
||||
printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool fFound = false;
|
||||
BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
|
||||
if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
|
||||
fFound = true;
|
||||
if (!fFound)
|
||||
{
|
||||
printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nOutput++;
|
||||
}
|
||||
}
|
||||
// check level 5: check whether all prevouts are marked spent
|
||||
if (nCheckLevel>4)
|
||||
BOOST_FOREACH(const CTxIn &txin, tx.vin)
|
||||
{
|
||||
CTxIndex txindex;
|
||||
if (ReadTxIndex(txin.prevout.hash, txindex))
|
||||
if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
|
||||
{
|
||||
printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
|
||||
pindexFork = pindex->pprev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pindexFork)
|
||||
{
|
||||
@@ -506,50 +725,58 @@ bool CTxDB::LoadBlockIndex()
|
||||
// CAddrDB
|
||||
//
|
||||
|
||||
bool CAddrDB::WriteAddress(const CAddress& addr)
|
||||
bool CAddrDB::WriteAddrman(const CAddrMan& addrman)
|
||||
{
|
||||
return Write(make_pair(string("addr"), addr.GetKey()), addr);
|
||||
}
|
||||
|
||||
bool CAddrDB::EraseAddress(const CAddress& addr)
|
||||
{
|
||||
return Erase(make_pair(string("addr"), addr.GetKey()));
|
||||
return Write(string("addrman"), addrman);
|
||||
}
|
||||
|
||||
bool CAddrDB::LoadAddresses()
|
||||
{
|
||||
CRITICAL_BLOCK(cs_mapAddresses)
|
||||
if (Read(string("addrman"), addrman))
|
||||
{
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
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
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
return false;
|
||||
|
||||
loop
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
return false;
|
||||
|
||||
loop
|
||||
// Unserialize
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "addr")
|
||||
{
|
||||
// Read next record
|
||||
CDataStream ssKey;
|
||||
CDataStream ssValue;
|
||||
int ret = ReadAtCursor(pcursor, ssKey, ssValue);
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
return false;
|
||||
|
||||
// Unserialize
|
||||
string strType;
|
||||
ssKey >> strType;
|
||||
if (strType == "addr")
|
||||
{
|
||||
CAddress addr;
|
||||
ssValue >> addr;
|
||||
mapAddresses.insert(make_pair(addr.GetKey(), addr));
|
||||
}
|
||||
CAddress addr;
|
||||
ssValue >> addr;
|
||||
vAddr.push_back(addr);
|
||||
}
|
||||
pcursor->close();
|
||||
|
||||
printf("Loaded %d addresses\n", mapAddresses.size());
|
||||
}
|
||||
pcursor->close();
|
||||
|
||||
addrman.Add(vAddr, CNetAddr("0.0.0.0"));
|
||||
printf("Loaded %i addresses\n", addrman.size());
|
||||
|
||||
// Note: old records left; we ran into hangs-on-startup
|
||||
// bugs for some users who (we think) were running after
|
||||
// an unclean shutdown.
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -656,21 +883,26 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
pwallet->vchDefaultKey.clear();
|
||||
int nFileVersion = 0;
|
||||
vector<uint256> vWalletUpgrade;
|
||||
|
||||
// Modify defaults
|
||||
#ifndef WIN32
|
||||
// Tray icon sometimes disappears on 9.10 karmic koala 64-bit, leaving no way to access the program
|
||||
fMinimizeToTray = false;
|
||||
fMinimizeOnClose = false;
|
||||
#endif
|
||||
bool fIsEncrypted = false;
|
||||
|
||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||
CRITICAL_BLOCK(pwallet->cs_wallet)
|
||||
{
|
||||
int nMinVersion = 0;
|
||||
if (Read((string)"minversion", nMinVersion))
|
||||
{
|
||||
if (nMinVersion > CLIENT_VERSION)
|
||||
return DB_TOO_NEW;
|
||||
pwallet->LoadMinVersion(nMinVersion);
|
||||
}
|
||||
|
||||
// Get cursor
|
||||
Dbc* pcursor = GetCursor();
|
||||
if (!pcursor)
|
||||
{
|
||||
printf("Error getting wallet database cursor\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
|
||||
loop
|
||||
{
|
||||
@@ -681,7 +913,10 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
if (ret == DB_NOTFOUND)
|
||||
break;
|
||||
else if (ret != 0)
|
||||
{
|
||||
printf("Error reading next record from wallet database\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
|
||||
// Unserialize
|
||||
// Taking advantage of the fact that pair serialization
|
||||
@@ -700,7 +935,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
ssKey >> hash;
|
||||
CWalletTx& wtx = pwallet->mapWallet[hash];
|
||||
ssValue >> wtx;
|
||||
wtx.pwallet = pwallet;
|
||||
wtx.BindWallet(pwallet);
|
||||
|
||||
if (wtx.GetHash() != hash)
|
||||
printf("Error in wallet.dat, hash mismatch\n");
|
||||
@@ -750,16 +985,41 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
{
|
||||
CPrivKey pkey;
|
||||
ssValue >> pkey;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetPrivKey(pkey);
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
printf("Error reading wallet database: CPrivKey pubkey inconsistency\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
if (!key.IsValid())
|
||||
{
|
||||
printf("Error reading wallet database: invalid CPrivKey\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CWalletKey wkey;
|
||||
ssValue >> wkey;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetPrivKey(wkey.vchPrivKey);
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
printf("Error reading wallet database: CWalletKey pubkey inconsistency\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
if (!key.IsValid())
|
||||
{
|
||||
printf("Error reading wallet database: invalid CWalletKey\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
if (!pwallet->LoadKey(key))
|
||||
{
|
||||
printf("Error reading wallet database: LoadKey failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
else if (strType == "mkey")
|
||||
{
|
||||
@@ -768,7 +1028,10 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
CMasterKey kMasterKey;
|
||||
ssValue >> kMasterKey;
|
||||
if(pwallet->mapMasterKeys.count(nID) != 0)
|
||||
{
|
||||
printf("Error reading wallet database: duplicate CMasterKey id %u\n", nID);
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
pwallet->mapMasterKeys[nID] = kMasterKey;
|
||||
if (pwallet->nMasterKeyMaxID < nID)
|
||||
pwallet->nMasterKeyMaxID = nID;
|
||||
@@ -780,7 +1043,11 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
vector<unsigned char> vchPrivKey;
|
||||
ssValue >> vchPrivKey;
|
||||
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
|
||||
{
|
||||
printf("Error reading wallet database: LoadCryptedKey failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
fIsEncrypted = true;
|
||||
}
|
||||
else if (strType == "defaultkey")
|
||||
{
|
||||
@@ -798,30 +1065,17 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
if (nFileVersion == 10300)
|
||||
nFileVersion = 300;
|
||||
}
|
||||
else if (strType == "setting")
|
||||
else if (strType == "cscript")
|
||||
{
|
||||
string strKey;
|
||||
ssKey >> strKey;
|
||||
|
||||
// Options
|
||||
#ifndef QT_GUI
|
||||
if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
|
||||
#endif
|
||||
if (strKey == "nTransactionFee") ssValue >> nTransactionFee;
|
||||
if (strKey == "fLimitProcessors") ssValue >> fLimitProcessors;
|
||||
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
|
||||
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
|
||||
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose;
|
||||
if (strKey == "fUseProxy") ssValue >> fUseProxy;
|
||||
if (strKey == "addrProxy") ssValue >> addrProxy;
|
||||
if (fHaveUPnP && strKey == "fUseUPnP") ssValue >> fUseUPnP;
|
||||
}
|
||||
else if (strType == "minversion")
|
||||
{
|
||||
int nMinVersion = 0;
|
||||
ssValue >> nMinVersion;
|
||||
if (nMinVersion > VERSION)
|
||||
return DB_TOO_NEW;
|
||||
uint160 hash;
|
||||
ssKey >> hash;
|
||||
CScript script;
|
||||
ssValue >> script;
|
||||
if (!pwallet->LoadCScript(script))
|
||||
{
|
||||
printf("Error reading wallet database: LoadCScript failed\n");
|
||||
return DB_CORRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
pcursor->close();
|
||||
@@ -831,27 +1085,21 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
|
||||
WriteTx(hash, pwallet->mapWallet[hash]);
|
||||
|
||||
printf("nFileVersion = %d\n", nFileVersion);
|
||||
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
|
||||
printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
|
||||
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
|
||||
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
|
||||
printf("fUseProxy = %d\n", fUseProxy);
|
||||
printf("addrProxy = %s\n", addrProxy.ToString().c_str());
|
||||
if (fHaveUPnP)
|
||||
printf("fUseUPnP = %d\n", fUseUPnP);
|
||||
|
||||
|
||||
// Upgrade
|
||||
if (nFileVersion < VERSION)
|
||||
// Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
|
||||
if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000))
|
||||
return DB_NEED_REWRITE;
|
||||
|
||||
if (nFileVersion < CLIENT_VERSION) // Update
|
||||
{
|
||||
// Get rid of old debug.log file in current directory
|
||||
if (nFileVersion <= 105 && !pszSetDataDir[0])
|
||||
unlink("debug.log");
|
||||
|
||||
WriteVersion(VERSION);
|
||||
WriteVersion(CLIENT_VERSION);
|
||||
}
|
||||
|
||||
|
||||
return DB_LOAD_OK;
|
||||
}
|
||||
|
||||
@@ -862,7 +1110,7 @@ void ThreadFlushWalletDB(void* parg)
|
||||
if (fOneThread)
|
||||
return;
|
||||
fOneThread = true;
|
||||
if (mapArgs.count("-noflushwallet"))
|
||||
if (!GetBoolArg("-flushwallet", true))
|
||||
return;
|
||||
|
||||
unsigned int nLastSeen = nWalletDBUpdated;
|
||||
@@ -936,14 +1184,19 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
|
||||
filesystem::path pathDest(strDest);
|
||||
if (filesystem::is_directory(pathDest))
|
||||
pathDest = pathDest / wallet.strWalletFile;
|
||||
#if BOOST_VERSION >= 104000
|
||||
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
|
||||
#else
|
||||
filesystem::copy_file(pathSrc, pathDest);
|
||||
#endif
|
||||
printf("copied wallet.dat to %s\n", pathDest.string().c_str());
|
||||
|
||||
return true;
|
||||
try {
|
||||
#if BOOST_VERSION >= 104000
|
||||
filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
|
||||
#else
|
||||
filesystem::copy_file(pathSrc, pathDest);
|
||||
#endif
|
||||
printf("copied wallet.dat to %s\n", pathDest.string().c_str());
|
||||
return true;
|
||||
} catch(const filesystem::filesystem_error &e) {
|
||||
printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Sleep(100);
|
||||
|
||||
64
src/db.h
64
src/db.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_DB_H
|
||||
@@ -13,29 +13,28 @@
|
||||
|
||||
#include <db_cxx.h>
|
||||
|
||||
class CTxIndex;
|
||||
class CDiskBlockIndex;
|
||||
class CDiskTxPos;
|
||||
class COutPoint;
|
||||
class CAddress;
|
||||
class CWalletTx;
|
||||
class CWallet;
|
||||
class CAccount;
|
||||
class CAccountingEntry;
|
||||
class CAddress;
|
||||
class CAddrMan;
|
||||
class CBlockLocator;
|
||||
|
||||
class CDiskBlockIndex;
|
||||
class CDiskTxPos;
|
||||
class CMasterKey;
|
||||
class COutPoint;
|
||||
class CTxIndex;
|
||||
class CWallet;
|
||||
class CWalletTx;
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
extern DbEnv dbenv;
|
||||
|
||||
|
||||
extern void DBFlush(bool fShutdown);
|
||||
void ThreadFlushWalletDB(void* parg);
|
||||
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
|
||||
|
||||
|
||||
|
||||
|
||||
/** RAII class that provides access to a Berkeley database */
|
||||
class CDB
|
||||
{
|
||||
protected:
|
||||
@@ -257,6 +256,8 @@ public:
|
||||
{
|
||||
return Write(std::string("version"), nVersion);
|
||||
}
|
||||
|
||||
bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
|
||||
};
|
||||
|
||||
|
||||
@@ -265,7 +266,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** Access to the transaction database (blkindex.dat) */
|
||||
class CTxDB : public CDB
|
||||
{
|
||||
public:
|
||||
@@ -296,7 +297,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** Access to the (IP) address database (addr.dat) */
|
||||
class CAddrDB : public CDB
|
||||
{
|
||||
public:
|
||||
@@ -305,15 +306,14 @@ private:
|
||||
CAddrDB(const CAddrDB&);
|
||||
void operator=(const CAddrDB&);
|
||||
public:
|
||||
bool WriteAddress(const CAddress& addr);
|
||||
bool EraseAddress(const CAddress& addr);
|
||||
bool WriteAddrman(const CAddrMan& addr);
|
||||
bool LoadAddresses();
|
||||
};
|
||||
|
||||
bool LoadAddresses();
|
||||
|
||||
|
||||
|
||||
/** A key pool entry */
|
||||
class CKeyPool
|
||||
{
|
||||
public:
|
||||
@@ -342,15 +342,17 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** Error statuses for the wallet database */
|
||||
enum DBErrors
|
||||
{
|
||||
DB_LOAD_OK,
|
||||
DB_CORRUPT,
|
||||
DB_TOO_NEW,
|
||||
DB_LOAD_FAIL,
|
||||
DB_NEED_REWRITE
|
||||
};
|
||||
|
||||
/** Access to the wallet database (wallet.dat) */
|
||||
class CWalletDB : public CDB
|
||||
{
|
||||
public:
|
||||
@@ -419,6 +421,19 @@ public:
|
||||
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
|
||||
}
|
||||
|
||||
// Support for BIP 0013 : see https://en.bitcoin.it/wiki/BIP_0013
|
||||
bool ReadCScript(const uint160 &hash, CScript& redeemScript)
|
||||
{
|
||||
redeemScript.clear();
|
||||
return Read(std::make_pair(std::string("cscript"), hash), redeemScript);
|
||||
}
|
||||
|
||||
bool WriteCScript(const uint160& hash, const CScript& redeemScript)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false);
|
||||
}
|
||||
|
||||
bool WriteBestBlock(const CBlockLocator& locator)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
@@ -459,18 +474,29 @@ public:
|
||||
return Erase(std::make_pair(std::string("pool"), nPool));
|
||||
}
|
||||
|
||||
// Settings are no longer stored in wallet.dat; these are
|
||||
// used only for backwards compatibility:
|
||||
template<typename T>
|
||||
bool ReadSetting(const std::string& strKey, T& value)
|
||||
{
|
||||
return Read(std::make_pair(std::string("setting"), strKey), value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool WriteSetting(const std::string& strKey, const T& value)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Write(std::make_pair(std::string("setting"), strKey), value);
|
||||
}
|
||||
bool EraseSetting(const std::string& strKey)
|
||||
{
|
||||
nWalletDBUpdated++;
|
||||
return Erase(std::make_pair(std::string("setting"), strKey));
|
||||
}
|
||||
|
||||
bool WriteMinVersion(int nVersion)
|
||||
{
|
||||
return Write(std::string("minversion"), nVersion);
|
||||
}
|
||||
|
||||
bool ReadAccount(const std::string& strAccount, CAccount& account);
|
||||
bool WriteAccount(const std::string& strAccount, const CAccount& account);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// 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.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#ifdef _WIN32_IE
|
||||
#undef _WIN32_IE
|
||||
#endif
|
||||
@@ -21,9 +21,6 @@
|
||||
|
||||
// Include boost/foreach here as it defines __STDC_LIMIT_MACROS on some systems.
|
||||
#include <boost/foreach.hpp>
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
|
||||
#endif
|
||||
|
||||
#if (defined(__unix__) || defined(unix)) && !defined(USG)
|
||||
#include <sys/param.h> // to get BSD define
|
||||
@@ -44,7 +41,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
@@ -83,8 +79,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#pragma hdrstop
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "util.h"
|
||||
|
||||
444
src/init.cpp
444
src/init.cpp
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include "headers.h"
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "strlcpy.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
|
||||
#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
|
||||
@@ -20,6 +21,7 @@ Q_IMPORT_PLUGIN(qcncodecs)
|
||||
Q_IMPORT_PLUGIN(qjpcodecs)
|
||||
Q_IMPORT_PLUGIN(qtwcodecs)
|
||||
Q_IMPORT_PLUGIN(qkrcodecs)
|
||||
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
@@ -44,8 +46,8 @@ void Shutdown(void* parg)
|
||||
{
|
||||
static CCriticalSection cs_Shutdown;
|
||||
static bool fTaken;
|
||||
bool fFirstThread;
|
||||
CRITICAL_BLOCK(cs_Shutdown)
|
||||
bool fFirstThread = false;
|
||||
TRY_CRITICAL_BLOCK(cs_Shutdown)
|
||||
{
|
||||
fFirstThread = !fTaken;
|
||||
fTaken = true;
|
||||
@@ -148,94 +150,116 @@ bool AppInit2(int argc, char* argv[])
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
|
||||
#if !defined(QT_GUI)
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
if (mapArgs.count("-datadir"))
|
||||
if (!ReadConfigFile(mapArgs, mapMultiArgs))
|
||||
{
|
||||
if (filesystem::is_directory(filesystem::system_complete(mapArgs["-datadir"])))
|
||||
{
|
||||
filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]);
|
||||
strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
Shutdown(NULL);
|
||||
}
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
Shutdown(NULL);
|
||||
}
|
||||
|
||||
|
||||
ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
|
||||
#endif
|
||||
|
||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||
{
|
||||
string strUsage = string() +
|
||||
_("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
|
||||
_("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
|
||||
" bitcoin [options] \t " + "\n" +
|
||||
" bitcoin [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") +
|
||||
" bitcoin [options] help \t\t " + _("List commands\n") +
|
||||
" bitcoin [options] help <command> \t\t " + _("Get help for a command\n") +
|
||||
_("Options:\n") +
|
||||
" -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") +
|
||||
" -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") +
|
||||
" -gen \t\t " + _("Generate coins\n") +
|
||||
" -gen=0 \t\t " + _("Don't generate coins\n") +
|
||||
" -min \t\t " + _("Start minimized\n") +
|
||||
" -datadir=<dir> \t\t " + _("Specify data directory\n") +
|
||||
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)\n") +
|
||||
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
|
||||
" -dns \t " + _("Allow DNS lookups for addnode and connect\n") +
|
||||
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
|
||||
" -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
|
||||
" -nolisten \t " + _("Don't accept connections from outside\n") +
|
||||
" -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") +
|
||||
" -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") +
|
||||
" bitcoind [options] \t " + "\n" +
|
||||
" bitcoind [options] <command> [params]\t " + _("Send command to -server or bitcoind") + "\n" +
|
||||
" bitcoind [options] help \t\t " + _("List commands") + "\n" +
|
||||
" bitcoind [options] help <command> \t\t " + _("Get help for a command") + "\n" +
|
||||
_("Options:") + "\n" +
|
||||
" -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)") + "\n" +
|
||||
" -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)") + "\n" +
|
||||
" -gen \t\t " + _("Generate coins") + "\n" +
|
||||
" -gen=0 \t\t " + _("Don't generate coins") + "\n" +
|
||||
" -min \t\t " + _("Start minimized") + "\n" +
|
||||
" -splash \t\t " + _("Show splash screen on startup (default: 1)") + "\n" +
|
||||
" -datadir=<dir> \t\t " + _("Specify data directory") + "\n" +
|
||||
" -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" +
|
||||
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
|
||||
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
|
||||
" -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" +
|
||||
" -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
|
||||
" -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
|
||||
" -addnode=<ip> \t " + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
|
||||
" -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" +
|
||||
" -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" +
|
||||
" -listen \t " + _("Accept connections from outside (default: 1)") + "\n" +
|
||||
#ifdef QT_GUI
|
||||
" -lang=<lang> \t\t " + _("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
|
||||
#endif
|
||||
" -dnsseed \t " + _("Find peers using DNS lookup (default: 1)") + "\n" +
|
||||
" -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
|
||||
" -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
|
||||
" -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" +
|
||||
" -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" +
|
||||
#ifdef USE_UPNP
|
||||
#if USE_UPNP
|
||||
" -noupnp \t " + _("Don't attempt to use UPnP to map the listening port\n") +
|
||||
" -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" +
|
||||
#else
|
||||
" -upnp \t " + _("Attempt to use UPnP to map the listening port\n") +
|
||||
" -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" +
|
||||
#endif
|
||||
#endif
|
||||
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send\n") +
|
||||
#ifdef GUI
|
||||
" -server \t\t " + _("Accept command line and JSON-RPC commands\n") +
|
||||
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send") + "\n" +
|
||||
#ifdef QT_GUI
|
||||
" -server \t\t " + _("Accept command line and JSON-RPC commands") + "\n" +
|
||||
#endif
|
||||
#ifndef WIN32
|
||||
" -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
|
||||
#if !defined(WIN32) && !defined(QT_GUI)
|
||||
" -daemon \t\t " + _("Run in the background as a daemon and accept commands") + "\n" +
|
||||
#endif
|
||||
" -testnet \t\t " + _("Use the test network\n") +
|
||||
" -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
|
||||
" -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
|
||||
" -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") +
|
||||
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") +
|
||||
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") +
|
||||
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") +
|
||||
" -rescan \t " + _("Rescan the block chain for missing wallet transactions\n");
|
||||
" -testnet \t\t " + _("Use the test network") + "\n" +
|
||||
" -debug \t\t " + _("Output extra debugging information") + "\n" +
|
||||
" -logtimestamps \t " + _("Prepend debug output with timestamp") + "\n" +
|
||||
" -printtoconsole \t " + _("Send trace/debug info to console instead of debug.log file") + "\n" +
|
||||
#ifdef WIN32
|
||||
" -printtodebugger \t " + _("Send trace/debug info to debugger") + "\n" +
|
||||
#endif
|
||||
" -rpcuser=<user> \t " + _("Username for JSON-RPC connections") + "\n" +
|
||||
" -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections") + "\n" +
|
||||
" -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" +
|
||||
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
|
||||
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
|
||||
" -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
|
||||
" -upgradewallet \t " + _("Upgrade wallet to latest format") + "\n" +
|
||||
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" +
|
||||
" -rescan \t " + _("Rescan the block chain for missing wallet transactions") + "\n" +
|
||||
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
|
||||
" -checklevel=<n> \t\t " + _("How thorough the block verification is (0-6, default: 1)") + "\n";
|
||||
|
||||
#ifdef USE_SSL
|
||||
strUsage += string() +
|
||||
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") +
|
||||
" -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") +
|
||||
" -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") +
|
||||
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") +
|
||||
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
|
||||
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" +
|
||||
" -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" +
|
||||
" -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)") + "\n" +
|
||||
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)") + "\n" +
|
||||
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)") + "\n";
|
||||
#endif
|
||||
|
||||
strUsage += string() +
|
||||
" -? \t\t " + _("This help message\n");
|
||||
" -? \t\t " + _("This help message") + "\n";
|
||||
|
||||
// Remove tabs
|
||||
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
|
||||
#if defined(QT_GUI) && defined(WIN32)
|
||||
// On windows, show a message box, as there is no stderr
|
||||
wxMessageBox(strUsage, "Usage");
|
||||
#else
|
||||
fprintf(stderr, "%s", strUsage.c_str());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
fDebug = GetBoolArg("-debug");
|
||||
fAllowDNS = GetBoolArg("-dns");
|
||||
fTestNet = GetBoolArg("-testnet");
|
||||
if (fTestNet)
|
||||
{
|
||||
SoftSetBoolArg("-irc", true);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
fDebug = GetBoolArg("-debug");
|
||||
|
||||
#if !defined(WIN32) && !defined(QT_GUI)
|
||||
fDaemon = GetBoolArg("-daemon");
|
||||
#else
|
||||
fDaemon = false;
|
||||
@@ -252,15 +276,11 @@ bool AppInit2(int argc, char* argv[])
|
||||
#endif
|
||||
fPrintToConsole = GetBoolArg("-printtoconsole");
|
||||
fPrintToDebugger = GetBoolArg("-printtodebugger");
|
||||
|
||||
fTestNet = GetBoolArg("-testnet");
|
||||
bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
|
||||
fNoListen = GetBoolArg("-nolisten") || fTOR;
|
||||
fLogTimestamps = GetBoolArg("-logtimestamps");
|
||||
|
||||
#ifndef QT_GUI
|
||||
for (int i = 1; i < argc; i++)
|
||||
if (!IsSwitchChar(argv[i][0]))
|
||||
if (!IsSwitchChar(argv[i][0]) && !(strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0))
|
||||
fCommandLine = true;
|
||||
|
||||
if (fCommandLine)
|
||||
@@ -270,7 +290,7 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32) && !defined(QT_GUI)
|
||||
if (fDaemon)
|
||||
{
|
||||
// Daemonize
|
||||
@@ -317,37 +337,26 @@ bool AppInit2(int argc, char* argv[])
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind to the port early so we can tell if another instance is already running.
|
||||
string strErrors;
|
||||
if (!fNoListen)
|
||||
{
|
||||
if (!BindListenPort(strErrors))
|
||||
{
|
||||
wxMessageBox(strErrors, "Bitcoin");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream strErrors;
|
||||
//
|
||||
// Load data files
|
||||
//
|
||||
if (fDaemon)
|
||||
fprintf(stdout, "bitcoin server starting\n");
|
||||
strErrors = "";
|
||||
int64 nStart;
|
||||
|
||||
InitMessage(_("Loading addresses..."));
|
||||
printf("Loading addresses...\n");
|
||||
nStart = GetTimeMillis();
|
||||
if (!LoadAddresses())
|
||||
strErrors += _("Error loading addr.dat \n");
|
||||
strErrors << _("Error loading addr.dat") << "\n";
|
||||
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
|
||||
InitMessage(_("Loading block index..."));
|
||||
printf("Loading block index...\n");
|
||||
nStart = GetTimeMillis();
|
||||
if (!LoadBlockIndex())
|
||||
strErrors += _("Error loading blkindex.dat \n");
|
||||
strErrors << _("Error loading blkindex.dat") << "\n";
|
||||
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
|
||||
InitMessage(_("Loading wallet..."));
|
||||
@@ -359,12 +368,50 @@ bool AppInit2(int argc, char* argv[])
|
||||
if (nLoadWalletRet != DB_LOAD_OK)
|
||||
{
|
||||
if (nLoadWalletRet == DB_CORRUPT)
|
||||
strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
|
||||
strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n";
|
||||
else if (nLoadWalletRet == DB_TOO_NEW)
|
||||
strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
|
||||
strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin") << "\n";
|
||||
else if (nLoadWalletRet == DB_NEED_REWRITE)
|
||||
{
|
||||
strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n";
|
||||
printf("%s", strErrors.str().c_str());
|
||||
wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
strErrors += _("Error loading wallet.dat \n");
|
||||
strErrors << _("Error loading wallet.dat") << "\n";
|
||||
}
|
||||
|
||||
if (GetBoolArg("-upgradewallet", fFirstRun))
|
||||
{
|
||||
int nMaxVersion = GetArg("-upgradewallet", 0);
|
||||
if (nMaxVersion == 0) // the -walletupgrade without argument case
|
||||
{
|
||||
printf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
|
||||
nMaxVersion = CLIENT_VERSION;
|
||||
pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
|
||||
}
|
||||
else
|
||||
printf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
||||
if (nMaxVersion < pwalletMain->GetVersion())
|
||||
strErrors << _("Cannot downgrade wallet") << "\n";
|
||||
pwalletMain->SetMaxVersion(nMaxVersion);
|
||||
}
|
||||
|
||||
if (fFirstRun)
|
||||
{
|
||||
// Create new keyUser and set as default key
|
||||
RandAddSeedPerfmon();
|
||||
|
||||
std::vector<unsigned char> newDefaultKey;
|
||||
if (!pwalletMain->GetKeyFromPool(newDefaultKey, false))
|
||||
strErrors << _("Cannot initialize keypool") << "\n";
|
||||
pwalletMain->SetDefaultKey(newDefaultKey);
|
||||
if (!pwalletMain->SetAddressBookName(CBitcoinAddress(pwalletMain->vchDefaultKey), ""))
|
||||
strErrors << _("Cannot write default address") << "\n";
|
||||
}
|
||||
|
||||
printf("%s", strErrors.str().c_str());
|
||||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||
|
||||
RegisterWallet(pwalletMain);
|
||||
@@ -391,22 +438,26 @@ bool AppInit2(int argc, char* argv[])
|
||||
InitMessage(_("Done loading"));
|
||||
printf("Done loading\n");
|
||||
|
||||
//// debug print
|
||||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
|
||||
printf("nBestHeight = %d\n", nBestHeight);
|
||||
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
|
||||
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
|
||||
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
|
||||
//// debug print
|
||||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
|
||||
printf("nBestHeight = %d\n", nBestHeight);
|
||||
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
|
||||
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
|
||||
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
|
||||
|
||||
if (!strErrors.empty())
|
||||
if (!strErrors.str().empty())
|
||||
{
|
||||
wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
|
||||
wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add wallet transactions that aren't already in a block to mapTransactions
|
||||
pwalletMain->ReacceptWalletTransactions();
|
||||
|
||||
// Note: Bitcoin-QT stores several settings in the wallet, so we want
|
||||
// to load the wallet BEFORE parsing command-line arguments, so
|
||||
// the command-line/bitcoin.conf settings override GUI setting.
|
||||
|
||||
//
|
||||
// Parameters
|
||||
//
|
||||
@@ -446,12 +497,10 @@ bool AppInit2(int argc, char* argv[])
|
||||
return false;
|
||||
}
|
||||
|
||||
fGenerateBitcoins = GetBoolArg("-gen");
|
||||
|
||||
if (mapArgs.count("-proxy"))
|
||||
{
|
||||
fUseProxy = true;
|
||||
addrProxy = CAddress(mapArgs["-proxy"]);
|
||||
addrProxy = CService(mapArgs["-proxy"], 9050);
|
||||
if (!addrProxy.IsValid())
|
||||
{
|
||||
wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
|
||||
@@ -459,22 +508,48 @@ bool AppInit2(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050);
|
||||
if (fTor)
|
||||
{
|
||||
// Use SoftSetBoolArg here so user can override any of these if they wish.
|
||||
// Note: the GetBoolArg() calls for all of these must happen later.
|
||||
SoftSetBoolArg("-listen", false);
|
||||
SoftSetBoolArg("-irc", false);
|
||||
SoftSetBoolArg("-dnsseed", false);
|
||||
SoftSetBoolArg("-upnp", false);
|
||||
SoftSetBoolArg("-dns", false);
|
||||
}
|
||||
|
||||
fAllowDNS = GetBoolArg("-dns");
|
||||
fNoListen = !GetBoolArg("-listen", true);
|
||||
|
||||
// Continue to put "/P2SH/" in the coinbase to monitor
|
||||
// BIP16 support.
|
||||
// This can be removed eventually...
|
||||
const char* pszP2SH = "/P2SH/";
|
||||
COINBASE_FLAGS << std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH));
|
||||
|
||||
if (!fNoListen)
|
||||
{
|
||||
std::string strError;
|
||||
if (!BindListenPort(strError))
|
||||
{
|
||||
wxMessageBox(strError, "Bitcoin");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapArgs.count("-addnode"))
|
||||
{
|
||||
BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
|
||||
{
|
||||
CAddress addr(strAddr, fAllowDNS);
|
||||
CAddress addr(CService(strAddr, GetDefaultPort(), fAllowDNS));
|
||||
addr.nTime = 0; // so it won't relay unless successfully connected
|
||||
if (addr.IsValid())
|
||||
AddAddress(addr);
|
||||
addrman.Add(addr, CNetAddr("127.0.0.1"));
|
||||
}
|
||||
}
|
||||
|
||||
if (GetBoolArg("-nodnsseed"))
|
||||
printf("DNS seeding disabled\n");
|
||||
else
|
||||
DNSAddressSeed();
|
||||
|
||||
if (mapArgs.count("-paytxfee"))
|
||||
{
|
||||
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
|
||||
@@ -486,17 +561,6 @@ bool AppInit2(int argc, char* argv[])
|
||||
wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
||||
}
|
||||
|
||||
if (fHaveUPnP)
|
||||
{
|
||||
#if USE_UPNP
|
||||
if (GetBoolArg("-noupnp"))
|
||||
fUseUPnP = false;
|
||||
#else
|
||||
if (GetBoolArg("-upnp"))
|
||||
fUseUPnP = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Start the node
|
||||
//
|
||||
@@ -511,6 +575,11 @@ bool AppInit2(int argc, char* argv[])
|
||||
if (fServer)
|
||||
CreateThread(ThreadRPCServer, NULL);
|
||||
|
||||
#ifdef QT_GUI
|
||||
if(GetStartOnSystemStartup())
|
||||
SetStartOnSystemStartup(true); // Remove startup links to bitcoin-wx
|
||||
#endif
|
||||
|
||||
#if !defined(QT_GUI)
|
||||
while (1)
|
||||
Sleep(5000);
|
||||
@@ -518,3 +587,152 @@ bool AppInit2(int argc, char* argv[])
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
string StartupShortcutPath()
|
||||
{
|
||||
return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
|
||||
}
|
||||
|
||||
bool GetStartOnSystemStartup()
|
||||
{
|
||||
return filesystem::exists(StartupShortcutPath().c_str());
|
||||
}
|
||||
|
||||
bool SetStartOnSystemStartup(bool fAutoStart)
|
||||
{
|
||||
// If the shortcut exists already, remove it for updating
|
||||
remove(StartupShortcutPath().c_str());
|
||||
|
||||
if (fAutoStart)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
|
||||
// Get a pointer to the IShellLink interface.
|
||||
IShellLink* psl = NULL;
|
||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IShellLink,
|
||||
reinterpret_cast<void**>(&psl));
|
||||
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
// Get the current executable path
|
||||
TCHAR pszExePath[MAX_PATH];
|
||||
GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
|
||||
|
||||
TCHAR pszArgs[5] = TEXT("-min");
|
||||
|
||||
// Set the path to the shortcut target
|
||||
psl->SetPath(pszExePath);
|
||||
PathRemoveFileSpec(pszExePath);
|
||||
psl->SetWorkingDirectory(pszExePath);
|
||||
psl->SetShowCmd(SW_SHOWMINNOACTIVE);
|
||||
psl->SetArguments(pszArgs);
|
||||
|
||||
// Query IShellLink for the IPersistFile interface for
|
||||
// saving the shortcut in persistent storage.
|
||||
IPersistFile* ppf = NULL;
|
||||
hres = psl->QueryInterface(IID_IPersistFile,
|
||||
reinterpret_cast<void**>(&ppf));
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
WCHAR pwsz[MAX_PATH];
|
||||
// Ensure that the string is ANSI.
|
||||
MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().c_str(), -1, pwsz, MAX_PATH);
|
||||
// Save the link by calling IPersistFile::Save.
|
||||
hres = ppf->Save(pwsz, TRUE);
|
||||
ppf->Release();
|
||||
psl->Release();
|
||||
CoUninitialize();
|
||||
return true;
|
||||
}
|
||||
psl->Release();
|
||||
}
|
||||
CoUninitialize();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
// Follow the Desktop Application Autostart Spec:
|
||||
// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
|
||||
|
||||
boost::filesystem::path GetAutostartDir()
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
char* pszConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
if (pszConfigHome) return fs::path(pszConfigHome) / fs::path("autostart");
|
||||
char* pszHome = getenv("HOME");
|
||||
if (pszHome) return fs::path(pszHome) / fs::path(".config/autostart");
|
||||
return fs::path();
|
||||
}
|
||||
|
||||
boost::filesystem::path GetAutostartFilePath()
|
||||
{
|
||||
return GetAutostartDir() / boost::filesystem::path("bitcoin.desktop");
|
||||
}
|
||||
|
||||
bool GetStartOnSystemStartup()
|
||||
{
|
||||
boost::filesystem::ifstream optionFile(GetAutostartFilePath());
|
||||
if (!optionFile.good())
|
||||
return false;
|
||||
// Scan through file for "Hidden=true":
|
||||
string line;
|
||||
while (!optionFile.eof())
|
||||
{
|
||||
getline(optionFile, line);
|
||||
if (line.find("Hidden") != string::npos &&
|
||||
line.find("true") != string::npos)
|
||||
return false;
|
||||
}
|
||||
optionFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetStartOnSystemStartup(bool fAutoStart)
|
||||
{
|
||||
if (!fAutoStart)
|
||||
{
|
||||
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION >= 3
|
||||
unlink(GetAutostartFilePath().string().c_str());
|
||||
#else
|
||||
unlink(GetAutostartFilePath().native_file_string().c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
char pszExePath[MAX_PATH+1];
|
||||
memset(pszExePath, 0, sizeof(pszExePath));
|
||||
if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
|
||||
return false;
|
||||
|
||||
boost::filesystem::create_directories(GetAutostartDir());
|
||||
|
||||
boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
|
||||
if (!optionFile.good())
|
||||
return false;
|
||||
// Write a bitcoin.desktop file to the autostart directory:
|
||||
optionFile << "[Desktop Entry]\n";
|
||||
optionFile << "Type=Application\n";
|
||||
optionFile << "Name=Bitcoin\n";
|
||||
optionFile << "Exec=" << pszExePath << " -min\n";
|
||||
optionFile << "Terminal=false\n";
|
||||
optionFile << "Hidden=false\n";
|
||||
optionFile.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
// TODO: OSX startup stuff; see:
|
||||
// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
|
||||
|
||||
bool GetStartOnSystemStartup() { return false; }
|
||||
bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_INIT_H
|
||||
@@ -11,4 +11,7 @@ void Shutdown(void* parg);
|
||||
bool AppInit(int argc, char* argv[]);
|
||||
bool AppInit2(int argc, char* argv[]);
|
||||
|
||||
bool GetStartOnSystemStartup();
|
||||
bool SetStartOnSystemStartup(bool fAutoStart);
|
||||
|
||||
#endif
|
||||
|
||||
110
src/irc.cpp
110
src/irc.cpp
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// 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.
|
||||
|
||||
@@ -22,22 +22,25 @@ void ThreadIRCSeed2(void* parg);
|
||||
#pragma pack(push, 1)
|
||||
struct ircaddr
|
||||
{
|
||||
int ip;
|
||||
struct in_addr ip;
|
||||
short port;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
string EncodeAddress(const CAddress& addr)
|
||||
string EncodeAddress(const CService& addr)
|
||||
{
|
||||
struct ircaddr tmp;
|
||||
tmp.ip = addr.ip;
|
||||
tmp.port = addr.port;
|
||||
if (addr.GetInAddr(&tmp.ip))
|
||||
{
|
||||
tmp.port = htons(addr.GetPort());
|
||||
|
||||
vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
|
||||
return string("u") + EncodeBase58Check(vch);
|
||||
vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp));
|
||||
return string("u") + EncodeBase58Check(vch);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool DecodeAddress(string str, CAddress& addr)
|
||||
bool DecodeAddress(string str, CService& addr)
|
||||
{
|
||||
vector<unsigned char> vch;
|
||||
if (!DecodeBase58Check(str.substr(1), vch))
|
||||
@@ -48,7 +51,7 @@ bool DecodeAddress(string str, CAddress& addr)
|
||||
return false;
|
||||
memcpy(&tmp, &vch[0], sizeof(tmp));
|
||||
|
||||
addr = CAddress(tmp.ip, ntohs(tmp.port), NODE_NETWORK);
|
||||
addr = CService(tmp.ip, ntohs(tmp.port));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -73,57 +76,6 @@ static bool Send(SOCKET hSocket, const char* pszSend)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecvLine(SOCKET hSocket, string& strLine)
|
||||
{
|
||||
strLine = "";
|
||||
loop
|
||||
{
|
||||
char c;
|
||||
int nBytes = recv(hSocket, &c, 1, 0);
|
||||
if (nBytes > 0)
|
||||
{
|
||||
if (c == '\n')
|
||||
continue;
|
||||
if (c == '\r')
|
||||
return true;
|
||||
strLine += c;
|
||||
if (strLine.size() >= 9000)
|
||||
return true;
|
||||
}
|
||||
else if (nBytes <= 0)
|
||||
{
|
||||
if (fShutdown)
|
||||
return false;
|
||||
if (nBytes < 0)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
if (nErr == WSAEMSGSIZE)
|
||||
continue;
|
||||
if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
|
||||
{
|
||||
Sleep(10);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!strLine.empty())
|
||||
return true;
|
||||
if (nBytes == 0)
|
||||
{
|
||||
// socket closed
|
||||
printf("IRC socket closed\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// socket error
|
||||
int nErr = WSAGetLastError();
|
||||
printf("IRC recv failed: %d\n", nErr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RecvLineIRC(SOCKET hSocket, string& strLine)
|
||||
{
|
||||
loop
|
||||
@@ -204,7 +156,7 @@ bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet)
|
||||
}
|
||||
}
|
||||
|
||||
bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet)
|
||||
bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
|
||||
{
|
||||
Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str());
|
||||
|
||||
@@ -227,10 +179,10 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet)
|
||||
printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
|
||||
if (fUseProxy)
|
||||
return false;
|
||||
CAddress addr(strHost, 0, true);
|
||||
CNetAddr addr(strHost, true);
|
||||
if (!addr.IsValid())
|
||||
return false;
|
||||
ipRet = addr.ip;
|
||||
ipRet = addr;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -258,25 +210,21 @@ void ThreadIRCSeed2(void* parg)
|
||||
if (mapArgs.count("-connect") || fNoListen)
|
||||
return;
|
||||
|
||||
if (GetBoolArg("-noirc"))
|
||||
if (!GetBoolArg("-irc", false))
|
||||
return;
|
||||
|
||||
printf("ThreadIRCSeed started\n");
|
||||
int nErrorWait = 10;
|
||||
int nRetryWait = 10;
|
||||
bool fNameInUse = false;
|
||||
bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
|
||||
|
||||
while (!fShutdown)
|
||||
{
|
||||
//CAddress addrConnect("216.155.130.130:6667"); // chat.freenode.net
|
||||
CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org
|
||||
if (!fTOR)
|
||||
{
|
||||
//struct hostent* phostent = gethostbyname("chat.freenode.net");
|
||||
CAddress addrIRC("irc.lfnet.org", 6667, true);
|
||||
if (addrIRC.IsValid())
|
||||
addrConnect = addrIRC;
|
||||
}
|
||||
CService addrConnect("92.243.23.21", 6667); // irc.lfnet.org
|
||||
|
||||
CService addrIRC("irc.lfnet.org", 6667, true);
|
||||
if (addrIRC.IsValid())
|
||||
addrConnect = addrIRC;
|
||||
|
||||
SOCKET hSocket;
|
||||
if (!ConnectSocket(addrConnect, hSocket))
|
||||
@@ -330,15 +278,15 @@ void ThreadIRCSeed2(void* parg)
|
||||
Sleep(500);
|
||||
|
||||
// Get our external IP from the IRC server and re-nick before joining the channel
|
||||
CAddress addrFromIRC;
|
||||
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip))
|
||||
CNetAddr addrFromIRC;
|
||||
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
|
||||
{
|
||||
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str());
|
||||
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
|
||||
if (!fUseProxy && addrFromIRC.IsRoutable())
|
||||
{
|
||||
// IRC lets you to re-nick
|
||||
fGotExternalIP = true;
|
||||
addrLocalHost.ip = addrFromIRC.ip;
|
||||
addrLocalHost.SetIP(addrFromIRC);
|
||||
strMyName = EncodeAddress(addrLocalHost);
|
||||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str());
|
||||
}
|
||||
@@ -393,7 +341,7 @@ void ThreadIRCSeed2(void* parg)
|
||||
if (DecodeAddress(pszName, addr))
|
||||
{
|
||||
addr.nTime = GetAdjustedTime();
|
||||
if (AddAddress(addr, 51 * 60))
|
||||
if (addrman.Add(addr, addrConnect, 51 * 60))
|
||||
printf("IRC got new address: %s\n", addr.ToString().c_str());
|
||||
nGotIRCAddresses++;
|
||||
}
|
||||
@@ -406,10 +354,6 @@ void ThreadIRCSeed2(void* parg)
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
|
||||
// IRC usually blocks TOR, so only try once
|
||||
if (fTOR)
|
||||
return;
|
||||
|
||||
if (GetTime() - nStart > 20 * 60)
|
||||
{
|
||||
nErrorWait /= 3;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_IRC_H
|
||||
#define BITCOIN_IRC_H
|
||||
|
||||
bool RecvLine(SOCKET hSocket, std::string& strLine);
|
||||
void ThreadIRCSeed(void* parg);
|
||||
|
||||
extern int nGotIRCAddresses;
|
||||
|
||||
117
src/key.cpp
Normal file
117
src/key.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
|
||||
// Generate a private key from just the secret parameter
|
||||
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
|
||||
if (!eckey) return 0;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
pub_key = EC_POINT_new(group);
|
||||
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
|
||||
EC_KEY_set_private_key(eckey,priv_key);
|
||||
EC_KEY_set_public_key(eckey,pub_key);
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (pub_key)
|
||||
EC_POINT_free(pub_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
// 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
|
||||
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;
|
||||
|
||||
int ret = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
BIGNUM *x = NULL;
|
||||
BIGNUM *e = NULL;
|
||||
BIGNUM *order = NULL;
|
||||
BIGNUM *sor = NULL;
|
||||
BIGNUM *eor = NULL;
|
||||
BIGNUM *field = NULL;
|
||||
EC_POINT *R = NULL;
|
||||
EC_POINT *O = NULL;
|
||||
EC_POINT *Q = NULL;
|
||||
BIGNUM *rr = NULL;
|
||||
BIGNUM *zero = NULL;
|
||||
int n = 0;
|
||||
int i = recid / 2;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
|
||||
BN_CTX_start(ctx);
|
||||
order = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
|
||||
x = BN_CTX_get(ctx);
|
||||
if (!BN_copy(x, order)) { ret=-1; goto err; }
|
||||
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
|
||||
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
|
||||
field = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
|
||||
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
|
||||
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
|
||||
if (check)
|
||||
{
|
||||
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
|
||||
}
|
||||
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
n = EC_GROUP_get_degree(group);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
|
||||
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
|
||||
zero = BN_CTX_get(ctx);
|
||||
if (!BN_zero(zero)) { ret=-1; goto err; }
|
||||
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
|
||||
rr = BN_CTX_get(ctx);
|
||||
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
|
||||
sor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
|
||||
eor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
|
||||
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (R != NULL) EC_POINT_free(R);
|
||||
if (O != NULL) EC_POINT_free(O);
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
200
src/key.h
200
src/key.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEY_H
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "base58.h"
|
||||
|
||||
// secp160k1
|
||||
// const unsigned int PRIVATE_KEY_SIZE = 192;
|
||||
@@ -39,112 +38,8 @@
|
||||
// see www.keylength.com
|
||||
// script supports up to 75 for single byte push
|
||||
|
||||
int static inline EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
|
||||
if (!eckey) return 0;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
pub_key = EC_POINT_new(group);
|
||||
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
|
||||
EC_KEY_set_private_key(eckey,priv_key);
|
||||
EC_KEY_set_public_key(eckey,pub_key);
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
|
||||
if (pub_key)
|
||||
EC_POINT_free(pub_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
int static inline 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;
|
||||
|
||||
int ret = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
BIGNUM *x = NULL;
|
||||
BIGNUM *e = NULL;
|
||||
BIGNUM *order = NULL;
|
||||
BIGNUM *sor = NULL;
|
||||
BIGNUM *eor = NULL;
|
||||
BIGNUM *field = NULL;
|
||||
EC_POINT *R = NULL;
|
||||
EC_POINT *O = NULL;
|
||||
EC_POINT *Q = NULL;
|
||||
BIGNUM *rr = NULL;
|
||||
BIGNUM *zero = NULL;
|
||||
int n = 0;
|
||||
int i = recid / 2;
|
||||
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
|
||||
BN_CTX_start(ctx);
|
||||
order = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
|
||||
x = BN_CTX_get(ctx);
|
||||
if (!BN_copy(x, order)) { ret=-1; goto err; }
|
||||
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
|
||||
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
|
||||
field = BN_CTX_get(ctx);
|
||||
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
|
||||
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
|
||||
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
|
||||
if (check)
|
||||
{
|
||||
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
|
||||
}
|
||||
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
|
||||
n = EC_GROUP_get_degree(group);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
|
||||
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
|
||||
zero = BN_CTX_get(ctx);
|
||||
if (!BN_zero(zero)) { ret=-1; goto err; }
|
||||
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
|
||||
rr = BN_CTX_get(ctx);
|
||||
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
|
||||
sor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
|
||||
eor = BN_CTX_get(ctx);
|
||||
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
|
||||
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
|
||||
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (R != NULL) EC_POINT_free(R);
|
||||
if (O != NULL) EC_POINT_free(O);
|
||||
if (Q != NULL) EC_POINT_free(Q);
|
||||
return ret;
|
||||
}
|
||||
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
|
||||
{
|
||||
@@ -154,24 +49,41 @@ public:
|
||||
|
||||
|
||||
// secure_allocator is defined in serialize.h
|
||||
// CPrivKey is a serialized private key, with all parameters included (279 bytes)
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
|
||||
// CSecret is a serialization of just the secret parameter (32 bytes)
|
||||
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CSecret;
|
||||
|
||||
/** An encapsulated OpenSSL Elliptic Curve key (public and/or private) */
|
||||
class CKey
|
||||
{
|
||||
protected:
|
||||
EC_KEY* pkey;
|
||||
bool fSet;
|
||||
bool fCompressedPubKey;
|
||||
|
||||
void SetCompressedPubKey()
|
||||
{
|
||||
EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
|
||||
fCompressedPubKey = true;
|
||||
}
|
||||
|
||||
public:
|
||||
CKey()
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
CKey()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
CKey(const CKey& b)
|
||||
{
|
||||
pkey = EC_KEY_dup(b.pkey);
|
||||
@@ -198,10 +110,17 @@ public:
|
||||
return !fSet;
|
||||
}
|
||||
|
||||
void MakeNewKey()
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -214,7 +133,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetSecret(const CSecret& vchSecret)
|
||||
bool SetSecret(const CSecret& vchSecret, bool fCompressed = false)
|
||||
{
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
@@ -223,16 +142,21 @@ public:
|
||||
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)
|
||||
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() const
|
||||
CSecret GetSecret(bool &fCompressed) const
|
||||
{
|
||||
CSecret vchRet;
|
||||
vchRet.resize(32);
|
||||
@@ -243,6 +167,7 @@ public:
|
||||
int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
|
||||
if (n != nBytes)
|
||||
throw key_error("CKey::GetSecret(): BN_bn2bin failed");
|
||||
fCompressed = fCompressedPubKey;
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
@@ -264,6 +189,8 @@ public:
|
||||
if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
|
||||
return false;
|
||||
fSet = true;
|
||||
if (vchPubKey.size() == 33)
|
||||
SetCompressedPubKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -281,17 +208,21 @@ public:
|
||||
|
||||
bool Sign(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
vchSig.clear();
|
||||
unsigned char pchSig[10000];
|
||||
unsigned int nSize = 0;
|
||||
if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), pchSig, &nSize, pkey))
|
||||
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);
|
||||
memcpy(&vchSig[0], pchSig, nSize);
|
||||
}
|
||||
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 SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
bool fOk = false;
|
||||
@@ -309,6 +240,8 @@ public:
|
||||
{
|
||||
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())
|
||||
{
|
||||
@@ -318,9 +251,9 @@ public:
|
||||
}
|
||||
|
||||
if (nRecId == -1)
|
||||
throw key_error("CKEy::SignCompact() : unable to construct recoverable key");
|
||||
throw key_error("CKey::SignCompact() : unable to construct recoverable key");
|
||||
|
||||
vchSig[0] = nRecId+27;
|
||||
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;
|
||||
@@ -330,11 +263,15 @@ public:
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (vchSig[0]<27 || vchSig[0]>=31)
|
||||
int nV = vchSig[0];
|
||||
if (nV<27 || nV>=35)
|
||||
return false;
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
BN_bin2bn(&vchSig[1],32,sig->r);
|
||||
@@ -342,7 +279,12 @@ public:
|
||||
|
||||
EC_KEY_free(pkey);
|
||||
pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), vchSig[0] - 27, 0) == 1)
|
||||
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);
|
||||
@@ -359,6 +301,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verify a compact signature
|
||||
bool VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
|
||||
{
|
||||
CKey key;
|
||||
@@ -369,9 +312,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
CBitcoinAddress GetAddress() const
|
||||
bool IsValid()
|
||||
{
|
||||
return CBitcoinAddress(GetPubKey());
|
||||
if (!fSet)
|
||||
return false;
|
||||
|
||||
bool fCompr;
|
||||
CSecret secret = GetSecret(fCompr);
|
||||
CKey key2;
|
||||
key2.SetSecret(secret, fCompr);
|
||||
return GetPubKey() == key2.GetPubKey();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "headers.h"
|
||||
#include "db.h"
|
||||
#include "crypter.h"
|
||||
|
||||
std::vector<unsigned char> CKeyStore::GenerateNewKey()
|
||||
{
|
||||
RandAddSeedPerfmon();
|
||||
CKey key;
|
||||
key.MakeNewKey();
|
||||
if (!AddKey(key))
|
||||
throw std::runtime_error("CKeyStore::GenerateNewKey() : AddKey failed");
|
||||
return key.GetPubKey();
|
||||
}
|
||||
#include "db.h"
|
||||
#include "script.h"
|
||||
|
||||
bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned char> &vchPubKeyOut) const
|
||||
{
|
||||
@@ -28,11 +19,43 @@ bool CKeyStore::GetPubKey(const CBitcoinAddress &address, std::vector<unsigned c
|
||||
|
||||
bool CBasicKeyStore::AddKey(const CKey& key)
|
||||
{
|
||||
bool fCompressed = false;
|
||||
CSecret secret = key.GetSecret(fCompressed);
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
mapKeys[key.GetAddress()] = key.GetSecret();
|
||||
mapKeys[CBitcoinAddress(key.GetPubKey())] = make_pair(secret, fCompressed);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::AddCScript(const CScript& redeemScript)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
mapScripts[Hash160(redeemScript)] = redeemScript;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::HaveCScript(const uint160& hash) const
|
||||
{
|
||||
bool result;
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
result = (mapScripts.count(hash) > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool CBasicKeyStore::GetCScript(const uint160 &hash, CScript& redeemScriptOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
ScriptMap::const_iterator mi = mapScripts.find(hash);
|
||||
if (mi != mapScripts.end())
|
||||
{
|
||||
redeemScriptOut = (*mi).second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
@@ -46,16 +69,6 @@ bool CCryptoKeyStore::SetCrypted()
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CCryptoKeyStore::GenerateNewKey()
|
||||
{
|
||||
RandAddSeedPerfmon();
|
||||
CKey key;
|
||||
key.MakeNewKey();
|
||||
if (!AddKey(key))
|
||||
throw std::runtime_error("CCryptoKeyStore::GenerateNewKey() : AddKey failed");
|
||||
return key.GetPubKey();
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
@@ -72,6 +85,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
|
||||
if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
return false;
|
||||
CKey key;
|
||||
key.SetPubKey(vchPubKey);
|
||||
key.SetSecret(vchSecret);
|
||||
if (key.GetPubKey() == vchPubKey)
|
||||
break;
|
||||
@@ -94,7 +108,8 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
std::vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||
if (!EncryptSecret(vMasterKey, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
bool fCompressed;
|
||||
if (!EncryptSecret(vMasterKey, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
|
||||
@@ -131,6 +146,7 @@ bool CCryptoKeyStore::GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
CSecret vchSecret;
|
||||
if (!DecryptSecret(vMasterKey, vchCryptedSecret, Hash(vchPubKey.begin(), vchPubKey.end()), vchSecret))
|
||||
return false;
|
||||
keyOut.SetPubKey(vchPubKey);
|
||||
keyOut.SetSecret(vchSecret);
|
||||
return true;
|
||||
}
|
||||
@@ -163,14 +179,15 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
CKey key;
|
||||
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
|
||||
{
|
||||
if (!key.SetSecret(mKey.second))
|
||||
CKey key;
|
||||
if (!key.SetSecret(mKey.second.first, mKey.second.second))
|
||||
return false;
|
||||
const std::vector<unsigned char> vchPubKey = key.GetPubKey();
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
bool fCompressed;
|
||||
if (!EncryptSecret(vMasterKeyIn, key.GetSecret(fCompressed), Hash(vchPubKey.begin(), vchPubKey.end()), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
|
||||
@@ -1,31 +1,53 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_KEYSTORE_H
|
||||
#define BITCOIN_KEYSTORE_H
|
||||
|
||||
#include "crypter.h"
|
||||
#include "script.h"
|
||||
|
||||
/** A virtual base class for key stores */
|
||||
class CKeyStore
|
||||
{
|
||||
protected:
|
||||
mutable CCriticalSection cs_KeyStore;
|
||||
|
||||
public:
|
||||
// Add a key to the store.
|
||||
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 std::vector<unsigned char> GenerateNewKey();
|
||||
|
||||
// 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 GetSecret(const CBitcoinAddress &address, CSecret& vchSecret, bool &fCompressed) const
|
||||
{
|
||||
CKey key;
|
||||
if (!GetKey(address, key))
|
||||
return false;
|
||||
vchSecret = key.GetSecret(fCompressed);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<CBitcoinAddress, CSecret> KeyMap;
|
||||
typedef std::map<CBitcoinAddress, std::pair<CSecret, bool> > KeyMap;
|
||||
typedef std::map<uint160, CScript > ScriptMap;
|
||||
|
||||
/** Basic key store, that keeps keys in an address->secret map */
|
||||
class CBasicKeyStore : public CKeyStore
|
||||
{
|
||||
protected:
|
||||
KeyMap mapKeys;
|
||||
ScriptMap mapScripts;
|
||||
|
||||
public:
|
||||
bool AddKey(const CKey& key);
|
||||
@@ -36,23 +58,43 @@ public:
|
||||
result = (mapKeys.count(address) > 0);
|
||||
return result;
|
||||
}
|
||||
bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const
|
||||
void GetKeys(std::set<CBitcoinAddress> &setAddress) const
|
||||
{
|
||||
setAddress.clear();
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
KeyMap::const_iterator mi = mapKeys.begin();
|
||||
while (mi != mapKeys.end())
|
||||
{
|
||||
setAddress.insert((*mi).first);
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool GetKey(const CBitcoinAddress &address, CKey &keyOut) const
|
||||
{
|
||||
CRITICAL_BLOCK(cs_KeyStore)
|
||||
{
|
||||
KeyMap::const_iterator mi = mapKeys.find(address);
|
||||
if (mi != mapKeys.end())
|
||||
{
|
||||
keyOut.SetSecret((*mi).second);
|
||||
keyOut.Reset();
|
||||
keyOut.SetSecret((*mi).second.first, (*mi).second.second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual bool AddCScript(const CScript& redeemScript);
|
||||
virtual bool HaveCScript(const uint160 &hash) const;
|
||||
virtual bool GetCScript(const uint160 &hash, CScript& redeemScriptOut) const;
|
||||
};
|
||||
|
||||
typedef std::map<CBitcoinAddress, std::pair<std::vector<unsigned char>, 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.
|
||||
*/
|
||||
class CCryptoKeyStore : public CBasicKeyStore
|
||||
{
|
||||
private:
|
||||
@@ -104,7 +146,6 @@ public:
|
||||
}
|
||||
|
||||
virtual bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
std::vector<unsigned char> GenerateNewKey();
|
||||
bool AddKey(const CKey& key);
|
||||
bool HaveKey(const CBitcoinAddress &address) const
|
||||
{
|
||||
@@ -118,6 +159,21 @@ public:
|
||||
}
|
||||
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
|
||||
{
|
||||
if (!IsCrypted())
|
||||
{
|
||||
CBasicKeyStore::GetKeys(setAddress);
|
||||
return;
|
||||
}
|
||||
setAddress.clear();
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
while (mi != mapCryptedKeys.end())
|
||||
{
|
||||
setAddress.insert((*mi).first);
|
||||
mi++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
957
src/main.cpp
957
src/main.cpp
File diff suppressed because it is too large
Load Diff
280
src/main.h
280
src/main.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_MAIN_H
|
||||
@@ -25,11 +25,15 @@ class CAddress;
|
||||
class CInv;
|
||||
class CRequestTracker;
|
||||
class CNode;
|
||||
class CBlockIndex;
|
||||
|
||||
static const int CLIENT_VERSION = 60006;
|
||||
static const bool VERSION_IS_BETA = true;
|
||||
extern const std::string CLIENT_NAME;
|
||||
|
||||
static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
||||
static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
|
||||
static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
|
||||
static const int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
|
||||
static const int64 COIN = 100000000;
|
||||
static const int64 CENT = 1000000;
|
||||
static const int64 MIN_TX_FEE = 50000;
|
||||
@@ -46,6 +50,9 @@ static const int fHaveUPnP = false;
|
||||
#endif
|
||||
|
||||
|
||||
extern CScript COINBASE_FLAGS;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,7 +66,11 @@ extern CBigNum bnBestChainWork;
|
||||
extern CBigNum bnBestInvalidWork;
|
||||
extern uint256 hashBestChain;
|
||||
extern CBlockIndex* pindexBest;
|
||||
extern uint64 nPooledTx;
|
||||
extern unsigned int nTransactionsUpdated;
|
||||
extern uint64 nLastBlockTx;
|
||||
extern uint64 nLastBlockSize;
|
||||
extern const std::string strMessageMagic;
|
||||
extern double dHashesPerSec;
|
||||
extern int64 nHPSTimerStart;
|
||||
extern int64 nTimeBestReceived;
|
||||
@@ -67,13 +78,7 @@ extern CCriticalSection cs_setpwalletRegistered;
|
||||
extern std::set<CWallet*> setpwalletRegistered;
|
||||
|
||||
// Settings
|
||||
extern int fGenerateBitcoins;
|
||||
extern int64 nTransactionFee;
|
||||
extern int fLimitProcessors;
|
||||
extern int nLimitProcessors;
|
||||
extern int fMinimizeToTray;
|
||||
extern int fMinimizeOnClose;
|
||||
extern int fUseUPnP;
|
||||
|
||||
|
||||
|
||||
@@ -99,7 +104,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
||||
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
|
||||
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||
int GetTotalBlocksEstimate();
|
||||
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
|
||||
int GetNumBlocksOfPeers();
|
||||
bool IsInitialBlockDownload();
|
||||
std::string GetWarnings(std::string strFor);
|
||||
@@ -117,21 +122,7 @@ std::string GetWarnings(std::string strFor);
|
||||
|
||||
bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
|
||||
|
||||
template<typename T>
|
||||
bool WriteSetting(const std::string& strKey, const T& value)
|
||||
{
|
||||
bool fOk = false;
|
||||
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
|
||||
{
|
||||
std::string strWalletFile;
|
||||
if (!GetWalletFile(pwallet, strWalletFile))
|
||||
continue;
|
||||
fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
|
||||
}
|
||||
return fOk;
|
||||
}
|
||||
|
||||
|
||||
/** Position on disk for a particular transaction. */
|
||||
class CDiskTxPos
|
||||
{
|
||||
public:
|
||||
@@ -183,7 +174,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** An inpoint - a combination of a transaction and an index n into its vin */
|
||||
class CInPoint
|
||||
{
|
||||
public:
|
||||
@@ -198,7 +189,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
/** An outpoint - a combination of a transaction hash and an index n into its vout */
|
||||
class COutPoint
|
||||
{
|
||||
public:
|
||||
@@ -240,11 +231,10 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// An input of a transaction. It contains the location of the previous
|
||||
// transaction's output that it claims and a signature that matches the
|
||||
// output's public key.
|
||||
//
|
||||
/** An input of a transaction. It contains the location of the previous
|
||||
* transaction's output that it claims and a signature that matches the
|
||||
* output's public key.
|
||||
*/
|
||||
class CTxIn
|
||||
{
|
||||
public:
|
||||
@@ -254,17 +244,17 @@ public:
|
||||
|
||||
CTxIn()
|
||||
{
|
||||
nSequence = UINT_MAX;
|
||||
nSequence = std::numeric_limits<unsigned int>::max();
|
||||
}
|
||||
|
||||
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
|
||||
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
prevout = prevoutIn;
|
||||
scriptSig = scriptSigIn;
|
||||
nSequence = nSequenceIn;
|
||||
}
|
||||
|
||||
CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
|
||||
CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
prevout = COutPoint(hashPrevTx, nOut);
|
||||
scriptSig = scriptSigIn;
|
||||
@@ -280,7 +270,7 @@ public:
|
||||
|
||||
bool IsFinal() const
|
||||
{
|
||||
return (nSequence == UINT_MAX);
|
||||
return (nSequence == std::numeric_limits<unsigned int>::max());
|
||||
}
|
||||
|
||||
friend bool operator==(const CTxIn& a, const CTxIn& b)
|
||||
@@ -304,7 +294,7 @@ public:
|
||||
str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
|
||||
else
|
||||
str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
|
||||
if (nSequence != UINT_MAX)
|
||||
if (nSequence != std::numeric_limits<unsigned int>::max())
|
||||
str += strprintf(", nSequence=%u", nSequence);
|
||||
str += ")";
|
||||
return str;
|
||||
@@ -319,10 +309,9 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// An output of a transaction. It contains the public key that the next input
|
||||
// must be able to sign with to claim it.
|
||||
//
|
||||
/** An output of a transaction. It contains the public key that the next input
|
||||
* must be able to sign with to claim it.
|
||||
*/
|
||||
class CTxOut
|
||||
{
|
||||
public:
|
||||
@@ -389,10 +378,18 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The basic transaction that is broadcasted on the network and contained in
|
||||
// blocks. A transaction can contain multiple inputs and outputs.
|
||||
//
|
||||
enum GetMinFee_mode
|
||||
{
|
||||
GMF_BLOCK,
|
||||
GMF_RELAY,
|
||||
GMF_SEND,
|
||||
};
|
||||
|
||||
typedef std::map<uint256, std::pair<CTxIndex, CTransaction> > MapPrevTx;
|
||||
|
||||
/** The basic transaction that is broadcasted on the network and contained in
|
||||
* blocks. A transaction can contain multiple inputs and outputs.
|
||||
*/
|
||||
class CTransaction
|
||||
{
|
||||
public:
|
||||
@@ -464,7 +461,7 @@ public:
|
||||
return false;
|
||||
|
||||
bool fNewer = false;
|
||||
unsigned int nLowest = UINT_MAX;
|
||||
unsigned int nLowest = std::numeric_limits<unsigned int>::max();
|
||||
for (int i = 0; i < vin.size(); i++)
|
||||
{
|
||||
if (vin[i].nSequence != old.vin[i].nSequence)
|
||||
@@ -489,27 +486,35 @@ public:
|
||||
return (vin.size() == 1 && vin[0].prevout.IsNull());
|
||||
}
|
||||
|
||||
int GetSigOpCount() const
|
||||
{
|
||||
int n = 0;
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
n += txin.scriptSig.GetSigOpCount();
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
n += txout.scriptPubKey.GetSigOpCount();
|
||||
return n;
|
||||
}
|
||||
/** Check for standard transaction types
|
||||
@return True if all outputs (scriptPubKeys) use only standard transaction forms
|
||||
*/
|
||||
bool IsStandard() const;
|
||||
|
||||
bool IsStandard() const
|
||||
{
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
if (!txin.scriptSig.IsPushOnly())
|
||||
return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
if (!::IsStandard(txout.scriptPubKey))
|
||||
return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
|
||||
return true;
|
||||
}
|
||||
/** Check for standard transaction types
|
||||
@param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
@return True if all inputs (scriptSigs) use only standard transaction forms
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
bool AreInputsStandard(const MapPrevTx& mapInputs) const;
|
||||
|
||||
/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
|
||||
@return number of sigops this transaction's outputs will produce when spent
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
int GetLegacySigOpCount() const;
|
||||
|
||||
/** Count ECDSA signature operations in pay-to-script-hash inputs.
|
||||
|
||||
@param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
@return maximum number of sigops required to validate this transaction's inputs
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
int GetP2SHSigOpCount(const MapPrevTx& mapInputs) const;
|
||||
|
||||
/** Amount of bitcoins spent by this transaction.
|
||||
@return sum of all outputs (note: does not include fees)
|
||||
*/
|
||||
int64 GetValueOut() const
|
||||
{
|
||||
int64 nValueOut = 0;
|
||||
@@ -522,6 +527,16 @@ public:
|
||||
return nValueOut;
|
||||
}
|
||||
|
||||
/** Amount of bitcoins coming in to this transaction
|
||||
Note that lightweight clients may not know anything besides the hash of previous transactions,
|
||||
so may not be able to calculate this.
|
||||
|
||||
@param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
@return Sum of value of all inputs (scriptSigs)
|
||||
@see CTransaction::FetchInputs
|
||||
*/
|
||||
int64 GetValueIn(const MapPrevTx& mapInputs) const;
|
||||
|
||||
static bool AllowFree(double dPriority)
|
||||
{
|
||||
// Large (in bytes) low-priority (new, small-coin) transactions
|
||||
@@ -529,10 +544,10 @@ public:
|
||||
return dPriority > COIN * 144 / 250;
|
||||
}
|
||||
|
||||
int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const
|
||||
int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const
|
||||
{
|
||||
// Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
|
||||
int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
|
||||
int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
|
||||
|
||||
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
|
||||
unsigned int nNewBlockSize = nBlockSize + nBytes;
|
||||
@@ -636,13 +651,42 @@ public:
|
||||
bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
|
||||
bool ReadFromDisk(COutPoint prevout);
|
||||
bool DisconnectInputs(CTxDB& txdb);
|
||||
bool ConnectInputs(CTxDB& txdb, std::map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
|
||||
CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
|
||||
|
||||
/** Fetch from memory and/or disk. inputsRet keys are transaction hashes.
|
||||
|
||||
@param[in] txdb Transaction database
|
||||
@param[in] mapTestPool List of pending changes to the transaction index database
|
||||
@param[in] fBlock True if being called to add a new best-block to the chain
|
||||
@param[in] fMiner True if being called by CreateNewBlock
|
||||
@param[out] inputsRet Pointers to this transaction's inputs
|
||||
@param[out] fInvalid returns true if transaction is invalid
|
||||
@return Returns true if all inputs are in txdb or mapTestPool
|
||||
*/
|
||||
bool FetchInputs(CTxDB& txdb, const std::map<uint256, CTxIndex>& mapTestPool,
|
||||
bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid);
|
||||
|
||||
/** Sanity check previous transactions, then, if all checks succeed,
|
||||
mark them as spent by this transaction.
|
||||
|
||||
@param[in] inputs Previous transactions (from FetchInputs)
|
||||
@param[out] mapTestPool Keeps track of inputs that need to be updated on disk
|
||||
@param[in] posThisTx Position of this transaction on disk
|
||||
@param[in] pindexBlock
|
||||
@param[in] fBlock true if called from ConnectBlock
|
||||
@param[in] fMiner true if called from CreateNewBlock
|
||||
@param[in] fStrictPayToScriptHash true if fully validating p2sh transactions
|
||||
@return Returns true if all checks succeed
|
||||
*/
|
||||
bool ConnectInputs(MapPrevTx inputs,
|
||||
std::map<uint256, CTxIndex>& mapTestPool, const CDiskTxPos& posThisTx,
|
||||
const CBlockIndex* pindexBlock, bool fBlock, bool fMiner, bool fStrictPayToScriptHash=true);
|
||||
bool ClientConnectInputs();
|
||||
bool CheckTransaction() const;
|
||||
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
|
||||
bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
|
||||
|
||||
protected:
|
||||
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
|
||||
bool AddToMemoryPoolUnchecked();
|
||||
public:
|
||||
bool RemoveFromMemoryPool();
|
||||
@@ -652,9 +696,7 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A transaction with a merkle branch linking it to the block chain
|
||||
//
|
||||
/** A transaction with a merkle branch linking it to the block chain. */
|
||||
class CMerkleTx : public CTransaction
|
||||
{
|
||||
public:
|
||||
@@ -695,8 +737,8 @@ public:
|
||||
|
||||
|
||||
int SetMerkleBranch(const CBlock* pblock=NULL);
|
||||
int GetDepthInMainChain(int& nHeightRet) const;
|
||||
int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
|
||||
int GetDepthInMainChain(CBlockIndex* &pindexRet) const;
|
||||
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
|
||||
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
|
||||
int GetBlocksToMaturity() const;
|
||||
bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
|
||||
@@ -706,11 +748,10 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// A txdb record that contains the disk location of a transaction and the
|
||||
// locations of transactions that spend its outputs. vSpent is really only
|
||||
// used as a flag, but having the location is very helpful for debugging.
|
||||
//
|
||||
/** A txdb record that contains the disk location of a transaction and the
|
||||
* locations of transactions that spend its outputs. vSpent is really only
|
||||
* used as a flag, but having the location is very helpful for debugging.
|
||||
*/
|
||||
class CTxIndex
|
||||
{
|
||||
public:
|
||||
@@ -758,23 +799,23 @@ public:
|
||||
return !(a == b);
|
||||
}
|
||||
int GetDepthInMainChain() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Nodes collect new transactions into a block, hash them into a hash tree,
|
||||
// and scan through nonce values to make the block's hash satisfy proof-of-work
|
||||
// requirements. When they solve the proof-of-work, they broadcast the block
|
||||
// to everyone and the block is added to the block chain. The first transaction
|
||||
// in the block is a special one that creates a new coin owned by the creator
|
||||
// of the block.
|
||||
//
|
||||
// Blocks are appended to blk0001.dat files on disk. Their location on disk
|
||||
// is indexed by CBlockIndex objects in memory.
|
||||
//
|
||||
/** Nodes collect new transactions into a block, hash them into a hash tree,
|
||||
* and scan through nonce values to make the block's hash satisfy proof-of-work
|
||||
* requirements. When they solve the proof-of-work, they broadcast the block
|
||||
* to everyone and the block is added to the block chain. The first transaction
|
||||
* in the block is a special one that creates a new coin owned by the creator
|
||||
* of the block.
|
||||
*
|
||||
* Blocks are appended to blk0001.dat files on disk. Their location on disk
|
||||
* is indexed by CBlockIndex objects in memory.
|
||||
*/
|
||||
class CBlock
|
||||
{
|
||||
public:
|
||||
@@ -846,13 +887,7 @@ public:
|
||||
return (int64)nTime;
|
||||
}
|
||||
|
||||
int GetSigOpCount() const
|
||||
{
|
||||
int n = 0;
|
||||
BOOST_FOREACH(const CTransaction& tx, vtx)
|
||||
n += tx.GetSigOpCount();
|
||||
return n;
|
||||
}
|
||||
void UpdateTime(const CBlockIndex* pindexPrev);
|
||||
|
||||
|
||||
uint256 BuildMerkleTree() const
|
||||
@@ -988,6 +1023,9 @@ public:
|
||||
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
|
||||
bool CheckBlock() const;
|
||||
bool AcceptBlock();
|
||||
|
||||
private:
|
||||
bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew);
|
||||
};
|
||||
|
||||
|
||||
@@ -995,14 +1033,13 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The block chain is a tree shaped structure starting with the
|
||||
// genesis block at the root, with each block potentially having multiple
|
||||
// candidates to be the next block. pprev and pnext link a path through the
|
||||
// main/longest chain. A blockindex may have multiple pprev pointing back
|
||||
// to it, but pnext will only point forward to the longest branch, or will
|
||||
// be null if the block is not part of the longest chain.
|
||||
//
|
||||
/** The block chain is a tree shaped structure starting with the
|
||||
* genesis block at the root, with each block potentially having multiple
|
||||
* candidates to be the next block. pprev and pnext link a path through the
|
||||
* main/longest chain. A blockindex may have multiple pprev pointing back
|
||||
* to it, but pnext will only point forward to the longest branch, or will
|
||||
* be null if the block is not part of the longest chain.
|
||||
*/
|
||||
class CBlockIndex
|
||||
{
|
||||
public:
|
||||
@@ -1159,9 +1196,7 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Used to marshal pointers into hashes for db storage.
|
||||
//
|
||||
/** Used to marshal pointers into hashes for db storage. */
|
||||
class CDiskBlockIndex : public CBlockIndex
|
||||
{
|
||||
public:
|
||||
@@ -1236,11 +1271,10 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Describes a place in the block chain to another node such that if the
|
||||
// other node doesn't have the same branch, it can find a recent common trunk.
|
||||
// The further back it is, the further before the fork it may be.
|
||||
//
|
||||
/** Describes a place in the block chain to another node such that if the
|
||||
* other node doesn't have the same branch, it can find a recent common trunk.
|
||||
* The further back it is, the further before the fork it may be.
|
||||
*/
|
||||
class CBlockLocator
|
||||
{
|
||||
protected:
|
||||
@@ -1263,6 +1297,11 @@ public:
|
||||
Set((*mi).second);
|
||||
}
|
||||
|
||||
CBlockLocator(const std::vector<uint256>& vHaveIn)
|
||||
{
|
||||
vHave = vHaveIn;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
if (!(nType & SER_GETHASH))
|
||||
@@ -1367,13 +1406,12 @@ 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.
|
||||
//
|
||||
/** 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:
|
||||
@@ -1473,6 +1511,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
||||
class CAlert : public CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
@@ -1521,6 +1560,7 @@ public:
|
||||
|
||||
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)));
|
||||
@@ -1528,7 +1568,7 @@ public:
|
||||
|
||||
bool AppliesToMe() const
|
||||
{
|
||||
return AppliesTo(VERSION, ::pszSubVer);
|
||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
|
||||
}
|
||||
|
||||
bool RelayTo(CNode* pnode) const
|
||||
|
||||
@@ -29,27 +29,6 @@ LIBS= \
|
||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
|
||||
DEBUGFLAGS=-g
|
||||
CFLAGS=-O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
HEADERS = \
|
||||
base58.h \
|
||||
bignum.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
init.h \
|
||||
irc.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
main.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
protocol.h \
|
||||
bitcoinrpc.h \
|
||||
script.h \
|
||||
serialize.h \
|
||||
strlcpy.h \
|
||||
uint256.h \
|
||||
util.h \
|
||||
wallet.h
|
||||
|
||||
|
||||
ifdef USE_UPNP
|
||||
@@ -60,8 +39,15 @@ 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
|
||||
|
||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
obj/init.o \
|
||||
obj/irc.o \
|
||||
@@ -70,29 +56,29 @@ OBJS= \
|
||||
obj/net.o \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
|
||||
all: bitcoind.exe
|
||||
|
||||
obj/nogui/%.o: %.cpp $(HEADERS)
|
||||
obj/%.o: %.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/nogui/%)
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
|
||||
obj/test/%.o: obj/test/%.cpp $(HEADERS)
|
||||
i586-mingw32msvc-g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%))
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
i586-mingw32msvc-g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lboost_unit_test_framework-mt-s
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f obj/*.o
|
||||
-rm -f obj/nogui/*.o
|
||||
-rm -f obj/test/*.o
|
||||
-rm -f test/*.o
|
||||
-rm -f headers.h.gch
|
||||
|
||||
@@ -26,27 +26,7 @@ LIBS= \
|
||||
DEFS=-DWIN32 -D_WINDOWS -DNOPCH -DUSE_SSL -DBOOST_THREAD_USE_LIB
|
||||
DEBUGFLAGS=-g
|
||||
CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
HEADERS = \
|
||||
base58.h \
|
||||
bignum.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
init.h \
|
||||
irc.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
main.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
protocol.h \
|
||||
bitcoinrpc.h \
|
||||
script.h \
|
||||
serialize.h \
|
||||
strlcpy.h \
|
||||
uint256.h \
|
||||
util.h \
|
||||
wallet.h
|
||||
|
||||
|
||||
ifdef USE_UPNP
|
||||
INCLUDEPATHS += -I"C:\miniupnpc-1.6-mgw"
|
||||
@@ -57,8 +37,15 @@ 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
|
||||
|
||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
obj/init.o \
|
||||
obj/irc.o \
|
||||
@@ -67,6 +54,7 @@ OBJS= \
|
||||
obj/net.o \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
@@ -74,16 +62,16 @@ OBJS= \
|
||||
|
||||
all: bitcoind.exe
|
||||
|
||||
obj/nogui/%.o: %.cpp $(HEADERS)
|
||||
obj/%.o: %.cpp $(HEADERS)
|
||||
g++ -c $(CFLAGS) -o $@ $<
|
||||
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/nogui/%)
|
||||
bitcoind.exe: $(OBJS:obj/%=obj/%)
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
obj/test/test_bitcoin.o: $(wildcard test/*.cpp) $(HEADERS)
|
||||
g++ -c $(CFLAGS) -o $@ test/test_bitcoin.cpp
|
||||
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%))
|
||||
test_bitcoin.exe: obj/test/test_bitcoin.o $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
|
||||
@@ -10,6 +10,7 @@ CXX=llvm-g++
|
||||
DEPSDIR=/opt/local
|
||||
|
||||
INCLUDEPATHS= \
|
||||
-I"$(CURDIR)" \
|
||||
-I"$(DEPSDIR)/include" \
|
||||
-I"$(DEPSDIR)/include/db48"
|
||||
|
||||
@@ -22,6 +23,8 @@ USE_UPNP:=1
|
||||
LIBS= -dead_strip
|
||||
ifdef STATIC
|
||||
# Build STATIC if you are redistributing the bitcoind binary
|
||||
TESTLIBS += \
|
||||
$(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
|
||||
LIBS += \
|
||||
$(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \
|
||||
$(DEPSDIR)/lib/libboost_system-mt.a \
|
||||
@@ -29,8 +32,11 @@ LIBS += \
|
||||
$(DEPSDIR)/lib/libboost_program_options-mt.a \
|
||||
$(DEPSDIR)/lib/libboost_thread-mt.a \
|
||||
$(DEPSDIR)/lib/libssl.a \
|
||||
$(DEPSDIR)/lib/libcrypto.a
|
||||
$(DEPSDIR)/lib/libcrypto.a \
|
||||
-lz
|
||||
else
|
||||
TESTLIBS += \
|
||||
-lboost_unit_test_framework-mt
|
||||
LIBS += \
|
||||
-ldb_cxx-4.8 \
|
||||
-lboost_system-mt \
|
||||
@@ -38,38 +44,25 @@ LIBS += \
|
||||
-lboost_program_options-mt \
|
||||
-lboost_thread-mt \
|
||||
-lssl \
|
||||
-lcrypto
|
||||
-lcrypto \
|
||||
-lz
|
||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||
endif
|
||||
|
||||
DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DUSE_SSL
|
||||
|
||||
DEBUGFLAGS=-g
|
||||
# ppc doesn't work because we don't support big-endian
|
||||
CFLAGS=-mmacosx-version-min=10.5 -arch i386 -O3 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
HEADERS = \
|
||||
base58.h \
|
||||
bignum.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
init.h \
|
||||
irc.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
main.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
protocol.h \
|
||||
bitcoinrpc.h \
|
||||
script.h \
|
||||
serialize.h \
|
||||
strlcpy.h \
|
||||
uint256.h \
|
||||
util.h \
|
||||
wallet.h
|
||||
CFLAGS=-mmacosx-version-min=10.5 -arch i386 -O3 \
|
||||
-Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat-security \
|
||||
$(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
obj/init.o \
|
||||
obj/irc.o \
|
||||
@@ -78,6 +71,7 @@ OBJS= \
|
||||
obj/net.o \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
@@ -91,38 +85,37 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
all: bitcoind
|
||||
|
||||
# auto-generated dependencies:
|
||||
-include obj/nogui/*.P
|
||||
-include obj/test/*.P
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/nogui/%.o: %.cpp
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(CFLAGS) -MMD -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/nogui/%)
|
||||
bitcoind: $(OBJS:obj/%=obj/%)
|
||||
$(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
obj/test/%.o: test/%.cpp
|
||||
$(CXX) -c $(CFLAGS) -MMD -o $@ $<
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj-test/%.o: test/%.cpp
|
||||
$(CXX) -c $(TESTDEFS) $(CFLAGS) -MMD -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: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%))
|
||||
$(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) $(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
|
||||
test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
$(CXX) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) $(TESTLIBS)
|
||||
|
||||
clean:
|
||||
-rm -f bitcoind test_bitcoin
|
||||
-rm -f obj/*.o
|
||||
-rm -f obj/nogui/*.o
|
||||
-rm -f obj/test/*.o
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj/nogui/*.P
|
||||
-rm -f obj/test/*.P
|
||||
-rm -f obj-test/*.P
|
||||
|
||||
@@ -6,8 +6,8 @@ USE_UPNP:=0
|
||||
|
||||
DEFS=-DNOPCH
|
||||
|
||||
DEFS += $(addprefix -I,$(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||
LIBS += $(addprefix -l,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||
DEFS += $(addprefix -I,$(CURDIR) $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
|
||||
LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||
|
||||
LMODE = dynamic
|
||||
LMODE2 = dynamic
|
||||
@@ -16,10 +16,12 @@ ifdef STATIC
|
||||
ifeq (${STATIC}, all)
|
||||
LMODE2 = static
|
||||
endif
|
||||
else
|
||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||
endif
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
LIBS= \
|
||||
LIBS += \
|
||||
-Wl,-B$(LMODE) \
|
||||
-l boost_system$(BOOST_LIB_SUFFIX) \
|
||||
-l boost_filesystem$(BOOST_LIB_SUFFIX) \
|
||||
@@ -83,31 +85,15 @@ LIBS+= \
|
||||
|
||||
DEBUGFLAGS=-g
|
||||
CXXFLAGS=-O2
|
||||
xCXXFLAGS=-pthread -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
|
||||
HEADERS = \
|
||||
base58.h \
|
||||
bignum.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
init.h \
|
||||
irc.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
main.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
protocol.h \
|
||||
bitcoinrpc.h \
|
||||
script.h \
|
||||
serialize.h \
|
||||
strlcpy.h \
|
||||
uint256.h \
|
||||
util.h \
|
||||
wallet.h
|
||||
xCXXFLAGS=-pthread -Wextra -Wno-sign-compare -Wno-char-subscripts -Wno-invalid-offsetof -Wformat -Wformat-security \
|
||||
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
|
||||
|
||||
OBJS= \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
obj/init.o \
|
||||
obj/irc.o \
|
||||
@@ -116,6 +102,7 @@ OBJS= \
|
||||
obj/net.o \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/script.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o
|
||||
@@ -124,34 +111,34 @@ OBJS= \
|
||||
all: bitcoind
|
||||
|
||||
# auto-generated dependencies:
|
||||
-include obj/nogui/*.P
|
||||
-include obj/test/*.P
|
||||
-include obj/*.P
|
||||
-include obj-test/*.P
|
||||
|
||||
obj/nogui/%.o: %.cpp
|
||||
obj/%.o: %.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -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/nogui/%)
|
||||
bitcoind: $(OBJS:obj/%=obj/%)
|
||||
$(CXX) $(xCXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
obj/test/%.o: test/%.cpp
|
||||
$(CXX) -c $(xCXXFLAGS) -MMD -o $@ $<
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj-test/%.o: test/%.cpp
|
||||
$(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -MMD -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: obj/test/test_bitcoin.o $(filter-out obj/nogui/init.o,$(OBJS:obj/%=obj/nogui/%))
|
||||
$(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-Bstatic -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
|
||||
test_bitcoin: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
$(CXX) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ -Wl,-B$(LMODE) -lboost_unit_test_framework $(LDFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
-rm -f bitcoind test_bitcoin
|
||||
-rm -f obj/*.o
|
||||
-rm -f obj/nogui/*.o
|
||||
-rm -f obj/test/*.o
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f obj/*.P
|
||||
-rm -f obj/nogui/*.P
|
||||
-rm -f obj/test/*.P
|
||||
-rm -f obj-test/*.P
|
||||
|
||||
147
src/makefile.vc
147
src/makefile.vc
@@ -1,147 +0,0 @@
|
||||
# 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.
|
||||
|
||||
|
||||
INCLUDEPATHS= \
|
||||
/I"/boost" \
|
||||
/I"/db/build_windows" \
|
||||
/I"/openssl/include" \
|
||||
/I"/miniupnpc"
|
||||
|
||||
LIBPATHS= \
|
||||
/LIBPATH:"/boost/stage/lib" \
|
||||
/LIBPATH:"/db/build_windows/Release" \
|
||||
/LIBPATH:"/openssl/lib" \
|
||||
/LIBPATH:"/miniupnpc/msvc/Release" \
|
||||
/NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib \
|
||||
/NODEFAULTLIB:libcd.lib /NODEFAULTLIB:libcmtd.lib \
|
||||
/NODEFAULTLIB:msvcrtd.lib
|
||||
|
||||
USE_UPNP=0
|
||||
|
||||
DEFS=/DWIN32 /D_WINDOWS /DNOPCH /DNOMINMAX
|
||||
|
||||
LIBS= \
|
||||
libboost_system-vc100-mt.lib \
|
||||
libboost_filesystem-vc100-mt.lib \
|
||||
libboost_program_options-vc100-mt.lib \
|
||||
libboost_thread-vc100-mt.lib \
|
||||
libdb47s.lib \
|
||||
libeay32.lib
|
||||
|
||||
!IFDEF USE_UPNP
|
||||
LIBS=$(LIBS) miniupnpc.lib
|
||||
DEFS=$(DEFS) /DUSE_UPNP=$(USE_UPNP)
|
||||
!ENDIF
|
||||
|
||||
LIBS=$(LIBS) \
|
||||
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib iphlpapi.lib
|
||||
|
||||
DEBUGFLAGS=/Os
|
||||
CFLAGS=/MD /c /nologo /EHsc /GR /Zm300 $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
|
||||
HEADERS = \
|
||||
base58.h \
|
||||
bignum.h \
|
||||
crypter.h \
|
||||
db.h \
|
||||
headers.h \
|
||||
init.h \
|
||||
irc.h \
|
||||
key.h \
|
||||
keystore.h \
|
||||
main.h \
|
||||
net.h \
|
||||
noui.h \
|
||||
protocol.h \
|
||||
bitcoinrpc.h \
|
||||
script.h \
|
||||
serialize.h \
|
||||
strlcpy.h \
|
||||
ui.h \
|
||||
uibase.h \
|
||||
uint256.h \
|
||||
util.h \
|
||||
wallet.h
|
||||
|
||||
OBJS= \
|
||||
obj\crypter.o \
|
||||
obj\db.o \
|
||||
obj\init.o \
|
||||
obj\irc.o \
|
||||
obj\keystore.o \
|
||||
obj\main.o \
|
||||
obj\net.o \
|
||||
obj\rpc.o \
|
||||
obj\protocol.o \
|
||||
obj\script.o \
|
||||
obj\util.o \
|
||||
obj\wallet.o
|
||||
|
||||
RC=../share
|
||||
|
||||
|
||||
all: bitcoind.exe
|
||||
|
||||
|
||||
.cpp{obj}.obj:
|
||||
cl $(CFLAGS) /DGUI /Fo$@ %s
|
||||
|
||||
obj\util.obj: $(HEADERS)
|
||||
|
||||
obj\script.obj: $(HEADERS)
|
||||
|
||||
obj\db.obj: $(HEADERS)
|
||||
|
||||
obj\net.obj: $(HEADERS)
|
||||
|
||||
obj\irc.obj: $(HEADERS)
|
||||
|
||||
obj\keystore.obj: $(HEADERS)
|
||||
|
||||
obj\main.obj: $(HEADERS)
|
||||
|
||||
obj\wallet.obj: $(HEADERS)
|
||||
|
||||
obj\rpc.obj: $(HEADERS)
|
||||
|
||||
obj\init.obj: $(HEADERS)
|
||||
|
||||
obj\crypter.obj: $(HEADERS)
|
||||
|
||||
obj\ui.obj: $(HEADERS)
|
||||
|
||||
obj\uibase.obj: $(HEADERS)
|
||||
|
||||
.cpp{obj\nogui}.obj:
|
||||
cl $(CFLAGS) /Fo$@ %s
|
||||
|
||||
obj\nogui\util.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\script.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\db.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\net.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\irc.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\keystore.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\main.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\wallet.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\rpc.obj: $(HEADERS)
|
||||
|
||||
obj\nogui\init.obj: $(HEADERS)
|
||||
|
||||
bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\ui.res
|
||||
link /nologo /OUT:$@ $(LIBPATHS) $** $(LIBS)
|
||||
|
||||
clean:
|
||||
-del /Q obj\*
|
||||
-del /Q obj\nogui\*
|
||||
-del /Q *.ilk
|
||||
-del /Q *.pdb
|
||||
-del /Q bitcoind.exe
|
||||
64
src/mruset.h
Normal file
64
src/mruset.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
#ifndef BITCOIN_MRUSET_H
|
||||
#define BITCOIN_MRUSET_H
|
||||
|
||||
#include <set>
|
||||
#include <deque>
|
||||
|
||||
/** STL-like set container that only keeps the most recent N elements. */
|
||||
template <typename T> class mruset
|
||||
{
|
||||
public:
|
||||
typedef T key_type;
|
||||
typedef T value_type;
|
||||
typedef typename std::set<T>::iterator iterator;
|
||||
typedef typename std::set<T>::const_iterator const_iterator;
|
||||
typedef typename std::set<T>::size_type size_type;
|
||||
|
||||
protected:
|
||||
std::set<T> set;
|
||||
std::deque<T> queue;
|
||||
size_type nMaxSize;
|
||||
|
||||
public:
|
||||
mruset(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; }
|
||||
iterator begin() const { return set.begin(); }
|
||||
iterator end() const { return set.end(); }
|
||||
size_type size() const { return set.size(); }
|
||||
bool empty() const { return set.empty(); }
|
||||
iterator find(const key_type& k) const { return set.find(k); }
|
||||
size_type count(const key_type& k) const { return set.count(k); }
|
||||
bool inline friend operator==(const mruset<T>& a, const mruset<T>& b) { return a.set == b.set; }
|
||||
bool inline friend operator==(const mruset<T>& a, const std::set<T>& b) { return a.set == b; }
|
||||
bool inline friend operator<(const mruset<T>& a, const mruset<T>& b) { return a.set < b.set; }
|
||||
std::pair<iterator, bool> insert(const key_type& x)
|
||||
{
|
||||
std::pair<iterator, bool> ret = set.insert(x);
|
||||
if (ret.second)
|
||||
{
|
||||
if (nMaxSize && queue.size() == nMaxSize)
|
||||
{
|
||||
set.erase(queue.front());
|
||||
queue.pop_front();
|
||||
}
|
||||
queue.push_back(x);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
size_type max_size() const { return nMaxSize; }
|
||||
size_type max_size(size_type s)
|
||||
{
|
||||
if (s)
|
||||
while (queue.size() >= s)
|
||||
{
|
||||
set.erase(queue.front());
|
||||
queue.pop_front();
|
||||
}
|
||||
nMaxSize = s;
|
||||
return nMaxSize;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
1053
src/net.cpp
1053
src/net.cpp
File diff suppressed because it is too large
Load Diff
97
src/net.h
97
src/net.h
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NET_H
|
||||
@@ -14,14 +14,16 @@
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "mruset.h"
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "addrman.h"
|
||||
|
||||
class CAddrDB;
|
||||
class CRequestTracker;
|
||||
class CNode;
|
||||
class CBlockIndex;
|
||||
extern int nBestHeight;
|
||||
extern int nConnectTimeout;
|
||||
|
||||
|
||||
|
||||
@@ -29,18 +31,15 @@ inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer"
|
||||
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
|
||||
static const unsigned int PUBLISH_HOPS = 5;
|
||||
|
||||
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
|
||||
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool GetMyExternalIP(unsigned int& ipRet);
|
||||
bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
|
||||
void AddressCurrentlyConnected(const CAddress& addr);
|
||||
CNode* FindNode(unsigned int ip);
|
||||
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 AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
|
||||
bool AnySubscribed(unsigned int nChannel);
|
||||
void MapPort(bool fMapPort);
|
||||
void DNSAddressSeed();
|
||||
bool BindListenPort(std::string& strError=REF(std::string()));
|
||||
void StartNode(void* parg);
|
||||
bool StopNode();
|
||||
@@ -70,34 +69,43 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** Thread types */
|
||||
enum threadId
|
||||
{
|
||||
THREAD_SOCKETHANDLER,
|
||||
THREAD_OPENCONNECTIONS,
|
||||
THREAD_MESSAGEHANDLER,
|
||||
THREAD_MINER,
|
||||
THREAD_RPCSERVER,
|
||||
THREAD_UPNP,
|
||||
THREAD_DNSSEED,
|
||||
THREAD_ADDEDCONNECTIONS,
|
||||
THREAD_DUMPADDRESS,
|
||||
|
||||
|
||||
THREAD_MAX
|
||||
};
|
||||
|
||||
extern bool fClient;
|
||||
extern bool fAllowDNS;
|
||||
extern uint64 nLocalServices;
|
||||
extern CAddress addrLocalHost;
|
||||
extern uint64 nLocalHostNonce;
|
||||
extern boost::array<int, 10> vnThreadsRunning;
|
||||
extern boost::array<int, THREAD_MAX> vnThreadsRunning;
|
||||
extern CAddrMan addrman;
|
||||
|
||||
extern std::vector<CNode*> vNodes;
|
||||
extern CCriticalSection cs_vNodes;
|
||||
extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
|
||||
extern CCriticalSection cs_mapAddresses;
|
||||
extern std::map<CInv, CDataStream> mapRelay;
|
||||
extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
|
||||
extern CCriticalSection cs_mapRelay;
|
||||
extern std::map<CInv, int64> mapAlreadyAskedFor;
|
||||
|
||||
// Settings
|
||||
extern int fUseProxy;
|
||||
extern CAddress addrProxy;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Information about a peer */
|
||||
class CNode
|
||||
{
|
||||
public:
|
||||
@@ -127,7 +135,7 @@ protected:
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
// Key is ip address, value is banned-until-time
|
||||
static std::map<unsigned int, int64> setBanned;
|
||||
static std::map<CNetAddr, int64> setBanned;
|
||||
static CCriticalSection cs_setBanned;
|
||||
int nMisbehavior;
|
||||
|
||||
@@ -147,7 +155,7 @@ public:
|
||||
std::set<uint256> setKnown;
|
||||
|
||||
// inventory based relay
|
||||
std::set<CInv> setInventoryKnown;
|
||||
mruset<CInv> setInventoryKnown;
|
||||
std::vector<CInv> vInventoryToSend;
|
||||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64, CInv> mapAskFor;
|
||||
@@ -160,15 +168,9 @@ public:
|
||||
nServices = 0;
|
||||
hSocket = hSocketIn;
|
||||
vSend.SetType(SER_NETWORK);
|
||||
vSend.SetVersion(0);
|
||||
vRecv.SetType(SER_NETWORK);
|
||||
vRecv.SetVersion(0);
|
||||
// Version 0.2 obsoletes 20 Feb 2012
|
||||
if (GetTime() > 1329696000)
|
||||
{
|
||||
vSend.SetVersion(209);
|
||||
vRecv.SetVersion(209);
|
||||
}
|
||||
vSend.SetVersion(209);
|
||||
vRecv.SetVersion(209);
|
||||
nLastSend = 0;
|
||||
nLastRecv = 0;
|
||||
nLastSendEmpty = GetTime();
|
||||
@@ -192,6 +194,7 @@ public:
|
||||
fGetAddr = false;
|
||||
vfSubscribe.assign(256, false);
|
||||
nMisbehavior = 0;
|
||||
setInventoryKnown.max_size(SendBufferSize() / 1000);
|
||||
|
||||
// Be shy and don't send version until we hear
|
||||
if (!fInbound)
|
||||
@@ -272,7 +275,9 @@ public:
|
||||
// Make sure not to reuse time indexes to keep things in the same order
|
||||
int64 nNow = (GetTime() - 1) * 1000000;
|
||||
static int64 nLastTime;
|
||||
nLastTime = nNow = std::max(nNow, ++nLastTime);
|
||||
++nLastTime;
|
||||
nNow = std::max(nNow, nLastTime);
|
||||
nLastTime = nNow;
|
||||
|
||||
// Each retry is 2 minutes after the last
|
||||
nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
|
||||
@@ -283,7 +288,7 @@ public:
|
||||
|
||||
void BeginMessage(const char* pszCommand)
|
||||
{
|
||||
cs_vSend.Enter("cs_vSend", __FILE__, __LINE__);
|
||||
ENTER_CRITICAL_SECTION(cs_vSend);
|
||||
if (nHeaderStart != -1)
|
||||
AbortMessage();
|
||||
nHeaderStart = vSend.size();
|
||||
@@ -302,7 +307,7 @@ public:
|
||||
vSend.resize(nHeaderStart);
|
||||
nHeaderStart = -1;
|
||||
nMessageStart = -1;
|
||||
cs_vSend.Leave();
|
||||
LEAVE_CRITICAL_SECTION(cs_vSend);
|
||||
|
||||
if (fDebug)
|
||||
printf("(aborted)\n");
|
||||
@@ -325,14 +330,11 @@ public:
|
||||
memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
|
||||
|
||||
// Set the checksum
|
||||
if (vSend.GetVersion() >= 209)
|
||||
{
|
||||
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));
|
||||
}
|
||||
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));
|
||||
|
||||
if (fDebug) {
|
||||
printf("(%d bytes)\n", nSize);
|
||||
@@ -340,7 +342,7 @@ public:
|
||||
|
||||
nHeaderStart = -1;
|
||||
nMessageStart = -1;
|
||||
cs_vSend.Leave();
|
||||
LEAVE_CRITICAL_SECTION(cs_vSend);
|
||||
}
|
||||
|
||||
void EndMessageAbortIfEmpty()
|
||||
@@ -356,18 +358,7 @@ public:
|
||||
|
||||
|
||||
|
||||
void PushVersion()
|
||||
{
|
||||
/// when NTP implemented, change to just nTime = GetAdjustedTime()
|
||||
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
|
||||
CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
|
||||
CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);
|
||||
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
|
||||
PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
|
||||
nLocalHostNonce, std::string(pszSubVer), nBestHeight);
|
||||
}
|
||||
|
||||
|
||||
void PushVersion();
|
||||
|
||||
|
||||
void PushMessage(const char* pszCommand)
|
||||
@@ -592,7 +583,7 @@ public:
|
||||
// between nodes running old code and nodes running
|
||||
// new code.
|
||||
static void ClearBanned(); // needed for unit testing
|
||||
static bool IsBanned(unsigned int ip);
|
||||
static bool IsBanned(CNetAddr ip);
|
||||
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
|
||||
};
|
||||
|
||||
|
||||
738
src/netbase.cpp
Normal file
738
src/netbase.cpp
Normal file
@@ -0,0 +1,738 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "strlcpy.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Settings
|
||||
int fUseProxy = false;
|
||||
CService addrProxy("127.0.0.1",9050);
|
||||
int nConnectTimeout = 5000;
|
||||
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
vIP.clear();
|
||||
struct addrinfo aiHint;
|
||||
memset(&aiHint, 0, sizeof(struct addrinfo));
|
||||
|
||||
aiHint.ai_socktype = SOCK_STREAM;
|
||||
aiHint.ai_protocol = IPPROTO_TCP;
|
||||
#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
|
||||
#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
|
||||
#endif
|
||||
struct addrinfo *aiRes = NULL;
|
||||
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
|
||||
if (nErr)
|
||||
return false;
|
||||
|
||||
struct addrinfo *aiTrav = aiRes;
|
||||
while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
|
||||
{
|
||||
if (aiTrav->ai_family == AF_INET)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
|
||||
vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if (aiTrav->ai_family == AF_INET6)
|
||||
{
|
||||
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
|
||||
vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
aiTrav = aiTrav->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(aiRes);
|
||||
|
||||
return (vIP.size() > 0);
|
||||
}
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions, bool fAllowLookup)
|
||||
{
|
||||
if (pszName[0] == 0)
|
||||
return false;
|
||||
char psz[256];
|
||||
char *pszHost = psz;
|
||||
strlcpy(psz, pszName, sizeof(psz));
|
||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
||||
{
|
||||
pszHost = psz+1;
|
||||
psz[strlen(psz)-1] = 0;
|
||||
}
|
||||
|
||||
return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
}
|
||||
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions)
|
||||
{
|
||||
return LookupHost(pszName, vIP, nMaxSolutions, false);
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, int nMaxSolutions)
|
||||
{
|
||||
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::vector<CNetAddr> vIP;
|
||||
bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
||||
if (!fRet)
|
||||
return false;
|
||||
vAddr.resize(vIP.size());
|
||||
for (int i = 0; i < vIP.size(); i++)
|
||||
vAddr[i] = CService(vIP[i], port);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
|
||||
{
|
||||
std::vector<CService> vService;
|
||||
bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
|
||||
if (!fRet)
|
||||
return false;
|
||||
addr = vService[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
|
||||
{
|
||||
return Lookup(pszName, addr, portDefault, false);
|
||||
}
|
||||
|
||||
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||
{
|
||||
hSocketRet = INVALID_SOCKET;
|
||||
|
||||
SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (hSocket == INVALID_SOCKET)
|
||||
return false;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
int set = 1;
|
||||
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)
|
||||
#else
|
||||
int fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
{
|
||||
// WSAEINVAL is here because some legacy version of winsock uses it
|
||||
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = nTimeout / 1000;
|
||||
timeout.tv_usec = (nTimeout % 1000) * 1000;
|
||||
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(hSocket, &fdset);
|
||||
int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
|
||||
if (nRet == 0)
|
||||
{
|
||||
printf("connection timeout\n");
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet == SOCKET_ERROR)
|
||||
{
|
||||
printf("select() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
socklen_t nRetSize = sizeof(nRet);
|
||||
#ifdef WIN32
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
|
||||
#else
|
||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
if (nRet != 0)
|
||||
{
|
||||
printf("connect() failed after select(): %s\n",strerror(nRet));
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef WIN32
|
||||
else if (WSAGetLastError() != WSAEISCONN)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
printf("connect() failed: %i\n",WSAGetLastError());
|
||||
closesocket(hSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// this isn't even strictly necessary
|
||||
// CNode::ConnectNode immediately turns the socket back to non-blocking
|
||||
// but we'll turn it back to blocking just in case
|
||||
#ifdef WIN32
|
||||
fNonblock = 0;
|
||||
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
|
||||
#else
|
||||
fFlags = fcntl(hSocket, F_GETFL, 0);
|
||||
if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
closesocket(hSocket);
|
||||
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);
|
||||
|
||||
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("proxy connected %s\n", addrDest.ToString().c_str());
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetAddr::Init()
|
||||
{
|
||||
memset(ip, 0, 16);
|
||||
}
|
||||
|
||||
void CNetAddr::SetIP(const CNetAddr& ipIn)
|
||||
{
|
||||
memcpy(ip, ipIn.ip, sizeof(ip));
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
|
||||
{
|
||||
memcpy(ip, pchIPv4, 12);
|
||||
memcpy(ip+12, &ipv4Addr, 4);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
|
||||
{
|
||||
memcpy(ip, &ipv6Addr, 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(pszIp, vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
std::vector<CNetAddr> vIP;
|
||||
if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
|
||||
*this = vIP[0];
|
||||
}
|
||||
|
||||
int CNetAddr::GetByte(int n) const
|
||||
{
|
||||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (
|
||||
GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3849() const
|
||||
{
|
||||
return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC3964() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6052() const
|
||||
{
|
||||
static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4380() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4862() const
|
||||
{
|
||||
static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
|
||||
return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4193() const
|
||||
{
|
||||
return ((GetByte(15) & 0xFE) == 0xFC);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC6145() const
|
||||
{
|
||||
static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
|
||||
return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRFC4843() const
|
||||
{
|
||||
return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsLocal() const
|
||||
{
|
||||
// IPv4 loopback
|
||||
if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
|
||||
return true;
|
||||
|
||||
// IPv6 loopback (::1/128)
|
||||
static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
|
||||
if (memcmp(ip, pchLocal, 16) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsMulticast() const
|
||||
{
|
||||
return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
|
||||
|| (GetByte(15) == 0xFF);
|
||||
}
|
||||
|
||||
bool CNetAddr::IsValid() const
|
||||
{
|
||||
// Clean up 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...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
// unspecified IPv6 address (::/128)
|
||||
unsigned char ipNone[16] = {};
|
||||
if (memcmp(ip, ipNone, 16) == 0)
|
||||
return false;
|
||||
|
||||
// documentation IPv6 address
|
||||
if (IsRFC3849())
|
||||
return false;
|
||||
|
||||
if (IsIPv4())
|
||||
{
|
||||
// INADDR_NONE
|
||||
uint32_t ipNone = INADDR_NONE;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
|
||||
// 0
|
||||
ipNone = 0;
|
||||
if (memcmp(ip+12, &ipNone, 4) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsRoutable() const
|
||||
{
|
||||
return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || IsRFC4193() || IsRFC4843() || IsLocal());
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToStringIP() const
|
||||
{
|
||||
if (IsIPv4())
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
else
|
||||
return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
||||
GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
|
||||
GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
|
||||
GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
|
||||
GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
|
||||
}
|
||||
|
||||
std::string CNetAddr::ToString() const
|
||||
{
|
||||
return ToStringIP();
|
||||
}
|
||||
|
||||
bool operator==(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) != 0);
|
||||
}
|
||||
|
||||
bool operator<(const CNetAddr& a, const CNetAddr& b)
|
||||
{
|
||||
return (memcmp(a.ip, b.ip, 16) < 0);
|
||||
}
|
||||
|
||||
bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
|
||||
{
|
||||
if (!IsIPv4())
|
||||
return false;
|
||||
memcpy(pipv4Addr, ip+12, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
||||
{
|
||||
memcpy(pipv6Addr, ip, 16);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// get canonical identifier of an address' group
|
||||
// no two connections will be attempted to addresses with the same group
|
||||
std::vector<unsigned char> CNetAddr::GetGroup() const
|
||||
{
|
||||
std::vector<unsigned char> vchRet;
|
||||
int nClass = 0; // 0=IPv6, 1=IPv4, 254=local, 255=unroutable
|
||||
int nStartByte = 0;
|
||||
int nBits = 16;
|
||||
|
||||
// all local addresses belong to the same group
|
||||
if (IsLocal())
|
||||
{
|
||||
nClass = 254;
|
||||
nBits = 0;
|
||||
}
|
||||
|
||||
// all unroutable addresses belong to the same group
|
||||
if (!IsRoutable())
|
||||
{
|
||||
nClass = 255;
|
||||
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;
|
||||
nStartByte = 12;
|
||||
}
|
||||
// for 6to4 tunneled addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC3964())
|
||||
{
|
||||
nClass = 1;
|
||||
nStartByte = 2;
|
||||
}
|
||||
// for Teredo-tunneled IPv6 addresses, use the encapsulated IPv4 address
|
||||
else if (IsRFC4380())
|
||||
{
|
||||
vchRet.push_back(1);
|
||||
vchRet.push_back(GetByte(3) ^ 0xFF);
|
||||
vchRet.push_back(GetByte(2) ^ 0xFF);
|
||||
return vchRet;
|
||||
}
|
||||
// for he.net, use /36 groups
|
||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
||||
nBits = 36;
|
||||
// for the rest of the IPv6 network, use /32 groups
|
||||
else
|
||||
nBits = 32;
|
||||
|
||||
vchRet.push_back(nClass);
|
||||
while (nBits >= 8)
|
||||
{
|
||||
vchRet.push_back(GetByte(15 - nStartByte));
|
||||
nStartByte++;
|
||||
nBits -= 8;
|
||||
}
|
||||
if (nBits > 0)
|
||||
vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1));
|
||||
|
||||
return vchRet;
|
||||
}
|
||||
|
||||
int64 CNetAddr::GetHash() const
|
||||
{
|
||||
uint256 hash = Hash(&ip[0], &ip[16]);
|
||||
int64 nRet;
|
||||
memcpy(&nRet, &hash, sizeof(nRet));
|
||||
return nRet;
|
||||
}
|
||||
|
||||
void CNetAddr::print() const
|
||||
{
|
||||
printf("CNetAddr(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CService::Init()
|
||||
{
|
||||
port = 0;
|
||||
}
|
||||
|
||||
CService::CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
|
||||
{
|
||||
assert(addr.sin_family == AF_INET);
|
||||
}
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
|
||||
{
|
||||
assert(addr.sin6_family == AF_INET6);
|
||||
}
|
||||
#endif
|
||||
|
||||
CService::CService(const char *pszIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(pszIpPort, ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIpPort, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
|
||||
{
|
||||
Init();
|
||||
CService ip;
|
||||
if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
|
||||
*this = ip;
|
||||
}
|
||||
|
||||
unsigned short CService::GetPort() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
bool operator==(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
|
||||
}
|
||||
|
||||
bool operator!=(const CService& a, const CService& b)
|
||||
{
|
||||
return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<unsigned char> CService::GetKey() const
|
||||
{
|
||||
std::vector<unsigned char> vKey;
|
||||
vKey.resize(18);
|
||||
memcpy(&vKey[0], ip, 16);
|
||||
vKey[16] = port / 0x100;
|
||||
vKey[17] = port & 0x0FF;
|
||||
return vKey;
|
||||
}
|
||||
|
||||
std::string CService::ToStringPort() const
|
||||
{
|
||||
return strprintf(":%i", port);
|
||||
}
|
||||
|
||||
std::string CService::ToStringIPPort() const
|
||||
{
|
||||
return ToStringIP() + ToStringPort();
|
||||
}
|
||||
|
||||
std::string CService::ToString() const
|
||||
{
|
||||
return ToStringIPPort();
|
||||
}
|
||||
|
||||
void CService::print() const
|
||||
{
|
||||
printf("CService(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
void CService::SetPort(unsigned short portIn)
|
||||
{
|
||||
port = portIn;
|
||||
}
|
||||
140
src/netbase.h
Normal file
140
src/netbase.h
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NETBASE_H
|
||||
#define BITCOIN_NETBASE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <winsock2.h>
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#ifdef BSD
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "serialize.h"
|
||||
#include "compat.h"
|
||||
|
||||
extern int nConnectTimeout;
|
||||
|
||||
|
||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
||||
class CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned char ip[16]; // in network byte order
|
||||
|
||||
public:
|
||||
CNetAddr();
|
||||
CNetAddr(const struct in_addr& ipv4Addr);
|
||||
explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
|
||||
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetIP(const CNetAddr& ip);
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
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 IsRFC4193() const; // IPv6 unique local (FC00::/15)
|
||||
bool IsRFC4380() const; // IPv6 Teredo tunneling (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 IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
bool IsMulticast() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringIP() const;
|
||||
int GetByte(int n) const;
|
||||
int64 GetHash() const;
|
||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||
std::vector<unsigned char> GetGroup() const;
|
||||
void print() const;
|
||||
|
||||
#ifdef USE_IPV6
|
||||
CNetAddr(const struct in6_addr& pipv6Addr);
|
||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||
#endif
|
||||
|
||||
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
|
||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(FLATDATA(ip));
|
||||
)
|
||||
};
|
||||
|
||||
/** A combnation of a network address (CNetAddr) and a (TCP) port */
|
||||
class CService : public CNetAddr
|
||||
{
|
||||
protected:
|
||||
unsigned short port; // host order
|
||||
|
||||
public:
|
||||
CService();
|
||||
CService(const CNetAddr& ip, unsigned short port);
|
||||
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
||||
CService(const struct sockaddr_in& addr);
|
||||
explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
|
||||
explicit CService(const char *pszIpPort, bool fAllowLookup = false);
|
||||
explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
|
||||
explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
|
||||
void Init();
|
||||
void SetPort(unsigned short portIn);
|
||||
unsigned short GetPort() const;
|
||||
bool GetSockAddr(struct sockaddr_in* paddr) const;
|
||||
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);
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
std::string ToString() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToStringIPPort() const;
|
||||
void print() const;
|
||||
|
||||
#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
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CService* pthis = const_cast<CService*>(this);
|
||||
READWRITE(FLATDATA(ip));
|
||||
unsigned short portN = htons(port);
|
||||
READWRITE(portN);
|
||||
if (fRead)
|
||||
pthis->port = ntohs(portN);
|
||||
)
|
||||
};
|
||||
|
||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
|
||||
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);
|
||||
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
|
||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0);
|
||||
bool 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;
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef BITCOIN_NOUI_H
|
||||
|
||||
2
src/obj-test/.gitignore
vendored
Normal file
2
src/obj-test/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
176
src/protocol.cpp
176
src/protocol.cpp
@@ -1,20 +1,16 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "protocol.h"
|
||||
#include "util.h"
|
||||
#include "netbase.h"
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
// Prototypes from net.h, but that header (currently) stinks, can't #include it without breaking things
|
||||
bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
|
||||
|
||||
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
static const char* ppszTypeName[] =
|
||||
{
|
||||
"ERROR",
|
||||
@@ -77,185 +73,26 @@ bool CMessageHeader::IsValid() const
|
||||
return true;
|
||||
}
|
||||
|
||||
CAddress::CAddress()
|
||||
|
||||
|
||||
CAddress::CAddress() : CService()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
CAddress::CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn)
|
||||
CAddress::CAddress(CService ipIn, uint64 nServicesIn) : CService(ipIn)
|
||||
{
|
||||
Init();
|
||||
ip = ipIn;
|
||||
port = htons(portIn == 0 ? GetDefaultPort() : portIn);
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
CAddress::CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
ip = sockaddr.sin_addr.s_addr;
|
||||
port = sockaddr.sin_port;
|
||||
nServices = nServicesIn;
|
||||
}
|
||||
|
||||
CAddress::CAddress(const char* pszIn, int portIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(pszIn, *this, nServicesIn, fNameLookup, portIn);
|
||||
}
|
||||
|
||||
CAddress::CAddress(const char* pszIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(pszIn, *this, nServicesIn, fNameLookup, 0, true);
|
||||
}
|
||||
|
||||
CAddress::CAddress(std::string strIn, int portIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, portIn);
|
||||
}
|
||||
|
||||
CAddress::CAddress(std::string strIn, bool fNameLookup, uint64 nServicesIn)
|
||||
{
|
||||
Init();
|
||||
Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, 0, true);
|
||||
}
|
||||
|
||||
void CAddress::Init()
|
||||
{
|
||||
nServices = NODE_NETWORK;
|
||||
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
|
||||
ip = INADDR_NONE;
|
||||
port = htons(GetDefaultPort());
|
||||
nTime = 100000000;
|
||||
nLastTry = 0;
|
||||
}
|
||||
|
||||
bool operator==(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
|
||||
a.ip == b.ip &&
|
||||
a.port == b.port);
|
||||
}
|
||||
|
||||
bool operator!=(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
bool operator<(const CAddress& a, const CAddress& b)
|
||||
{
|
||||
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
|
||||
if (ret < 0)
|
||||
return true;
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (ntohl(a.ip) < ntohl(b.ip))
|
||||
return true;
|
||||
else if (a.ip == b.ip)
|
||||
return ntohs(a.port) < ntohs(b.port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CAddress::GetKey() const
|
||||
{
|
||||
CDataStream ss;
|
||||
ss.reserve(18);
|
||||
ss << FLATDATA(pchReserved) << ip << port;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
return std::vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
|
||||
#else
|
||||
return std::vector<unsigned char>(ss.begin(), ss.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr_in CAddress::GetSockAddr() const
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_addr.s_addr = ip;
|
||||
sockaddr.sin_port = port;
|
||||
return sockaddr;
|
||||
}
|
||||
|
||||
bool CAddress::IsIPv4() const
|
||||
{
|
||||
return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
}
|
||||
|
||||
bool CAddress::IsRFC1918() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 10 ||
|
||||
(GetByte(3) == 192 && GetByte(2) == 168) ||
|
||||
(GetByte(3) == 172 &&
|
||||
(GetByte(2) >= 16 && GetByte(2) <= 31)));
|
||||
}
|
||||
|
||||
bool CAddress::IsRFC3927() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
|
||||
}
|
||||
|
||||
bool CAddress::IsLocal() const
|
||||
{
|
||||
return IsIPv4() && (GetByte(3) == 127 ||
|
||||
GetByte(3) == 0);
|
||||
}
|
||||
|
||||
bool CAddress::IsRoutable() const
|
||||
{
|
||||
return IsValid() &&
|
||||
!(IsRFC1918() || IsRFC3927() || IsLocal());
|
||||
}
|
||||
|
||||
bool CAddress::IsValid() const
|
||||
{
|
||||
// Clean up 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...
|
||||
// so if the first length field is garbled, it reads the second batch
|
||||
// of addr misaligned by 3 bytes.
|
||||
if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
|
||||
return false;
|
||||
|
||||
return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
|
||||
}
|
||||
|
||||
unsigned char CAddress::GetByte(int n) const
|
||||
{
|
||||
return ((unsigned char*)&ip)[3-n];
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringIPPort() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringIP() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
|
||||
}
|
||||
|
||||
std::string CAddress::ToStringPort() const
|
||||
{
|
||||
return strprintf("%u", ntohs(port));
|
||||
}
|
||||
|
||||
std::string CAddress::ToString() const
|
||||
{
|
||||
return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
|
||||
}
|
||||
|
||||
void CAddress::print() const
|
||||
{
|
||||
printf("CAddress(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
CInv::CInv()
|
||||
{
|
||||
type = 0;
|
||||
@@ -310,3 +147,4 @@ void CInv::print() const
|
||||
{
|
||||
printf("CInv(%s)\n", ToString().c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2011 The Bitcoin developers
|
||||
// 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.
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define __INCLUDED_PROTOCOL_H__
|
||||
|
||||
#include "serialize.h"
|
||||
#include "netbase.h"
|
||||
#include "util.h"
|
||||
#include <string>
|
||||
#include "uint256.h"
|
||||
|
||||
@@ -20,15 +22,15 @@ static inline unsigned short GetDefaultPort(const bool testnet = fTestNet)
|
||||
return testnet ? 18333 : 8333;
|
||||
}
|
||||
|
||||
//
|
||||
// Message header
|
||||
// (4) message start
|
||||
// (12) command
|
||||
// (4) size
|
||||
// (4) checksum
|
||||
|
||||
extern unsigned char pchMessageStart[4];
|
||||
|
||||
/** Message header.
|
||||
* (4) message start.
|
||||
* (12) command.
|
||||
* (4) size.
|
||||
* (4) checksum.
|
||||
*/
|
||||
class CMessageHeader
|
||||
{
|
||||
public:
|
||||
@@ -43,7 +45,6 @@ class CMessageHeader
|
||||
READWRITE(FLATDATA(pchMessageStart));
|
||||
READWRITE(FLATDATA(pchCommand));
|
||||
READWRITE(nMessageSize);
|
||||
if (nVersion >= 209)
|
||||
READWRITE(nChecksum);
|
||||
)
|
||||
|
||||
@@ -56,71 +57,49 @@ class CMessageHeader
|
||||
unsigned int nChecksum;
|
||||
};
|
||||
|
||||
/** nServices flags */
|
||||
enum
|
||||
{
|
||||
NODE_NETWORK = (1 << 0),
|
||||
};
|
||||
|
||||
class CAddress
|
||||
/** A CService with information about it as peer */
|
||||
class CAddress : public CService
|
||||
{
|
||||
public:
|
||||
CAddress();
|
||||
CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const char* pszIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(const char* pszIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(std::string strIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(std::string strIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK);
|
||||
explicit CAddress(CService ipIn, uint64 nServicesIn=NODE_NETWORK);
|
||||
|
||||
void Init();
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
CAddress* pthis = const_cast<CAddress*>(this);
|
||||
CService* pip = (CService*)pthis;
|
||||
if (fRead)
|
||||
const_cast<CAddress*>(this)->Init();
|
||||
pthis->Init();
|
||||
if (nType & SER_DISK)
|
||||
READWRITE(nVersion);
|
||||
if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
|
||||
READWRITE(nTime);
|
||||
READWRITE(nServices);
|
||||
READWRITE(FLATDATA(pchReserved)); // for IPv6
|
||||
READWRITE(ip);
|
||||
READWRITE(port);
|
||||
READWRITE(*pip);
|
||||
)
|
||||
|
||||
friend bool operator==(const CAddress& a, const CAddress& b);
|
||||
friend bool operator!=(const CAddress& a, const CAddress& b);
|
||||
friend bool operator<(const CAddress& a, const CAddress& b);
|
||||
|
||||
std::vector<unsigned char> GetKey() const;
|
||||
struct sockaddr_in GetSockAddr() const;
|
||||
bool IsIPv4() const;
|
||||
bool IsRFC1918() const;
|
||||
bool IsRFC3927() const;
|
||||
bool IsLocal() const;
|
||||
bool IsRoutable() const;
|
||||
bool IsValid() const;
|
||||
unsigned char GetByte(int n) const;
|
||||
std::string ToStringIPPort() const;
|
||||
std::string ToStringIP() const;
|
||||
std::string ToStringPort() const;
|
||||
std::string ToString() const;
|
||||
void print() const;
|
||||
|
||||
// TODO: make private (improves encapsulation)
|
||||
public:
|
||||
uint64 nServices;
|
||||
unsigned char pchReserved[12];
|
||||
unsigned int ip;
|
||||
unsigned short port;
|
||||
|
||||
// disk and network only
|
||||
unsigned int nTime;
|
||||
|
||||
// memory only
|
||||
unsigned int nLastTry;
|
||||
int64 nLastTry;
|
||||
};
|
||||
|
||||
/** inv message data */
|
||||
class CInv
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -7,12 +7,14 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
||||
ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
void AboutDialog::setModel(ClientModel *model)
|
||||
{
|
||||
ui->versionLabel->setText(model->formatFullVersion());
|
||||
if(model)
|
||||
{
|
||||
ui->versionLabel->setText(model->formatFullVersion());
|
||||
}
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Ui {
|
||||
}
|
||||
class ClientModel;
|
||||
|
||||
/** "About" dialog box */
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -2,13 +2,19 @@
|
||||
#include "ui_addressbookpage.h"
|
||||
|
||||
#include "addresstablemodel.h"
|
||||
#include "bitcoingui.h"
|
||||
#include "editaddressdialog.h"
|
||||
#include "csvmodelwriter.h"
|
||||
#include "guiutil.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QClipboard>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
|
||||
#ifdef USE_QRCODE
|
||||
#include "qrcodedialog.h"
|
||||
#endif
|
||||
|
||||
AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -25,6 +31,10 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
ui->deleteButton->setIcon(QIcon());
|
||||
#endif
|
||||
|
||||
#ifndef USE_QRCODE
|
||||
ui->showQRCode->setVisible(false);
|
||||
#endif
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case ForSending:
|
||||
@@ -45,7 +55,28 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
||||
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);
|
||||
|
||||
contextMenu = new QMenu();
|
||||
contextMenu->addAction(copyAddressAction);
|
||||
contextMenu->addAction(copyLabelAction);
|
||||
contextMenu->addAction(editAction);
|
||||
contextMenu->addAction(deleteAction);
|
||||
|
||||
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(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
|
||||
|
||||
// Pass through accept action from button box
|
||||
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
}
|
||||
|
||||
@@ -57,6 +88,8 @@ AddressBookPage::~AddressBookPage()
|
||||
void AddressBookPage::setModel(AddressTableModel *model)
|
||||
{
|
||||
this->model = model;
|
||||
if(!model)
|
||||
return;
|
||||
// Refresh list from core
|
||||
model->updateList();
|
||||
|
||||
@@ -96,27 +129,55 @@ void AddressBookPage::setModel(AddressTableModel *model)
|
||||
selectionChanged();
|
||||
}
|
||||
|
||||
QTableView *AddressBookPage::getCurrentTable()
|
||||
{
|
||||
return ui->tableView;
|
||||
}
|
||||
|
||||
void AddressBookPage::on_copyToClipboard_clicked()
|
||||
{
|
||||
// Copy currently selected address to clipboard
|
||||
// (or nothing, if nothing selected)
|
||||
QTableView *table = getCurrentTable();
|
||||
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
|
||||
}
|
||||
void AddressBookPage::onCopyLabelAction()
|
||||
{
|
||||
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
|
||||
}
|
||||
|
||||
void AddressBookPage::onEditAction()
|
||||
{
|
||||
if(!ui->tableView->selectionModel())
|
||||
return;
|
||||
QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
|
||||
if(indexes.isEmpty())
|
||||
return;
|
||||
|
||||
EditAddressDialog dlg(
|
||||
tab == SendingTab ?
|
||||
EditAddressDialog::EditSendingAddress :
|
||||
EditAddressDialog::EditReceivingAddress);
|
||||
dlg.setModel(model);
|
||||
QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
|
||||
dlg.loadRow(origIndex.row());
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void AddressBookPage::on_signMessage_clicked()
|
||||
{
|
||||
QTableView *table = ui->tableView;
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
||||
QString addr;
|
||||
|
||||
foreach (QModelIndex index, indexes)
|
||||
{
|
||||
QVariant address = index.data();
|
||||
QApplication::clipboard()->setText(address.toString());
|
||||
addr = address.toString();
|
||||
}
|
||||
|
||||
QObject *qoGUI = parent()->parent();
|
||||
BitcoinGUI *gui = qobject_cast<BitcoinGUI *>(qoGUI);
|
||||
if (gui)
|
||||
gui->gotoMessagePage(addr);
|
||||
}
|
||||
|
||||
void AddressBookPage::on_newAddressButton_clicked()
|
||||
{
|
||||
if(!model)
|
||||
return;
|
||||
EditAddressDialog dlg(
|
||||
tab == SendingTab ?
|
||||
EditAddressDialog::NewSendingAddress :
|
||||
@@ -139,7 +200,9 @@ void AddressBookPage::on_newAddressButton_clicked()
|
||||
|
||||
void AddressBookPage::on_deleteButton_clicked()
|
||||
{
|
||||
QTableView *table = getCurrentTable();
|
||||
QTableView *table = ui->tableView;
|
||||
if(!table->selectionModel())
|
||||
return;
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows();
|
||||
if(!indexes.isEmpty())
|
||||
{
|
||||
@@ -150,36 +213,49 @@ void AddressBookPage::on_deleteButton_clicked()
|
||||
void AddressBookPage::selectionChanged()
|
||||
{
|
||||
// Set button states based on selected tab and selection
|
||||
QTableView *table = getCurrentTable();
|
||||
QTableView *table = ui->tableView;
|
||||
if(!table->selectionModel())
|
||||
return;
|
||||
|
||||
if(table->selectionModel()->hasSelection())
|
||||
{
|
||||
switch(tab)
|
||||
{
|
||||
case SendingTab:
|
||||
// In sending tab, allow deletion of selection
|
||||
ui->deleteButton->setEnabled(true);
|
||||
deleteAction->setEnabled(true);
|
||||
ui->signMessage->setEnabled(false);
|
||||
break;
|
||||
case ReceivingTab:
|
||||
// Deleting receiving addresses, however, is not allowed
|
||||
ui->deleteButton->setEnabled(false);
|
||||
deleteAction->setEnabled(false);
|
||||
ui->signMessage->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
ui->copyToClipboard->setEnabled(true);
|
||||
ui->showQRCode->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->deleteButton->setEnabled(false);
|
||||
ui->showQRCode->setEnabled(false);
|
||||
ui->copyToClipboard->setEnabled(false);
|
||||
ui->signMessage->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBookPage::done(int retval)
|
||||
{
|
||||
QTableView *table = ui->tableView;
|
||||
if(!table->selectionModel() || !table->model())
|
||||
return;
|
||||
// When this is a tab/widget and not a model dialog, ignore "done"
|
||||
if(mode == ForEditing)
|
||||
return;
|
||||
|
||||
// Figure out which address was selected, and return it
|
||||
QTableView *table = getCurrentTable();
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
||||
|
||||
foreach (QModelIndex index, indexes)
|
||||
@@ -190,6 +266,7 @@ void AddressBookPage::done(int retval)
|
||||
|
||||
if(returnValue.isEmpty())
|
||||
{
|
||||
// If no address entry selected, return rejected
|
||||
retval = Rejected;
|
||||
}
|
||||
|
||||
@@ -199,10 +276,9 @@ void AddressBookPage::done(int retval)
|
||||
void AddressBookPage::exportClicked()
|
||||
{
|
||||
// CSV is currently the only supported format
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
QString filename = GUIUtil::getSaveFileName(
|
||||
this,
|
||||
tr("Export Address Book Data"),
|
||||
QDir::currentPath(),
|
||||
tr("Export Address Book Data"), QString(),
|
||||
tr("Comma separated file (*.csv)"));
|
||||
|
||||
if (filename.isNull()) return;
|
||||
@@ -220,3 +296,32 @@ void AddressBookPage::exportClicked()
|
||||
QMessageBox::Abort, QMessageBox::Abort);
|
||||
}
|
||||
}
|
||||
|
||||
void AddressBookPage::on_showQRCode_clicked()
|
||||
{
|
||||
#ifdef USE_QRCODE
|
||||
QTableView *table = ui->tableView;
|
||||
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
||||
|
||||
|
||||
QRCodeDialog *d;
|
||||
foreach (QModelIndex index, indexes)
|
||||
{
|
||||
QString address = index.data().toString(),
|
||||
label = index.sibling(index.row(), 0).data().toString(),
|
||||
title = QString("%1 << %2 >>").arg(label).arg(address);
|
||||
|
||||
QRCodeDialog *d = new QRCodeDialog(title, address, label, tab == ReceivingTab, this);
|
||||
d->show();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AddressBookPage::contextualMenu(const QPoint &point)
|
||||
{
|
||||
QModelIndex index = ui->tableView->indexAt(point);
|
||||
if(index.isValid())
|
||||
{
|
||||
contextMenu->exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@ QT_BEGIN_NAMESPACE
|
||||
class QTableView;
|
||||
class QItemSelection;
|
||||
class QSortFilterProxyModel;
|
||||
class QMenu;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/** Widget that shows a list of sending or receiving addresses.
|
||||
*/
|
||||
class AddressBookPage : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -25,8 +28,8 @@ public:
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
ForSending, // Pick address for sending
|
||||
ForEditing // Open address book for editing
|
||||
ForSending, /**< Open address book to pick address for sending */
|
||||
ForEditing /**< Open address book for editing */
|
||||
};
|
||||
|
||||
explicit AddressBookPage(Mode mode, Tabs tab, QWidget *parent = 0);
|
||||
@@ -46,14 +49,24 @@ private:
|
||||
Tabs tab;
|
||||
QString returnValue;
|
||||
QSortFilterProxyModel *proxyModel;
|
||||
|
||||
QTableView *getCurrentTable();
|
||||
QMenu *contextMenu;
|
||||
QAction *deleteAction;
|
||||
|
||||
private slots:
|
||||
void on_deleteButton_clicked();
|
||||
void on_newAddressButton_clicked();
|
||||
/** Copy address of currently selected address entry to clipboard */
|
||||
void on_copyToClipboard_clicked();
|
||||
void on_signMessage_clicked();
|
||||
void selectionChanged();
|
||||
void on_showQRCode_clicked();
|
||||
/** Spawn contextual menu (right mouse menu) for address book entry */
|
||||
void contextualMenu(const QPoint &point);
|
||||
|
||||
/** Copy label of currently selected address entry to clipboard */
|
||||
void onCopyLabelAction();
|
||||
/** Edit currently selected address entry */
|
||||
void onEditAction();
|
||||
};
|
||||
|
||||
#endif // ADDRESSBOOKDIALOG_H
|
||||
|
||||
@@ -8,6 +8,9 @@ class AddressTablePriv;
|
||||
class CWallet;
|
||||
class WalletModel;
|
||||
|
||||
/**
|
||||
Qt model of the address book in the core. This allows views to access and modify the address book.
|
||||
*/
|
||||
class AddressTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -16,27 +19,28 @@ public:
|
||||
~AddressTableModel();
|
||||
|
||||
enum ColumnIndex {
|
||||
Label = 0, /* User specified label */
|
||||
Address = 1 /* Bitcoin address */
|
||||
Label = 0, /**< User specified label */
|
||||
Address = 1 /**< Bitcoin address */
|
||||
};
|
||||
|
||||
enum RoleIndex {
|
||||
TypeRole = Qt::UserRole
|
||||
TypeRole = Qt::UserRole /**< Type of address (#Send or #Receive) */
|
||||
};
|
||||
|
||||
// Return status of last edit/insert operation
|
||||
/** Return status of edit/insert operation */
|
||||
enum EditStatus {
|
||||
OK,
|
||||
INVALID_ADDRESS,
|
||||
DUPLICATE_ADDRESS,
|
||||
WALLET_UNLOCK_FAILURE,
|
||||
KEY_GENERATION_FAILURE
|
||||
INVALID_ADDRESS, /**< Unparseable address */
|
||||
DUPLICATE_ADDRESS, /**< Address already in address book */
|
||||
WALLET_UNLOCK_FAILURE, /**< Wallet could not be unlocked to create new receiving address */
|
||||
KEY_GENERATION_FAILURE /**< Generating a new public key for a receiving address failed */
|
||||
};
|
||||
|
||||
static const QString Send; /* Send addres */
|
||||
static const QString Receive; /* Receive address */
|
||||
static const QString Send; /**< Specifies send address */
|
||||
static const QString Receive; /**< Specifies receive address */
|
||||
|
||||
/* Overridden methods from QAbstractTableModel */
|
||||
/** @name Methods overridden from QAbstractTableModel
|
||||
@{*/
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
@@ -45,6 +49,7 @@ public:
|
||||
QModelIndex index(int row, int column, const QModelIndex & parent) const;
|
||||
bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex());
|
||||
Qt::ItemFlags flags(const QModelIndex & index) const;
|
||||
/*@}*/
|
||||
|
||||
/* Add an address to the model.
|
||||
Returns the added address on success, and an empty string otherwise.
|
||||
|
||||
@@ -6,17 +6,25 @@
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QKeyEvent>
|
||||
|
||||
AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AskPassphraseDialog),
|
||||
mode(mode),
|
||||
model(0)
|
||||
model(0),
|
||||
fCapsLock(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE);
|
||||
ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE);
|
||||
ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE);
|
||||
|
||||
// Setup Caps Lock detection.
|
||||
ui->passEdit1->installEventFilter(this);
|
||||
ui->passEdit2->installEventFilter(this);
|
||||
ui->passEdit3->installEventFilter(this);
|
||||
ui->capsLabel->clear();
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
@@ -47,7 +55,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
|
||||
ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet."));
|
||||
break;
|
||||
}
|
||||
resize(minimumSize()); // Get rid of extra space in dialog
|
||||
|
||||
textChanged();
|
||||
connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
|
||||
@@ -71,14 +78,17 @@ void AskPassphraseDialog::setModel(WalletModel *model)
|
||||
|
||||
void AskPassphraseDialog::accept()
|
||||
{
|
||||
std::string oldpass, newpass1, newpass2;
|
||||
// TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely
|
||||
SecureString oldpass, newpass1, newpass2;
|
||||
if(!model)
|
||||
return;
|
||||
oldpass.reserve(MAX_PASSPHRASE_SIZE);
|
||||
newpass1.reserve(MAX_PASSPHRASE_SIZE);
|
||||
newpass2.reserve(MAX_PASSPHRASE_SIZE);
|
||||
oldpass.assign(ui->passEdit1->text().toStdString());
|
||||
newpass1.assign(ui->passEdit2->text().toStdString());
|
||||
newpass2.assign(ui->passEdit3->text().toStdString());
|
||||
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
|
||||
// Alternately, find a way to make this input mlock()'d to begin with.
|
||||
oldpass.assign(ui->passEdit1->text().toStdString().c_str());
|
||||
newpass1.assign(ui->passEdit2->text().toStdString().c_str());
|
||||
newpass2.assign(ui->passEdit3->text().toStdString().c_str());
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
@@ -99,7 +109,8 @@ void AskPassphraseDialog::accept()
|
||||
if(model->setWalletEncrypted(true, newpass1))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Wallet encrypted"),
|
||||
tr("Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
|
||||
tr("Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
|
||||
QApplication::quit();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -184,3 +195,46 @@ void AskPassphraseDialog::textChanged()
|
||||
}
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
|
||||
}
|
||||
|
||||
bool AskPassphraseDialog::event(QEvent *event)
|
||||
{
|
||||
// Detect Caps Lock key press.
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
if (ke->key() == Qt::Key_CapsLock) {
|
||||
fCapsLock = !fCapsLock;
|
||||
}
|
||||
if (fCapsLock) {
|
||||
ui->capsLabel->setText(tr("Warning: The Caps Lock key is on."));
|
||||
} else {
|
||||
ui->capsLabel->clear();
|
||||
}
|
||||
}
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
bool AskPassphraseDialog::eventFilter(QObject *, QEvent *event)
|
||||
{
|
||||
/* 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
|
||||
* Shift key is not down and the result is an upper case character.
|
||||
*/
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
QString str = ke->text();
|
||||
if (str.length() != 0) {
|
||||
const QChar *psz = str.unicode();
|
||||
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."));
|
||||
} else if (psz->isLetter()) {
|
||||
fCapsLock = false;
|
||||
ui->capsLabel->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,18 @@ namespace Ui {
|
||||
|
||||
class WalletModel;
|
||||
|
||||
/** Multifunctional dialog to ask for passphrases. Used for encryption, unlocking, and changing the passphrase.
|
||||
*/
|
||||
class AskPassphraseDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
Encrypt, // Ask passphrase x2
|
||||
Unlock, // Ask passphrase
|
||||
ChangePass, // Ask old passphrase + new passphrase x2
|
||||
Decrypt // Ask passphrase
|
||||
Encrypt, /**< Ask passphrase twice and encrypt */
|
||||
Unlock, /**< Ask passphrase and unlock */
|
||||
ChangePass, /**< Ask old passphrase + new passphrase twice */
|
||||
Decrypt /**< Ask passphrase and decrypt wallet */
|
||||
};
|
||||
|
||||
explicit AskPassphraseDialog(Mode mode, QWidget *parent = 0);
|
||||
@@ -32,9 +34,12 @@ private:
|
||||
Ui::AskPassphraseDialog *ui;
|
||||
Mode mode;
|
||||
WalletModel *model;
|
||||
bool fCapsLock;
|
||||
|
||||
private slots:
|
||||
void textChanged();
|
||||
bool event(QEvent *event);
|
||||
bool eventFilter(QObject *, QEvent *event);
|
||||
};
|
||||
|
||||
#endif // ASKPASSPHRASEDIALOG_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* W.J. van der Laan 2011
|
||||
* W.J. van der Laan 2011-2012
|
||||
*/
|
||||
#include "bitcoingui.h"
|
||||
#include "clientmodel.h"
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "headers.h"
|
||||
#include "init.h"
|
||||
#include "qtipcserver.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
@@ -18,24 +19,18 @@
|
||||
#include <QSplashScreen>
|
||||
#include <QLibraryInfo>
|
||||
|
||||
#include <boost/interprocess/ipc/message_queue.hpp>
|
||||
|
||||
// Need a global reference for the notifications to find the GUI
|
||||
BitcoinGUI *guiref;
|
||||
QSplashScreen *splashref;
|
||||
|
||||
int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
|
||||
{
|
||||
// Message from main thread
|
||||
if(guiref)
|
||||
{
|
||||
guiref->error(QString::fromStdString(caption),
|
||||
QString::fromStdString(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(0, QString::fromStdString(caption),
|
||||
QString::fromStdString(message),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
}
|
||||
// Message from AppInit2(), always in main thread before main window is constructed
|
||||
QMessageBox::critical(0, QString::fromStdString(caption),
|
||||
QString::fromStdString(message),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
return 4;
|
||||
}
|
||||
|
||||
@@ -79,6 +74,22 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindo
|
||||
return payFee;
|
||||
}
|
||||
|
||||
void ThreadSafeHandleURL(const std::string& strURL)
|
||||
{
|
||||
if(!guiref)
|
||||
return;
|
||||
|
||||
// Call slot on GUI thread.
|
||||
// If called from another thread, use a blocking QueuedConnection.
|
||||
Qt::ConnectionType connectionType = Qt::DirectConnection;
|
||||
if(QThread::currentThread() != QCoreApplication::instance()->thread())
|
||||
{
|
||||
connectionType = Qt::BlockingQueuedConnection;
|
||||
}
|
||||
QMetaObject::invokeMethod(guiref, "handleURL", connectionType,
|
||||
Q_ARG(QString, QString::fromStdString(strURL)));
|
||||
}
|
||||
|
||||
void CalledSetStatusBar(const std::string& strText, int nField)
|
||||
{
|
||||
// Only used for built-in mining, which is disabled, simple ignore
|
||||
@@ -91,6 +102,8 @@ void UIThreadCall(boost::function0<void> fn)
|
||||
|
||||
void MainFrameRepaint()
|
||||
{
|
||||
if(guiref)
|
||||
QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void InitMessage(const std::string &message)
|
||||
@@ -110,19 +123,68 @@ std::string _(const char* psz)
|
||||
return QCoreApplication::translate("bitcoin-core", psz).toStdString();
|
||||
}
|
||||
|
||||
#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 *strURL = argv[i];
|
||||
try {
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
|
||||
if(mq.try_send(strURL, strlen(strURL), 0))
|
||||
exit(0);
|
||||
else
|
||||
break;
|
||||
}
|
||||
catch (boost::interprocess::interprocess_exception &ex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Internal string conversion is all UTF-8
|
||||
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
|
||||
|
||||
Q_INIT_RESOURCE(bitcoin);
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Load language files for system locale:
|
||||
// Command-line options take precedence:
|
||||
ParseParameters(argc, argv);
|
||||
|
||||
// ... then bitcoin.conf:
|
||||
if (!ReadConfigFile(mapArgs, mapMultiArgs))
|
||||
{
|
||||
fprintf(stderr, "Error: Specified directory does not exist\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Application identification (must be set before OptionsModel is initialized,
|
||||
// as it is used to locate QSettings)
|
||||
app.setOrganizationName("Bitcoin");
|
||||
app.setOrganizationDomain("bitcoin.org");
|
||||
if(GetBoolArg("-testnet")) // Separate UI settings for testnet
|
||||
app.setApplicationName("Bitcoin-Qt-testnet");
|
||||
else
|
||||
app.setApplicationName("Bitcoin-Qt");
|
||||
|
||||
// ... then GUI settings:
|
||||
OptionsModel optionsModel;
|
||||
|
||||
// Get desired locale ("en_US") from command line or system locale
|
||||
QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
|
||||
// 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_territory = QLocale::system().name(); // "en_US"
|
||||
QString lang = lang_territory;
|
||||
|
||||
lang.truncate(lang_territory.lastIndexOf('_')); // "en"
|
||||
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
|
||||
|
||||
@@ -142,12 +204,13 @@ int main(int argc, char *argv[])
|
||||
if (!translator.isEmpty())
|
||||
app.installTranslator(&translator);
|
||||
|
||||
app.setApplicationName(QApplication::translate("main", "Bitcoin-Qt"));
|
||||
|
||||
QSplashScreen splash(QPixmap(":/images/splash"), 0);
|
||||
splash.show();
|
||||
splash.setAutoFillBackground(true);
|
||||
splashref = &splash;
|
||||
if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
|
||||
{
|
||||
splash.show();
|
||||
splash.setAutoFillBackground(true);
|
||||
splashref = &splash;
|
||||
}
|
||||
|
||||
app.processEvents();
|
||||
|
||||
@@ -159,10 +222,14 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
{
|
||||
// Put this in a block, so that BitcoinGUI is cleaned up properly before
|
||||
// calling Shutdown().
|
||||
// calling Shutdown() in case of exceptions.
|
||||
|
||||
optionsModel.Upgrade(); // Must be done after AppInit2
|
||||
|
||||
BitcoinGUI window;
|
||||
splash.finish(&window);
|
||||
OptionsModel optionsModel(pwalletMain);
|
||||
if (splashref)
|
||||
splash.finish(&window);
|
||||
|
||||
ClientModel clientModel(&optionsModel);
|
||||
WalletModel walletModel(pwalletMain, &optionsModel);
|
||||
|
||||
@@ -170,8 +237,37 @@ int main(int argc, char *argv[])
|
||||
window.setClientModel(&clientModel);
|
||||
window.setWalletModel(&walletModel);
|
||||
|
||||
window.show();
|
||||
// If -min option passed, start window minimized.
|
||||
if(GetBoolArg("-min"))
|
||||
{
|
||||
window.showMinimized();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.show();
|
||||
}
|
||||
|
||||
// Place this here as guiref has to be defined if we dont want to lose URLs
|
||||
ipcInit();
|
||||
|
||||
#if !defined(MAC_OSX) && !defined(WIN32)
|
||||
// TODO: implement qtipcserver.cpp for Mac and Windows
|
||||
|
||||
// Check for URL in argv
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
|
||||
{
|
||||
const char *strURL = argv[i];
|
||||
try {
|
||||
boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
|
||||
mq.try_send(strURL, strlen(strURL), 0);
|
||||
}
|
||||
catch (boost::interprocess::interprocess_exception &ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
app.exec();
|
||||
|
||||
guiref = 0;
|
||||
@@ -189,3 +285,4 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // BITCOIN_QT_TEST
|
||||
|
||||
@@ -37,21 +37,48 @@
|
||||
<file alias="lock_closed">res/icons/lock_closed.png</file>
|
||||
<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>
|
||||
</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="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="en">locale/bitcoin_en.qm</file>
|
||||
<file alias="es">locale/bitcoin_es.qm</file>
|
||||
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
|
||||
<file alias="es">locale/bitcoin_es.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="fi">locale/bitcoin_fi.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>
|
||||
<file alias="it">locale/bitcoin_it.qm</file>
|
||||
<file alias="lt">locale/bitcoin_lt.qm</file>
|
||||
<file alias="nb">locale/bitcoin_nb.qm</file>
|
||||
<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="ro_RO">locale/bitcoin_ro_RO.qm</file>
|
||||
<file alias="ru">locale/bitcoin_ru.qm</file>
|
||||
<file alias="sk">locale/bitcoin_sk.qm</file>
|
||||
<file alias="sr">locale/bitcoin_sr.qm</file>
|
||||
<file alias="sv">locale/bitcoin_sv.qm</file>
|
||||
<file alias="tr">locale/bitcoin_tr.qm</file>
|
||||
<file alias="uk">locale/bitcoin_uk.qm</file>
|
||||
<file alias="zh_CN">locale/bitcoin_zh_CN.qm</file>
|
||||
<file alias="zh_TW">locale/bitcoin_zh_TW.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <QRegExpValidator>
|
||||
|
||||
/* Base48 entry widget validator.
|
||||
/** Base48 entry widget validator.
|
||||
Corrects near-miss characters and refuses characters that are no part of base48.
|
||||
*/
|
||||
class BitcoinAddressValidator : public QValidator
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
|
||||
State validate(QString &input, int &pos) const;
|
||||
|
||||
static const int MaxAddressLength = 34;
|
||||
static const int MaxAddressLength = 35;
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
@@ -22,6 +22,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent):
|
||||
amount->setDecimals(8);
|
||||
amount->installEventFilter(this);
|
||||
amount->setMaximumWidth(170);
|
||||
amount->setSingleStep(0.001);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(amount);
|
||||
|
||||
@@ -8,8 +8,8 @@ class QDoubleSpinBox;
|
||||
class QValueComboBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// Coin amount entry widget with separate parts for whole
|
||||
// coins and decimals.
|
||||
/** Widget for entering bitcoin amounts.
|
||||
*/
|
||||
class BitcoinAmountField: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -20,25 +20,27 @@ public:
|
||||
qint64 value(bool *valid=0) const;
|
||||
void setValue(qint64 value);
|
||||
|
||||
// Mark current valid as invalid in UI
|
||||
/** Mark current value as invalid in UI. */
|
||||
void setValid(bool valid);
|
||||
/** Perform input validation, mark field as invalid if entered value is not valid. */
|
||||
bool validate();
|
||||
|
||||
// Change current unit
|
||||
/** Change unit used to display amount. */
|
||||
void setDisplayUnit(int unit);
|
||||
|
||||
// Make field empty and ready for new input
|
||||
/** Make field empty and ready for new input. */
|
||||
void clear();
|
||||
|
||||
// Qt messes up the tab chain by default in some cases (issue http://bugreports.qt.nokia.com/browse/QTBUG-10907)
|
||||
// Hence we have to set it up manually
|
||||
/** Qt messes up the tab chain by default in some cases (issue http://bugreports.qt.nokia.com/browse/QTBUG-10907),
|
||||
in these cases we have to set it up manually.
|
||||
*/
|
||||
QWidget *setupTabChain(QWidget *prev);
|
||||
|
||||
signals:
|
||||
void textChanged();
|
||||
|
||||
protected:
|
||||
// Intercept focus-in event and ',' keypresses
|
||||
/** Intercept focus-in event and ',' keypresses */
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user