]>
Commit | Line | Data |
---|---|---|
2513363e S |
1 | /* |
2 | So you need to broadcast an alert... | |
3 | ... here's what to do: | |
4 | ||
5 | 1. Copy sendalert.cpp into your bitcoind build directory | |
6 | ||
7 | 2. Decrypt the alert keys | |
8 | copy the decrypted file as alertkeys.h into the src/ directory. | |
9 | ||
10 | 3. Modify the alert parameters in sendalert.cpp | |
11 | See the comments in the code for what does what. | |
12 | ||
13 | 4. Add sendalert.cpp to the src/Makefile.am so it gets built: | |
14 | ||
15 | libbitcoin_server_a_SOURCES = \ | |
16 | sendalert.cpp \ | |
17 | ... etc | |
18 | ||
19 | 5. Update init.cpp to launch the send alert thread. | |
20 | Define the thread function as external at the top of init.cpp: | |
21 | ||
22 | extern void ThreadSendAlert(); | |
23 | ||
24 | Add this call at the end of AppInit2: | |
25 | ||
26 | threadGroup.create_thread(boost::bind(ThreadSendAlert)); | |
27 | ||
28 | 6. build bitcoind, then run it with -printalert or -sendalert | |
29 | I usually run it like this: | |
30 | ./bitcoind -printtoconsole -sendalert | |
31 | ||
32 | One minute after starting up the alert will be broadcast. It is then | |
33 | flooded through the network until the nRelayUntil time, and will be | |
34 | active until nExpiration OR the alert is cancelled. | |
35 | ||
36 | If you screw up something, send another alert with nCancel set to cancel | |
37 | the bad alert. | |
38 | */ | |
39 | #include "main.h" | |
40 | #include "net.h" | |
41 | #include "alert.h" | |
42 | #include "init.h" | |
43 | ||
44 | static const int64_t DAYS = 24 * 60 * 60; | |
45 | ||
46 | void ThreadSendAlert() | |
47 | { | |
48 | MilliSleep(60*1000); // Wait a minute so we get connected | |
49 | if (!mapArgs.count("-sendalert") && !mapArgs.count("-printalert")) | |
50 | return; | |
51 | ||
52 | // | |
53 | // Alerts are relayed around the network until nRelayUntil, flood | |
54 | // filling to every node. | |
55 | // After the relay time is past, new nodes are told about alerts | |
56 | // when they connect to peers, until either nExpiration or | |
57 | // the alert is cancelled by a newer alert. | |
58 | // Nodes never save alerts to disk, they are in-memory-only. | |
59 | // | |
60 | CAlert alert; | |
61 | alert.nRelayUntil = GetTime() + 15 * 60; | |
62 | alert.nExpiration = GetTime() + 365 * 60 * 60; | |
63 | alert.nID = 1040; // use https://en.bitcoin.it/wiki/Alerts to keep track of alert IDs | |
64 | alert.nCancel = 0; // cancels previous messages up to this ID number | |
65 | ||
66 | // These versions are protocol versions | |
67 | // 60002 : 0.7.* | |
68 | // 70001 : 0.8.* | |
69 | // 70002 : 0.9.* | |
70 | alert.nMinVer = 70002; | |
71 | alert.nMaxVer = 70002; | |
72 | ||
73 | // | |
74 | // main.cpp: | |
75 | // 1000 for Misc warnings like out of disk space and clock is wrong | |
76 | // 2000 for longer invalid proof-of-work chain | |
77 | // Higher numbers mean higher priority | |
78 | alert.nPriority = 5000; | |
79 | alert.strComment = ""; | |
80 | alert.strStatusBar = "URGENT: Upgrade required: see https://www.bitcoin.org/heartbleed"; | |
81 | ||
82 | // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done: | |
83 | // alert.setSubVer.insert(std::string("/Satoshi:0.7.2/")); | |
84 | ||
85 | // Sign | |
86 | #include "alertkeys.h" | |
87 | ||
88 | std::vector<unsigned char> vchTmp(ParseHex(TestNet() ? pszTestNetPrivKey : pszPrivKey)); | |
89 | CPrivKey vchPrivKey(vchTmp.begin(), vchTmp.end()); | |
90 | ||
91 | CDataStream sMsg(SER_NETWORK, CLIENT_VERSION); | |
92 | sMsg << *(CUnsignedAlert*)&alert; | |
93 | alert.vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end()); | |
94 | CKey key; | |
95 | if (!key.SetPrivKey(vchPrivKey, false)) | |
96 | { | |
97 | printf("ThreadSendAlert() : key.SetPrivKey failed\n"); | |
98 | return; | |
99 | } | |
100 | if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) | |
101 | { | |
102 | printf("ThreadSendAlert() : key.Sign failed\n"); | |
103 | return; | |
104 | } | |
105 | ||
106 | // Test | |
107 | CDataStream sBuffer(SER_NETWORK, CLIENT_VERSION); | |
108 | sBuffer << alert; | |
109 | CAlert alert2; | |
110 | sBuffer >> alert2; | |
111 | if (!alert2.CheckSignature()) | |
112 | { | |
113 | printf("ThreadSendAlert() : CheckSignature failed\n"); | |
114 | return; | |
115 | } | |
116 | assert(alert2.vchMsg == alert.vchMsg); | |
117 | assert(alert2.vchSig == alert.vchSig); | |
118 | alert.SetNull(); | |
119 | printf("\nThreadSendAlert:\n"); | |
120 | printf("hash=%s\n", alert2.GetHash().ToString().c_str()); | |
121 | alert2.print(); | |
122 | printf("vchMsg=%s\n", HexStr(alert2.vchMsg).c_str()); | |
123 | printf("vchSig=%s\n", HexStr(alert2.vchSig).c_str()); | |
124 | ||
125 | // Confirm | |
126 | if (!mapArgs.count("-sendalert")) | |
127 | return; | |
128 | while (vNodes.size() < 1 && !ShutdownRequested()) | |
129 | MilliSleep(500); | |
130 | if (ShutdownRequested()) | |
131 | return; | |
132 | #ifdef QT_GUI | |
133 | if (ThreadSafeMessageBox("Send alert?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES) | |
134 | return; | |
135 | if (ThreadSafeMessageBox("Send alert, are you sure?", "ThreadSendAlert", wxYES_NO | wxNO_DEFAULT) != wxYES) | |
136 | { | |
137 | ThreadSafeMessageBox("Nothing sent", "ThreadSendAlert", wxOK); | |
138 | return; | |
139 | } | |
140 | #endif | |
141 | ||
142 | // Send | |
143 | printf("ThreadSendAlert() : Sending alert\n"); | |
144 | int nSent = 0; | |
145 | { | |
146 | LOCK(cs_vNodes); | |
147 | BOOST_FOREACH(CNode* pnode, vNodes) | |
148 | { | |
149 | if (alert2.RelayTo(pnode)) | |
150 | { | |
151 | printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str()); | |
152 | nSent++; | |
153 | } | |
154 | } | |
155 | } | |
156 | printf("ThreadSendAlert() : Alert sent to %d nodes\n", nSent); | |
157 | } |