diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 104 |
1 files changed, 90 insertions, 14 deletions
diff --git a/src/main.cpp b/src/main.cpp index 9082bd5..9bb3c24 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -181,6 +181,39 @@ static bool AddKeyIfMissing(const CKey& key) | |||
| 181 | return AddKey(key); | 181 | return AddKey(key); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static bool DeriveNextHDWalletKey(vector<unsigned char>& vchPubKeyRet, string& strErrorRet) | ||
| 185 | { | ||
| 186 | vchPubKeyRet.clear(); | ||
| 187 | CRITICAL_BLOCK(cs_keyPool) | ||
| 188 | { | ||
| 189 | if (!HaveHDSeed()) | ||
| 190 | { | ||
| 191 | strErrorRet = "no seed"; | ||
| 192 | return false; | ||
| 193 | } | ||
| 194 | |||
| 195 | CKey key; | ||
| 196 | if (!DeriveHDKey(nHDNext, key, strErrorRet)) | ||
| 197 | return false; | ||
| 198 | if (!AddKeyIfMissing(key)) | ||
| 199 | { | ||
| 200 | strErrorRet = "could not write the derived key to wallet.dat"; | ||
| 201 | return false; | ||
| 202 | } | ||
| 203 | |||
| 204 | unsigned int nNext = nHDNext + 1; | ||
| 205 | if (!CWalletDB().WriteHDNext(nNext)) | ||
| 206 | { | ||
| 207 | strErrorRet = "could not advance the derivation counter"; | ||
| 208 | return false; | ||
| 209 | } | ||
| 210 | |||
| 211 | nHDNext = nNext; | ||
| 212 | vchPubKeyRet = key.GetPubKey(); | ||
| 213 | } | ||
| 214 | return true; | ||
| 215 | } | ||
| 216 | |||
| 184 | vector<unsigned char> GenerateNewKey() | 217 | vector<unsigned char> GenerateNewKey() |
| 185 | { | 218 | { |
| 186 | CKey key; | 219 | CKey key; |
| @@ -2310,27 +2343,55 @@ bool ProcessMessages(CNode* pfrom) | |||
| 2310 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", (int)(pstart - vRecv.begin())); | 2343 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", (int)(pstart - vRecv.begin())); |
| 2311 | vRecv.erase(vRecv.begin(), pstart); | 2344 | vRecv.erase(vRecv.begin(), pstart); |
| 2312 | 2345 | ||
| 2313 | // Read header | 2346 | // Read the header from a copy first. The old path consumed the header, |
| 2347 | // noticed the payload was incomplete, inserted the header back at the | ||
| 2348 | // front of the receive buffer, then slept inside the shared message | ||
| 2349 | // thread. A peer could announce a large payload and drip bytes forever, | ||
| 2350 | // making every pass pay for an O(n) insert and a 100 ms stall. | ||
| 2314 | CMessageHeader hdr; | 2351 | CMessageHeader hdr; |
| 2315 | vRecv >> hdr; | 2352 | CDataStream vHeader(vRecv.begin(), vRecv.begin() + sizeof(CMessageHeader), |
| 2353 | vRecv.nType, vRecv.nVersion); | ||
| 2354 | vHeader >> hdr; | ||
| 2316 | if (!hdr.IsValid()) | 2355 | if (!hdr.IsValid()) |
| 2317 | { | 2356 | { |
| 2318 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str()); | 2357 | if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand().c_str()); |
| 2358 | if (hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_SIZE) | ||
| 2359 | pfrom->fDisconnect = true; | ||
| 2360 | pfrom->nIncompleteMessageStart = 0; | ||
| 2361 | vRecv.ignore(sizeof(CMessageHeader)); | ||
| 2319 | continue; | 2362 | continue; |
| 2320 | } | 2363 | } |
| 2321 | string strCommand = hdr.GetCommand(); | 2364 | string strCommand = hdr.GetCommand(); |
| 2322 | 2365 | ||
| 2323 | // Message size | 2366 | // Message size |
| 2324 | unsigned int nMessageSize = hdr.nMessageSize; | 2367 | unsigned int nMessageSize = hdr.nMessageSize; |
| 2325 | if (nMessageSize > vRecv.size()) | 2368 | unsigned int nPayloadAvailable = vRecv.size() - sizeof(CMessageHeader); |
| 2369 | if (nMessageSize > nPayloadAvailable) | ||
| 2326 | { | 2370 | { |
| 2327 | // Rewind and wait for rest of message | 2371 | if (pfrom->nIncompleteMessageStart == 0 || |
| 2328 | ///// need a mechanism to give up waiting for overlong message size error | 2372 | pfrom->nIncompleteMessageSize != nMessageSize || |
| 2329 | if (LogAcceptsCategory("net")) printf("MESSAGE-BREAK 2\n"); | 2373 | pfrom->strIncompleteMessageCommand != strCommand) |
| 2330 | vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr)); | 2374 | { |
| 2331 | Sleep(100); | 2375 | pfrom->nIncompleteMessageStart = GetTime(); |
| 2376 | pfrom->nIncompleteMessageSize = nMessageSize; | ||
| 2377 | pfrom->strIncompleteMessageCommand = strCommand; | ||
| 2378 | } | ||
| 2379 | else if (GetTime() - pfrom->nIncompleteMessageStart > | ||
| 2380 | BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS) | ||
| 2381 | { | ||
| 2382 | LogPrint("net", | ||
| 2383 | "disconnecting %s: incomplete %s message, %u of %u bytes after %d seconds\n", | ||
| 2384 | pfrom->addr.ToString().c_str(), strCommand.c_str(), | ||
| 2385 | nPayloadAvailable, nMessageSize, | ||
| 2386 | BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS); | ||
| 2387 | pfrom->fDisconnect = true; | ||
| 2388 | } | ||
| 2332 | break; | 2389 | break; |
| 2333 | } | 2390 | } |
| 2391 | pfrom->nIncompleteMessageStart = 0; | ||
| 2392 | pfrom->nIncompleteMessageSize = 0; | ||
| 2393 | pfrom->strIncompleteMessageCommand.clear(); | ||
| 2394 | vRecv.ignore(sizeof(CMessageHeader)); | ||
| 2334 | 2395 | ||
| 2335 | // Copy message to its own buffer | 2396 | // Copy message to its own buffer |
| 2336 | CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion); | 2397 | CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion); |
| @@ -3774,13 +3835,28 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in | |||
| 3774 | // Fill vout[1] back to self with any change | 3835 | // Fill vout[1] back to self with any change |
| 3775 | if (nValueIn > nTotalValue) | 3836 | if (nValueIn > nTotalValue) |
| 3776 | { | 3837 | { |
| 3777 | // Use the same key as one of the coins | ||
| 3778 | vector<unsigned char> vchPubKey; | 3838 | vector<unsigned char> vchPubKey; |
| 3779 | CTransaction& txFirst = *(*setCoins.begin()); | 3839 | if (HaveHDSeed()) |
| 3780 | foreach(const CTxOut& txout, txFirst.vout) | 3840 | { |
| 3781 | if (txout.IsMine()) | 3841 | string strError; |
| 3782 | if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) | 3842 | if (!DeriveNextHDWalletKey(vchPubKey, strError)) |
| 3783 | break; | 3843 | { |
| 3844 | printf("CreateTransaction() : could not derive a phrase-backed change key: %s\n", | ||
| 3845 | strError.c_str()); | ||
| 3846 | return false; | ||
| 3847 | } | ||
| 3848 | } | ||
| 3849 | else | ||
| 3850 | { | ||
| 3851 | // Legacy wallets have no deterministic seed. Preserve | ||
| 3852 | // the 0.1.0 behaviour for them: return change to a key | ||
| 3853 | // already proven to belong to this wallet. | ||
| 3854 | CTransaction& txFirst = *(*setCoins.begin()); | ||
| 3855 | foreach(const CTxOut& txout, txFirst.vout) | ||
| 3856 | if (txout.IsMine()) | ||
| 3857 | if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey)) | ||
| 3858 | break; | ||
| 3859 | } | ||
| 3784 | if (vchPubKey.empty()) | 3860 | if (vchPubKey.empty()) |
| 3785 | return false; | 3861 | return false; |
| 3786 | 3862 | ||