From 6fd7ef2bbf1f941c8dee302ffdeb44e603148723 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 7 Feb 2014 02:19:48 +0100 Subject: [PATCH 001/336] Also switch the (unused) verification code to low-s instead of even-s. a81cd968 introduced a malleability breaker for signatures (using an even value for S). In e0e14e43 this was changed to the lower of two potential values, rather than the even one. Only the signing code was changed though, the (for now unused) verification code wasn't adapted. --- src/key.cpp | 72 +++++++++++++++++++++++++----------- src/key.h | 3 ++ src/script.cpp | 9 +++-- src/script.h | 2 +- src/test/canonical_tests.cpp | 17 +++++++++ 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index b57b7c506c..2199996cf3 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -332,30 +332,60 @@ public: } }; +int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { + while (c1len > c2len) { + if (*c1) + return 1; + c1++; + c1len--; + } + while (c2len > c1len) { + if (*c2) + return -1; + c2++; + c2len--; + } + while (c1len > 0) { + if (*c1 > *c2) + return 1; + if (*c2 > *c1) + return -1; + c1++; + c2++; + c1len--; + } + return 0; +} + +// Order of secp256k1's generator minus 1. +const unsigned char vchMaxModOrder[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 +}; + +// Half of the order of secp256k1's generator minus 1. +const unsigned char vchMaxModHalfOrder[32] = { + 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, + 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 +}; + +const unsigned char vchZero[0] = {}; + + }; // end of anonymous namespace bool CKey::Check(const unsigned char *vch) { - // Do not convert to OpenSSL's data structures for range-checking keys, - // it's easy enough to do directly. - static const unsigned char vchMax[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 - }; - bool fIsZero = true; - for (int i=0; i<32 && fIsZero; i++) - if (vch[i] != 0) - fIsZero = false; - if (fIsZero) - return false; - for (int i=0; i<32; i++) { - if (vch[i] < vchMax[i]) - return true; - if (vch[i] > vchMax[i]) - return false; - } - return true; + return CompareBigEndian(vch, 32, vchZero, 0) > 0 && + CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0; +} + +bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { + return CompareBigEndian(vch, len, vchZero, 0) > 0 && + CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; } void CKey::MakeNewKey(bool fCompressedIn) { diff --git a/src/key.h b/src/key.h index cf1165d3d0..37a06810b4 100644 --- a/src/key.h +++ b/src/key.h @@ -269,6 +269,9 @@ public: // Load private key and check that public key matches. bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck); + + // Check whether an element of a signature (r or s) is valid. + static bool CheckSignatureElement(const unsigned char *vch, int len, bool half); }; struct CExtPubKey { diff --git a/src/script.cpp b/src/script.cpp index 810ba16d28..84a2a629e8 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -296,9 +296,12 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) return error("Non-canonical signature: S value excessively padded"); - if (flags & SCRIPT_VERIFY_EVEN_S) { - if (S[nLenS-1] & 1) - return error("Non-canonical signature: S value odd"); + if (flags & SCRIPT_VERIFY_LOW_S) { + // If the S value is above the order of the curve divided by two, its + // complement modulo the order could have been used instead, which is + // one byte shorter when encoded correctly. + if (!CKey::CheckSignatureElement(S, nLenS, true)) + return error("Non-canonical signature: S value is unnecessarily high"); } return true; diff --git a/src/script.h b/src/script.h index 657ac0b388..b96bbc45c3 100644 --- a/src/script.h +++ b/src/script.h @@ -40,7 +40,7 @@ enum SCRIPT_VERIFY_NONE = 0, SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys - SCRIPT_VERIFY_EVEN_S = (1U << 2), // enforce even S values in signatures (depends on STRICTENC) + SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values ( sig; + uint256 hash = GetRandHash(); + + BOOST_CHECK(key.Sign(hash, sig)); // Generate a random signature. + BOOST_CHECK(key.GetPubKey().Verify(hash, sig)); // Check it. + sig.push_back(0x01); // Append a sighash type. + + BOOST_CHECK(IsCanonicalSignature(sig, SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_LOW_S)); + BOOST_CHECK(IsCanonicalSignature_OpenSSL(sig)); + } +} + BOOST_AUTO_TEST_SUITE_END() From b41e5947735097d12eb795f2d1dc9c79ff391aba Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 12 Mar 2014 20:07:51 -0400 Subject: [PATCH 002/336] Fix script test handling of empty scripts Previously an empty script would evaluate to OP_0 --- src/test/data/script_invalid.json | 10 ++++++++++ src/test/data/script_valid.json | 12 ++++++++++++ src/test/script_tests.cpp | 6 +++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 8cb365a46f..609c89be06 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -1,8 +1,18 @@ [ +["", "DEPTH", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH", "and multiple spaces should not change that."], +[" ", "DEPTH"], +[" ", "DEPTH"], + ["", ""], ["", "NOP"], +["", "NOP DEPTH"], ["NOP", ""], +["NOP", "DEPTH"], ["NOP","NOP"], +["NOP","NOP DEPTH"], + +["DEPTH", ""], ["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], ["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 3b4c191865..c50767071a 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -1,4 +1,16 @@ [ +["", "DEPTH 0 EQUAL", "Test the test: we should have an empty stack after scriptSig evaluation"], +[" ", "DEPTH 0 EQUAL", "and multiple spaces should not change that."], +[" ", "DEPTH 0 EQUAL"], +[" ", "DEPTH 0 EQUAL"], +["1 2", "2 EQUALVERIFY 1 EQUAL", "Similarly whitespace around and between symbols"], +["1 2", "2 EQUALVERIFY 1 EQUAL"], +[" 1 2", "2 EQUALVERIFY 1 EQUAL"], +["1 2 ", "2 EQUALVERIFY 1 EQUAL"], +[" 1 2 ", "2 EQUALVERIFY 1 EQUAL"], + +["1", ""], + ["0x01 0x0b", "11 EQUAL", "push 1 byte"], ["0x02 0x417a", "'Az' EQUAL"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index dd1b613047..f9ca65653b 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -63,7 +63,11 @@ ParseScript(string s) BOOST_FOREACH(string w, words) { - if (all(w, is_digit()) || + if (w.size() == 0) + { + // Empty string, ignore. (boost::split given '' will return one word) + } + else if (all(w, is_digit()) || (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) { // Number From d3a33fc869d23fb13c010a6e9995bdf6574a621e Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 12 Mar 2014 21:18:07 -0400 Subject: [PATCH 003/336] Test CHECKMULTISIG with m == 0 and n == 0 --- src/test/data/script_invalid.json | 16 ++++++++ src/test/data/script_valid.json | 64 +++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 609c89be06..c2824cb6f7 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -331,6 +331,22 @@ ["NOP", "HASH160 1"], ["NOP", "HASH256 1"], +["", +"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"202 CHECKMULTISIGS, fails due to 201 op limit"], + +["1", +"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY"], + +["", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"Fails due to 201 sig op limit"], + +["1", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], + + + ["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], ["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index c50767071a..162e5c3abd 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -414,6 +414,70 @@ ["NOP", "NOP9 1"], ["NOP", "NOP10 1"], +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"], +["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"], +["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Test from up to 20 pubkeys, all not checked"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], +["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"], + +["", +"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG", +"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"], + +["1", +"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY"], + +["", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG", +"Even though there are no signatures being checked nOpCount is incremented by the number of keys."], + +["1", +"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY"], + ["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], ["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], From 75ebced4992aab97b63c1a0842faf7dc37b86768 Mon Sep 17 00:00:00 2001 From: Alon Muroch Date: Mon, 10 Mar 2014 19:23:19 +0100 Subject: [PATCH 004/336] added many rpc wallet tests deleted the empty no throw test in rpc_wallet_tests line 65 fixed some comments starting verify tests finished verify message tests changed some comments --- src/test/rpc_wallet_tests.cpp | 87 +++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index af34e496e2..ac6d8ad8f0 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -67,6 +67,31 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) LOCK(pwalletMain->cs_wallet); + CPubKey demoPubkey = pwalletMain->GenerateNewKey(); + CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); + Value retValue; + string strAccount = "walletDemoAccount"; + string strPurpose = "receive"; + BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ + CWalletDB walletdb(pwalletMain->strWalletFile); + CAccount account; + account.vchPubKey = demoPubkey; + pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose); + walletdb.WriteAccount(strAccount, account); + }); + + + /********************************* + * setaccount + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount")); + BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error); + /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */ + BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error); + + /********************************* + * listunspent + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listunspent")); BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error); BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error); @@ -75,6 +100,9 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []")); BOOST_CHECK(r.get_array().empty()); + /********************************* + * listreceivedbyaddress + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error); @@ -82,12 +110,71 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error); + /********************************* + * listreceivedbyaccount + *********************************/ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount")); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error); BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error); BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true")); BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error); + + /********************************* + * getrawchangeaddress + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress")); + + /********************************* + * getnewaddress + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("getnewaddress")); + BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount")); + + /********************************* + * getaccountaddress + *********************************/ + BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\"")); + BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount)); + BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get()); + + /********************************* + * getaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error); + BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString())); + + /********************************* + * signmessage + verifymessage + *********************************/ + BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage")); + BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error); + /* Should throw error because this address is not loaded in the wallet */ + BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error); + + /* missing arguments */ + BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString()), runtime_error); + BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str()), runtime_error); + /* Illegal address */ + BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error); + /* wrong address */ + BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false); + /* Correct address and signature but wrong message */ + BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false); + /* Correct address, message and signature*/ + BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true); + + /********************************* + * getaddressesbyaccount + *********************************/ + BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); + BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); + Array arr = retValue.get_array(); + BOOST_CHECK(arr.size() > 0); + BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); + } + BOOST_AUTO_TEST_SUITE_END() From 3f9a01995e8d43c492eba8e1a08571705bceaef1 Mon Sep 17 00:00:00 2001 From: Alon Muroch Date: Tue, 25 Mar 2014 14:33:44 +0100 Subject: [PATCH 005/336] added list/get received by address/ account tests fixed some annotations and cleaned a bit received by tests d --- qa/rpc-tests/receivedby.py | 225 +++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100755 qa/rpc-tests/receivedby.py diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py new file mode 100755 index 0000000000..7f2d79b3c1 --- /dev/null +++ b/qa/rpc-tests/receivedby.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Exercise the listtransactions API + +# Add python-bitcoinrpc to module search path: + +import os +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc")) + +import json +import shutil +import subprocess +import tempfile +import traceback + +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * + +def get_sub_array_from_array(object_array, to_match): + ''' + Finds and returns a sub array from an array of arrays. + to_match should be a unique idetifier of a sub array + ''' + num_matched = 0 + for item in object_array: + all_match = True + for key,value in to_match.items(): + if item[key] != value: + all_match = False + if not all_match: + continue + return item + return [] + +def check_array_result(object_array, to_match, expected, should_not_find = False): + """ + Pass in array of JSON objects, a dictionary with key/value pairs + to match against, and another dictionary with expected key/value + pairs. + If the should_not_find flag is true, to_match should not be found in object_array + """ + if should_not_find == True: + expected = { } + num_matched = 0 + for item in object_array: + all_match = True + for key,value in to_match.items(): + if item[key] != value: + all_match = False + if not all_match: + continue + for key,value in expected.items(): + if item[key] != value: + raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value))) + num_matched = num_matched+1 + if num_matched == 0 and should_not_find != True: + raise AssertionError("No objects matched %s"%(str(to_match))) + if num_matched > 0 and should_not_find == True: + raise AssertionError("Objects was matched %s"%(str(to_match))) + +def run_test(nodes): + ''' + listreceivedbyaddress Test + ''' + # Send from node 0 to 1 + addr = nodes[1].getnewaddress() + txid = nodes[0].sendtoaddress(addr, 0.1) + sync_mempools(nodes) + + #Check not listed in listreceivedbyaddress because has 0 confirmations + check_array_result(nodes[1].listreceivedbyaddress(), + {"address":addr}, + { }, + True) + #Bury Tx under 10 block so it will be returned by listreceivedbyaddress + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + check_array_result(nodes[1].listreceivedbyaddress(), + {"address":addr}, + {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) + #With min confidence < 10 + check_array_result(nodes[1].listreceivedbyaddress(5), + {"address":addr}, + {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}) + #With min confidence > 10, should not find Tx + check_array_result(nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True) + + #Empty Tx + addr = nodes[1].getnewaddress() + check_array_result(nodes[1].listreceivedbyaddress(0,True), + {"address":addr}, + {"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]}) + + ''' + getreceivedbyaddress Test + ''' + # Send from node 0 to 1 + addr = nodes[1].getnewaddress() + txid = nodes[0].sendtoaddress(addr, 0.1) + sync_mempools(nodes) + + #Check balance is 0 because of 0 confirmations + balance = nodes[1].getreceivedbyaddress(addr) + if balance != Decimal("0.0"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + #Check balance is 0.1 + balance = nodes[1].getreceivedbyaddress(addr,0) + if balance != Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + #Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + balance = nodes[1].getreceivedbyaddress(addr) + if balance != Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance)) + + ''' + listreceivedbyaccount + getreceivedbyaccount Test + ''' + #set pre-state + addrArr = nodes[1].getnewaddress() + account = nodes[1].getaccount(addrArr) + received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account}) + if len(received_by_account_json) == 0: + raise AssertionError("No accounts found in node") + balance_by_account = rec_by_accountArr = nodes[1].getreceivedbyaccount(account) + + txid = nodes[0].sendtoaddress(addr, 0.1) + + # listreceivedbyaccount should return received_by_account_json because of 0 confirmations + check_array_result(nodes[1].listreceivedbyaccount(), + {"account":account}, + received_by_account_json) + + # getreceivedbyaddress should return same balance because of 0 confirmations + balance = nodes[1].getreceivedbyaccount(account) + if balance != balance_by_account: + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + + nodes[1].setgenerate(True, 10) + sync_blocks(nodes) + # listreceivedbyaccount should return updated account balance + check_array_result(nodes[1].listreceivedbyaccount(), + {"account":account}, + {"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))}) + + # getreceivedbyaddress should return updates balance + balance = nodes[1].getreceivedbyaccount(account) + if balance != balance_by_account + Decimal("0.1"): + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + + #Create a new account named "mynewaccount" that has a 0 balance + nodes[1].getaccountaddress("mynewaccount") + received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"}) + if len(received_by_account_json) == 0: + raise AssertionError("No accounts found in node") + + # Test includeempty of listreceivedbyaccount + if received_by_account_json["amount"] != Decimal("0.0"): + raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"])) + + # Test getreceivedbyaccount for 0 amount accounts + balance = nodes[1].getreceivedbyaccount("mynewaccount") + if balance != Decimal("0.0"): + raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance)) + +def main(): + import optparse + + parser = optparse.OptionParser(usage="%prog [options]") + parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", + help="Leave bitcoinds and test.* datadir on exit or error") + parser.add_option("--srcdir", dest="srcdir", default="../../src", + help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") + parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), + help="Root directory for datadirs") + (options, args) = parser.parse_args() + + os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] + + check_json_precision() + + success = False + nodes = [] + try: + print("Initializing test directory "+options.tmpdir) + if not os.path.isdir(options.tmpdir): + os.makedirs(options.tmpdir) + initialize_chain(options.tmpdir) + + nodes = start_nodes(2, options.tmpdir) + connect_nodes(nodes[1], 0) + sync_blocks(nodes) + + run_test(nodes) + + success = True + + except AssertionError as e: + print("Assertion failed: "+e.message) + except Exception as e: + print("Unexpected exception caught during testing: "+str(e)) + traceback.print_tb(sys.exc_info()[2]) + + if not options.nocleanup: + print("Cleaning up") + stop_nodes(nodes) + wait_bitcoinds() + shutil.rmtree(options.tmpdir) + + if success: + print("Tests successful") + sys.exit(0) + else: + print("Failed") + sys.exit(1) + +if __name__ == '__main__': + main() From 48d8eb1847d4218ee24ec1c27c73b90e03b1f007 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 26 Mar 2014 15:50:29 -0400 Subject: [PATCH 006/336] script: add CScriptNum class This class holds an int64_t and replaces the use of CBigInt for script integrals. --- src/script.h | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/src/script.h b/src/script.h index 657ac0b388..9bc06b2e07 100644 --- a/src/script.h +++ b/src/script.h @@ -25,6 +25,155 @@ class CTransaction; static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes +class scriptnum_error : public std::runtime_error +{ +public: + explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {} +}; + +class CScriptNum +{ +// Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. +// The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], +// but results may overflow (and are valid as long as they are not used in a subsequent +// numeric operation). CScriptNum enforces those semantics by storing results as +// an int64 and allowing out-of-range values to be returned as a vector of bytes but +// throwing an exception if arithmetic is done or the result is interpreted as an integer. +public: + + explicit CScriptNum(const int64_t& n) + { + m_value = n; + } + + explicit CScriptNum(const std::vector& vch) + { + if (vch.size() > nMaxNumSize) + throw scriptnum_error("CScriptNum(const std::vector&) : overflow"); + m_value = set_vch(vch); + } + + inline bool operator==(const int64_t& rhs) const { return m_value == rhs; } + inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; } + inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; } + inline bool operator< (const int64_t& rhs) const { return m_value < rhs; } + inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; } + inline bool operator> (const int64_t& rhs) const { return m_value > rhs; } + + inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); } + inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); } + inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); } + inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); } + inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); } + inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); } + + inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);} + inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);} + inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); } + inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); } + + inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); } + inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); } + + inline CScriptNum operator-() const + { + assert(m_value != std::numeric_limits::min()); + return CScriptNum(-m_value); + } + + inline CScriptNum& operator=( const int64_t& rhs) + { + m_value = rhs; + return *this; + } + + inline CScriptNum& operator+=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits::max() - rhs) || + (rhs < 0 && m_value >= std::numeric_limits::min() - rhs)); + m_value += rhs; + return *this; + } + + inline CScriptNum& operator-=( const int64_t& rhs) + { + assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits::min() + rhs) || + (rhs < 0 && m_value <= std::numeric_limits::max() + rhs)); + m_value -= rhs; + return *this; + } + + int getint() const + { + if (m_value > std::numeric_limits::max()) + return std::numeric_limits::max(); + else if (m_value < std::numeric_limits::min()) + return std::numeric_limits::min(); + return m_value; + } + + std::vector getvch() const + { + return serialize(m_value); + } + + static std::vector serialize(const int64_t& value) + { + if(value == 0) + return std::vector(); + + std::vector result; + const bool neg = value < 0; + uint64_t absvalue = neg ? -value : value; + + while(absvalue) + { + result.push_back(absvalue & 0xff); + absvalue >>= 8; + } + + +// - If the most significant byte is >= 0x80 and the value is positive, push a +// new zero-byte to make the significant byte < 0x80 again. + +// - If the most significant byte is >= 0x80 and the value is negative, push a +// new 0x80 byte that will be popped off when converting to an integral. + +// - If the most significant byte is < 0x80 and the value is negative, add +// 0x80 to it, since it will be subtracted and interpreted as a negative when +// converting to an integral. + + if (result.back() & 0x80) + result.push_back(neg ? 0x80 : 0); + else if (neg) + result.back() |= 0x80; + + return result; + } + + static const size_t nMaxNumSize = 4; + +private: + static int64_t set_vch(const std::vector& vch) + { + if (vch.empty()) + return 0; + + int64_t result = 0; + for (size_t i = 0; i != vch.size(); ++i) + result |= static_cast(vch[i]) << 8*i; + + // If the input vector's most significant byte is 0x80, remove it from + // the result's msb and return a negative. + if (vch.back() & 0x80) + return -(result & ~(0x80 << (8 * (vch.size() - 1)))); + + return result; + } + + int64_t m_value; +}; + /** Signature hash types/flags */ enum { From 27bff74e39c4c2951a709114e0d565568a0554fa Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 26 Mar 2014 15:55:35 -0400 Subject: [PATCH 007/336] script: switch to CScriptNum usage for scripts --- src/script.cpp | 44 +++++++++++++++++-------------------------- src/script.h | 51 +++++++++++--------------------------------------- 2 files changed, 28 insertions(+), 67 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index 810ba16d28..25180e0bbb 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -25,22 +25,13 @@ typedef vector valtype; static const valtype vchFalse(0); static const valtype vchZero(0); static const valtype vchTrue(1, 1); -static const CBigNum bnZero(0); -static const CBigNum bnOne(1); -static const CBigNum bnFalse(0); -static const CBigNum bnTrue(1); -static const size_t nMaxNumSize = 4; +static const CScriptNum bnZero(0); +static const CScriptNum bnOne(1); +static const CScriptNum bnFalse(0); +static const CScriptNum bnTrue(1); bool CheckSig(vector vchSig, const vector &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags); -CBigNum CastToBigNum(const valtype& vch) -{ - if (vch.size() > nMaxNumSize) - throw runtime_error("CastToBigNum() : overflow"); - // Get rid of extra leading zeros - return CBigNum(CBigNum(vch).getvch()); -} - bool CastToBool(const valtype& vch) { for (unsigned int i = 0; i < vch.size(); i++) @@ -306,7 +297,6 @@ bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { bool EvalScript(vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) { - CAutoBN_CTX pctx; CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); @@ -380,7 +370,7 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_16: { // ( -- value) - CBigNum bn((int)opcode - (int)(OP_1 - 1)); + CScriptNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); } break; @@ -556,7 +546,7 @@ bool EvalScript(vector >& stack, const CScript& script, co case OP_DEPTH: { // -- stacksize - CBigNum bn(stack.size()); + CScriptNum bn(stack.size()); stack.push_back(bn.getvch()); } break; @@ -606,7 +596,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return false; - int n = CastToBigNum(stacktop(-1)).getint(); + int n = CScriptNum(stacktop(-1)).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) return false; @@ -654,7 +644,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (in -- in size) if (stack.size() < 1) return false; - CBigNum bn(stacktop(-1).size()); + CScriptNum bn(stacktop(-1).size()); stack.push_back(bn.getvch()); } break; @@ -705,7 +695,7 @@ bool EvalScript(vector >& stack, const CScript& script, co // (in -- out) if (stack.size() < 1) return false; - CBigNum bn = CastToBigNum(stacktop(-1)); + CScriptNum bn(stacktop(-1)); switch (opcode) { case OP_1ADD: bn += bnOne; break; @@ -738,9 +728,9 @@ bool EvalScript(vector >& stack, const CScript& script, co // (x1 x2 -- out) if (stack.size() < 2) return false; - CBigNum bn1 = CastToBigNum(stacktop(-2)); - CBigNum bn2 = CastToBigNum(stacktop(-1)); - CBigNum bn; + CScriptNum bn1(stacktop(-2)); + CScriptNum bn2(stacktop(-1)); + CScriptNum bn(0); switch (opcode) { case OP_ADD: @@ -783,9 +773,9 @@ bool EvalScript(vector >& stack, const CScript& script, co // (x min max -- out) if (stack.size() < 3) return false; - CBigNum bn1 = CastToBigNum(stacktop(-3)); - CBigNum bn2 = CastToBigNum(stacktop(-2)); - CBigNum bn3 = CastToBigNum(stacktop(-1)); + CScriptNum bn1(stacktop(-3)); + CScriptNum bn2(stacktop(-2)); + CScriptNum bn3(stacktop(-1)); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); @@ -882,7 +872,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if ((int)stack.size() < i) return false; - int nKeysCount = CastToBigNum(stacktop(-i)).getint(); + int nKeysCount = CScriptNum(stacktop(-i)).getint(); if (nKeysCount < 0 || nKeysCount > 20) return false; nOpCount += nKeysCount; @@ -893,7 +883,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if ((int)stack.size() < i) return false; - int nSigsCount = CastToBigNum(stacktop(-i)).getint(); + int nSigsCount = CScriptNum(stacktop(-i)).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return false; int isig = ++i; diff --git a/src/script.h b/src/script.h index 9bc06b2e07..7781ea61c7 100644 --- a/src/script.h +++ b/src/script.h @@ -374,7 +374,7 @@ const char* GetOpName(opcodetype opcode); inline std::string ValueString(const std::vector& vch) { if (vch.size() <= 4) - return strprintf("%d", CBigNum(vch).getint()); + return strprintf("%d", CScriptNum(vch).getint()); else return HexStr(vch); } @@ -410,26 +410,10 @@ protected: } else { - CBigNum bn(n); - *this << bn.getvch(); + *this << CScriptNum::serialize(n); } return *this; } - - CScript& push_uint64(uint64_t n) - { - if (n >= 1 && n <= 16) - { - push_back(n + (OP_1 - 1)); - } - else - { - CBigNum bn(n); - *this << bn.getvch(); - } - return *this; - } - public: CScript() { } CScript(const CScript& b) : std::vector(b.begin(), b.end()) { } @@ -452,35 +436,16 @@ public: } - //explicit CScript(char b) is not portable. Use 'signed char' or 'unsigned char'. - explicit CScript(signed char b) { operator<<(b); } - explicit CScript(short b) { operator<<(b); } - explicit CScript(int b) { operator<<(b); } - explicit CScript(long b) { operator<<(b); } - explicit CScript(long long b) { operator<<(b); } - explicit CScript(unsigned char b) { operator<<(b); } - explicit CScript(unsigned int b) { operator<<(b); } - explicit CScript(unsigned short b) { operator<<(b); } - explicit CScript(unsigned long b) { operator<<(b); } - explicit CScript(unsigned long long b) { operator<<(b); } + CScript(int64_t b) { operator<<(b); } explicit CScript(opcodetype b) { operator<<(b); } explicit CScript(const uint256& b) { operator<<(b); } + explicit CScript(const CScriptNum& b) { operator<<(b); } explicit CScript(const CBigNum& b) { operator<<(b); } explicit CScript(const std::vector& b) { operator<<(b); } - //CScript& operator<<(char b) is not portable. Use 'signed char' or 'unsigned char'. - CScript& operator<<(signed char b) { return push_int64(b); } - CScript& operator<<(short b) { return push_int64(b); } - CScript& operator<<(int b) { return push_int64(b); } - CScript& operator<<(long b) { return push_int64(b); } - CScript& operator<<(long long b) { return push_int64(b); } - CScript& operator<<(unsigned char b) { return push_uint64(b); } - CScript& operator<<(unsigned int b) { return push_uint64(b); } - CScript& operator<<(unsigned short b) { return push_uint64(b); } - CScript& operator<<(unsigned long b) { return push_uint64(b); } - CScript& operator<<(unsigned long long b) { return push_uint64(b); } + CScript& operator<<(int64_t b) { return push_int64(b); } CScript& operator<<(opcodetype opcode) { @@ -518,6 +483,12 @@ public: return *this; } + CScript& operator<<(const CScriptNum& b) + { + *this << b.getvch(); + return *this; + } + CScript& operator<<(const std::vector& b) { if (b.size() < OP_PUSHDATA1) From 4f497cd97da4f9c88790a5f4e97926804669dfca Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 26 Mar 2014 15:56:45 -0400 Subject: [PATCH 008/336] script: switch outside users to CScriptNum --- src/chainparams.cpp | 2 +- src/miner.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b52774ee20..eb56800b92 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -125,7 +125,7 @@ public: CTransaction txNew; txNew.vin.resize(1); txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = 50 * COIN; txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; genesis.vtx.push_back(txNew); diff --git a/src/miner.cpp b/src/miner.cpp index 3351908e65..f21ee0c3a8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -355,7 +355,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& } ++nExtraNonce; unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 - pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS; + pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); From 05e3ecffa495c0905b88cfc92b23bb519b7fe70b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 26 Mar 2014 15:57:21 -0400 Subject: [PATCH 009/336] script: remove bignum dependency --- src/script.cpp | 1 - src/script.h | 8 -------- 2 files changed, 9 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index 25180e0bbb..81d2754453 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -5,7 +5,6 @@ #include "script.h" -#include "bignum.h" #include "core.h" #include "hash.h" #include "key.h" diff --git a/src/script.h b/src/script.h index 7781ea61c7..1742ce81f8 100644 --- a/src/script.h +++ b/src/script.h @@ -6,7 +6,6 @@ #ifndef H_BITCOIN_SCRIPT #define H_BITCOIN_SCRIPT -#include "bignum.h" #include "key.h" #include "util.h" @@ -441,7 +440,6 @@ public: explicit CScript(opcodetype b) { operator<<(b); } explicit CScript(const uint256& b) { operator<<(b); } explicit CScript(const CScriptNum& b) { operator<<(b); } - explicit CScript(const CBigNum& b) { operator<<(b); } explicit CScript(const std::vector& b) { operator<<(b); } @@ -477,12 +475,6 @@ public: return *this; } - CScript& operator<<(const CBigNum& b) - { - *this << b.getvch(); - return *this; - } - CScript& operator<<(const CScriptNum& b) { *this << b.getvch(); From 90320d67779be5c97061380c035d3fe51b7ce74b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 22 Apr 2014 00:10:33 -0400 Subject: [PATCH 010/336] script: add additional script tests --- src/test/data/script_invalid.json | 3 +++ src/test/data/script_valid.json | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 8cb365a46f..fdceb1ffa9 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -257,7 +257,10 @@ ["1","0xba", "0xba == OP_NOP10 + 1"], ["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], +["2147483648", "NEGATE 1", "We cannot do math on 5-byte integers"], ["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], +["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], +["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"], ["1", "1 ENDIF", "ENDIF without IF"], ["1", "IF 1", "IF without ENDIF"], diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 3b4c191865..67b985e355 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -97,6 +97,9 @@ ["8388608", "SIZE 4 EQUAL"], ["2147483647", "SIZE 4 EQUAL"], ["2147483648", "SIZE 5 EQUAL"], +["549755813887", "SIZE 5 EQUAL"], +["549755813888", "SIZE 6 EQUAL"], +["9223372036854775807", "SIZE 8 EQUAL"], ["-1", "SIZE 1 EQUAL"], ["-127", "SIZE 1 EQUAL"], ["-128", "SIZE 2 EQUAL"], @@ -106,6 +109,9 @@ ["-8388608", "SIZE 4 EQUAL"], ["-2147483647", "SIZE 4 EQUAL"], ["-2147483648", "SIZE 5 EQUAL"], +["-549755813887", "SIZE 5 EQUAL"], +["-549755813888", "SIZE 6 EQUAL"], +["-9223372036854775807", "SIZE 8 EQUAL"], ["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], @@ -306,6 +312,9 @@ ["8388608", "0x04 0x00008000 EQUAL"], ["2147483647", "0x04 0xFFFFFF7F EQUAL"], ["2147483648", "0x05 0x0000008000 EQUAL"], +["549755813887", "0x05 0xFFFFFFFF7F EQUAL"], +["549755813888", "0x06 0xFFFFFFFF7F EQUAL"], +["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL"], ["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], ["-127", "0x01 0xFF EQUAL"], ["-128", "0x02 0x8080 EQUAL"], @@ -315,6 +324,10 @@ ["-8388608", "0x04 0x00008080 EQUAL"], ["-2147483647", "0x04 0xFFFFFFFF EQUAL"], ["-2147483648", "0x05 0x0000008080 EQUAL"], +["-4294967295", "0x05 0xFFFFFFFF80 EQUAL"], +["-549755813887", "0x05 0xFFFFFFFFFF EQUAL"], +["-549755813888", "0x06 0x000000008080 EQUAL"], +["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL"], ["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], ["2147483647", "1ADD 1"], From b1fdd5475d9040445d7655730f262f214ea87c5f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 22 Apr 2014 00:11:39 -0400 Subject: [PATCH 011/336] script: Add test for CScriptNum Because this class replaces some usages of CBigNum, tests have been added to verify that they function the same way. The only difference in their usage is the handling of out-of-range numbers. While operands are constrained to [-0x7FFFFFFF,0x7FFFFFFF], the results may overflow. The overflowing result is technically unbounded, but in practice it can be no bigger than the result of an operation on two operands. This implementation limits them to the size of an int64. CBigNum was unaware of this constraint, so it allowed for unbounded results, which were then checked before use. CScriptNum asserts if an arithmetic operation will overflow an int64_t, since scripts are not able to reach those numbers anyway. Additionally, CScriptNum will throw an exception when constructed from a vector containing more than 4 bytes This mimics the previous CastToBigNum behavior. --- src/test/Makefile.am | 1 + src/test/scriptnum_tests.cpp | 196 +++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 src/test/scriptnum_tests.cpp diff --git a/src/test/Makefile.am b/src/test/Makefile.am index b375ba1306..e12f4904f1 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -61,6 +61,7 @@ test_bitcoin_SOURCES = \ transaction_tests.cpp \ uint256_tests.cpp \ util_tests.cpp \ + scriptnum_tests.cpp \ sighash_tests.cpp \ $(JSON_TEST_FILES) $(RAW_TEST_FILES) diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp new file mode 100644 index 0000000000..cd194cc4d9 --- /dev/null +++ b/src/test/scriptnum_tests.cpp @@ -0,0 +1,196 @@ +// Copyright (c) 2012-2014 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bignum.h" +#include "script.h" +#include +#include +#include +BOOST_AUTO_TEST_SUITE(scriptnum_tests) + +static const int64_t values[] = \ +{ 0, 1, CHAR_MIN, CHAR_MAX, UCHAR_MAX, SHRT_MIN, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX, LONG_MIN, LONG_MAX }; +static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000}; + +static bool verify(const CBigNum& bignum, const CScriptNum& scriptnum) +{ + return bignum.getvch() == scriptnum.getvch() && bignum.getint() == scriptnum.getint(); +} + +static void CheckCreateVch(const int64_t& num) +{ + CBigNum bignum(num); + CScriptNum scriptnum(num); + BOOST_CHECK(verify(bignum, scriptnum)); + + CBigNum bignum2(bignum.getvch()); + CScriptNum scriptnum2(scriptnum.getvch()); + BOOST_CHECK(verify(bignum2, scriptnum2)); + + CBigNum bignum3(scriptnum2.getvch()); + CScriptNum scriptnum3(bignum2.getvch()); + BOOST_CHECK(verify(bignum3, scriptnum3)); +} + +static void CheckCreateInt(const int64_t& num) +{ + CBigNum bignum(num); + CScriptNum scriptnum(num); + BOOST_CHECK(verify(bignum, scriptnum)); + BOOST_CHECK(verify(bignum.getint(), CScriptNum(scriptnum.getint()))); + BOOST_CHECK(verify(scriptnum.getint(), CScriptNum(bignum.getint()))); + BOOST_CHECK(verify(CBigNum(scriptnum.getint()).getint(), CScriptNum(CScriptNum(bignum.getint()).getint()))); +} + + +static void CheckAdd(const int64_t& num1, const int64_t& num2) +{ + const CBigNum bignum1(num1); + const CBigNum bignum2(num2); + const CScriptNum scriptnum1(num1); + const CScriptNum scriptnum2(num2); + CBigNum bignum3(num1); + CBigNum bignum4(num1); + CScriptNum scriptnum3(num1); + CScriptNum scriptnum4(num1); + + // int64_t overflow is undefined. + bool invalid = (((num2 > 0) && (num1 > (std::numeric_limits::max() - num2))) || + ((num2 < 0) && (num1 < (std::numeric_limits::min() - num2)))); + if (!invalid) + { + BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + scriptnum2)); + BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + num2)); + BOOST_CHECK(verify(bignum1 + bignum2, scriptnum2 + num1)); + } +} + +static void CheckNegate(const int64_t& num) +{ + const CBigNum bignum(num); + const CScriptNum scriptnum(num); + + // -INT64_MIN is undefined + if (num != std::numeric_limits::min()) + BOOST_CHECK(verify(-bignum, -scriptnum)); +} + +static void CheckSubtract(const int64_t& num1, const int64_t& num2) +{ + const CBigNum bignum1(num1); + const CBigNum bignum2(num2); + const CScriptNum scriptnum1(num1); + const CScriptNum scriptnum2(num2); + bool invalid = false; + + // int64_t overflow is undefined. + invalid = ((num2 > 0 && num1 < std::numeric_limits::min() + num2) || + (num2 < 0 && num1 > std::numeric_limits::max() + num2)); + if (!invalid) + { + BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - scriptnum2)); + BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - num2)); + } + + invalid = ((num1 > 0 && num2 < std::numeric_limits::min() + num1) || + (num1 < 0 && num2 > std::numeric_limits::max() + num1)); + if (!invalid) + { + BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - scriptnum1)); + BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - num1)); + } +} + +static void CheckCompare(const int64_t& num1, const int64_t& num2) +{ + const CBigNum bignum1(num1); + const CBigNum bignum2(num2); + const CScriptNum scriptnum1(num1); + const CScriptNum scriptnum2(num2); + + BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == scriptnum1)); + BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != scriptnum1)); + BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < scriptnum1)); + BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > scriptnum1)); + BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= scriptnum1)); + BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= scriptnum1)); + + BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == num1)); + BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != num1)); + BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < num1)); + BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > num1)); + BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= num1)); + BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= num1)); + + BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == scriptnum2)); + BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != scriptnum2)); + BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < scriptnum2)); + BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > scriptnum2)); + BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= scriptnum2)); + BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= scriptnum2)); + + BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == num2)); + BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != num2)); + BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < num2)); + BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > num2)); + BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= num2)); + BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= num2)); +} + +static void RunCreate(const int64_t& num) +{ + CheckCreateInt(num); + CScriptNum scriptnum(num); + if (scriptnum.getvch().size() <= CScriptNum::nMaxNumSize) + CheckCreateVch(num); + else + { + BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum_error); + } +} + +static void RunOperators(const int64_t& num1, const int64_t& num2) +{ + CheckAdd(num1, num2); + CheckSubtract(num1, num2); + CheckNegate(num1); + CheckCompare(num1, num2); +} + +BOOST_AUTO_TEST_CASE(creation) +{ + for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) + { + for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j) + { + RunCreate(values[i]); + RunCreate(values[i] + offsets[j]); + RunCreate(values[i] - offsets[j]); + } + } +} + +BOOST_AUTO_TEST_CASE(operators) +{ + for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) + { + for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j) + { + RunOperators(values[i], values[i]); + RunOperators(values[i], -values[i]); + RunOperators(values[i], values[j]); + RunOperators(values[i], -values[j]); + RunOperators(values[i] + values[j], values[j]); + RunOperators(values[i] + values[j], -values[j]); + RunOperators(values[i] - values[j], values[j]); + RunOperators(values[i] - values[j], -values[j]); + RunOperators(values[i] + values[j], values[i] + values[j]); + RunOperators(values[i] + values[j], values[i] - values[j]); + RunOperators(values[i] - values[j], values[i] + values[j]); + RunOperators(values[i] - values[j], values[i] - values[j]); + } + } +} + +BOOST_AUTO_TEST_SUITE_END() From f457347053029d6a0248036a1ffeb7127108fd6d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 11 Mar 2014 17:36:21 +0100 Subject: [PATCH 012/336] Split up CheckBlock in a block and header version --- src/main.cpp | 26 +++++++++++++++++--------- src/main.h | 1 + 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7a6d4b39de..66800cc224 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2288,16 +2288,8 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne } -bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot) +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) { - // These are checks that are independent of context - // that can be verified before saving an orphan block. - - // Size limits - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) - return state.DoS(100, error("CheckBlock() : size limits failed"), - REJECT_INVALID, "bad-blk-length"); - // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) return state.DoS(50, error("CheckBlock() : proof of work failed"), @@ -2308,6 +2300,22 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo return state.Invalid(error("CheckBlock() : block timestamp too far in the future"), REJECT_INVALID, "time-too-new"); + return true; +} + +bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot) +{ + // These are checks that are independent of context + // that can be verified before saving an orphan block. + + if (!CheckBlockHeader(block, state, fCheckPOW)) + return false; + + // Size limits + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE) + return state.DoS(100, error("CheckBlock() : size limits failed"), + REJECT_INVALID, "bad-blk-length"); + // First transaction must be coinbase, the rest must not be if (block.vtx.empty() || !block.vtx[0].IsCoinBase()) return state.DoS(100, error("CheckBlock() : first tx is not coinbase"), diff --git a/src/main.h b/src/main.h index aff20d0379..8e3f1d95ce 100644 --- a/src/main.h +++ b/src/main.h @@ -603,6 +603,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos); // Context-independent validity checks +bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); // Store block on disk From 942b33a19d3aa96326acc044c1834c48beff777c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Mar 2014 03:48:27 +0100 Subject: [PATCH 013/336] Split AcceptBlockHeader from AcceptBlock. Also modify some connection logic to deal with non-full blocks in the index. --- src/main.cpp | 200 +++++++++++++++++++++++++++++++++++---------------- src/main.h | 26 ++++++- 2 files changed, 162 insertions(+), 64 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 66800cc224..05f13dfda6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1849,8 +1849,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C if (fJustCheck) return true; + // Correct transaction counts. + pindex->nTx = block.vtx.size(); + if (pindex->pprev) + pindex->nChainTx = pindex->pprev->nChainTx + block.vtx.size(); + // Write undo information to disk - if (pindex->GetUndoPos().IsNull() || (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) + if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) { CDiskBlockPos pos; @@ -1864,7 +1869,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C pindex->nStatus |= BLOCK_HAVE_UNDO; } - pindex->nStatus = (pindex->nStatus & ~BLOCK_VALID_MASK) | BLOCK_VALID_SCRIPTS; + pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); CDiskBlockIndex blockindex(pindex); if (!pblocktree->WriteBlockIndex(blockindex)) @@ -2058,10 +2063,11 @@ void static FindMostWorkChain() { CBlockIndex *pindexTest = pindexNew; bool fInvalidAncestor = false; while (pindexTest && !chainActive.Contains(pindexTest)) { - if (pindexTest->nStatus & BLOCK_FAILED_MASK) { + if (!pindexTest->IsValid(BLOCK_VALID_TRANSACTIONS) || !(pindexTest->nStatus & BLOCK_HAVE_DATA)) { // Candidate has an invalid ancestor, remove entire chain from the set. if (pindexBestInvalid == NULL || pindexNew->nChainWork > pindexBestInvalid->nChainWork) - pindexBestInvalid = pindexNew; CBlockIndex *pindexFailed = pindexNew; + pindexBestInvalid = pindexNew; + CBlockIndex *pindexFailed = pindexNew; while (pindexTest != pindexFailed) { pindexFailed->nStatus |= BLOCK_FAILED_CHILD; setBlockIndexValid.erase(pindexFailed); @@ -2135,12 +2141,14 @@ bool ActivateBestChain(CValidationState &state) { return true; } -bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos) + +CBlockIndex* AddToBlockIndex(CBlockHeader& block) { // Check for duplicate uint256 hash = block.GetHash(); - if (mapBlockIndex.count(hash)) - return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString()), 0, "duplicate"); + std::map::iterator it = mapBlockIndex.find(hash); + if (it != mapBlockIndex.end()) + return it->second; // Construct new block index object CBlockIndex* pindexNew = new CBlockIndex(block); @@ -2157,14 +2165,38 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos pindexNew->pprev = (*miPrev).second; pindexNew->nHeight = pindexNew->pprev->nHeight + 1; } - pindexNew->nTx = block.vtx.size(); pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256(); - pindexNew->nChainTx = (pindexNew->pprev ? pindexNew->pprev->nChainTx : 0) + pindexNew->nTx; + pindexNew->RaiseValidity(BLOCK_VALID_TREE); + + return pindexNew; +} + + +// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). +bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) +{ + pindexNew->nTx = block.vtx.size(); + if (pindexNew->pprev) { + // Not the genesis block. + if (pindexNew->pprev->nChainTx) { + // This parent's block's total number transactions is known, so compute outs. + pindexNew->nChainTx = pindexNew->pprev->nChainTx + pindexNew->nTx; + } else { + // The total number of transactions isn't known yet. + // We will compute it when the block is connected. + pindexNew->nChainTx = 0; + } + } else { + // Genesis block. + pindexNew->nChainTx = pindexNew->nTx; + } pindexNew->nFile = pos.nFile; pindexNew->nDataPos = pos.nPos; pindexNew->nUndoPos = 0; - pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA; - setBlockIndexValid.insert(pindexNew); + pindexNew->nStatus |= BLOCK_HAVE_DATA; + + if (pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS)) + setBlockIndexValid.insert(pindexNew); if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew))) return state.Abort(_("Failed to write block index")); @@ -2292,14 +2324,35 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f { // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) - return state.DoS(50, error("CheckBlock() : proof of work failed"), + return state.DoS(50, error("CheckBlockHeader() : proof of work failed"), REJECT_INVALID, "high-hash"); // Check timestamp if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) - return state.Invalid(error("CheckBlock() : block timestamp too far in the future"), + return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"), REJECT_INVALID, "time-too-new"); + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime; + if (deltaTime < 0) + { + return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), + REJECT_CHECKPOINT, "time-too-old"); + } + CBigNum bnNewBlock; + bnNewBlock.SetCompact(block.nBits); + CBigNum bnRequired; + bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); + if (bnNewBlock > bnRequired) + { + return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), + REJECT_INVALID, "bad-diffbits"); + } + } + return true; } @@ -2362,13 +2415,18 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo return true; } -bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp) +bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) { AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); - if (mapBlockIndex.count(hash)) - return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"), 0, "duplicate"); + std::map::iterator miSelf = mapBlockIndex.find(hash); + CBlockIndex *pindex = NULL; + if (miSelf != mapBlockIndex.end()) { + pindex = miSelf->second; + if (pindex->nStatus & BLOCK_FAILED_MASK) + return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); + } // Get prev block index CBlockIndex* pindexPrev = NULL; @@ -2390,12 +2448,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp) return state.Invalid(error("AcceptBlock() : block's timestamp is too early"), REJECT_INVALID, "time-too-old"); - // Check that all transactions are finalized - BOOST_FOREACH(const CTransaction& tx, block.vtx) - if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) - return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"), - REJECT_INVALID, "bad-txns-nonfinal"); - // Check that the block chain matches the known block chain up to a checkpoint if (!Checkpoints::CheckBlock(nHeight, hash)) return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight), @@ -2416,18 +2468,57 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp) REJECT_OBSOLETE, "bad-version"); } } - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - if (block.nVersion >= 2) + } + + if (pindex == NULL) + pindex = AddToBlockIndex(block); + + if (ppindex) + *ppindex = pindex; + + return true; +} + +bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp) +{ + AssertLockHeld(cs_main); + + CBlockIndex *&pindex = *ppindex; + + if (!AcceptBlockHeader(block, state, &pindex)) + return false; + + if (!CheckBlock(block, state)) { + if (state.Invalid() && !state.CorruptionPossible()) { + pindex->nStatus |= BLOCK_FAILED_VALID; + } + return false; + } + + int nHeight = pindex->nHeight; + uint256 hash = pindex->GetBlockHash(); + + // Check that all transactions are finalized + BOOST_FOREACH(const CTransaction& tx, block.vtx) + if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"), + REJECT_INVALID, "bad-txns-nonfinal"); + } + + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (block.nVersion >= 2) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) { - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100))) - { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || - !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) - return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), - REJECT_INVALID, "bad-cb-height"); + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), + REJECT_INVALID, "bad-cb-height"); } } } @@ -2443,8 +2534,8 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp) if (dbp == NULL) if (!WriteBlockToDisk(block, blockPos)) return state.Abort(_("Failed to write block")); - if (!AddToBlockIndex(block, state, blockPos)) - return error("AcceptBlock() : AddToBlockIndex failed"); + if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + return error("AcceptBlock() : ReceivedBlockTransactions failed"); } catch(std::runtime_error &e) { return state.Abort(_("System error: ") + e.what()); } @@ -2514,30 +2605,9 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl if (!CheckBlock(*pblock, state)) return error("ProcessBlock() : CheckBlock FAILED"); - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); - if (pcheckpoint && pblock->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) - { - // Extra checks to prevent "fill up memory by spamming with bogus blocks" - int64_t deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime; - if (deltaTime < 0) - { - return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint"), - REJECT_CHECKPOINT, "time-too-old"); - } - CBigNum bnNewBlock; - bnNewBlock.SetCompact(pblock->nBits); - CBigNum bnRequired; - bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); - if (bnNewBlock > bnRequired) - { - return state.DoS(100, error("ProcessBlock() : block with too little proof-of-work"), - REJECT_INVALID, "bad-diffbits"); - } - } - - - // If we don't already have its previous block, shunt it off to holding area until we get it - if (pblock->hashPrevBlock != 0 && !mapBlockIndex.count(pblock->hashPrevBlock)) + // If we don't already have its previous block (with full data), shunt it off to holding area until we get it + std::map::iterator it = mapBlockIndex.find(pblock->hashPrevBlock); + if (pblock->hashPrevBlock != 0 && (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA))) { LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString()); @@ -2562,7 +2632,9 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl } // Store to disk - if (!AcceptBlock(*pblock, state, dbp)) + CBlockIndex *pindex = NULL; + bool ret = AcceptBlock(*pblock, state, &pindex, dbp); + if (!ret) return error("ProcessBlock() : AcceptBlock FAILED"); // Recursively process any orphan blocks that depended on this one @@ -2583,7 +2655,8 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl block.BuildMerkleTree(); // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned) CValidationState stateDummy; - if (AcceptBlock(block, stateDummy)) + CBlockIndex *pindexChild = NULL; + if (AcceptBlock(block, stateDummy, &pindexChild)) vWorkQueue.push_back(mi->second->hashBlock); mapOrphanBlocks.erase(mi->second->hashBlock); delete mi->second; @@ -2846,7 +2919,7 @@ bool static LoadBlockIndexDB() CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork().getuint256(); pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; - if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS && !(pindex->nStatus & BLOCK_FAILED_MASK)) + if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) setBlockIndexValid.insert(pindex); if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork)) pindexBestInvalid = pindex; @@ -2993,7 +3066,8 @@ bool InitBlockIndex() { return error("LoadBlockIndex() : FindBlockPos failed"); if (!WriteBlockToDisk(block, blockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); - if (!AddToBlockIndex(block, state, blockPos)) + CBlockIndex *pindex = AddToBlockIndex(block); + if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("LoadBlockIndex() : genesis block not accepted"); } catch(std::runtime_error &e) { return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); diff --git a/src/main.h b/src/main.h index 8e3f1d95ce..77a6fbe9dc 100644 --- a/src/main.h +++ b/src/main.h @@ -608,7 +608,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = t // Store block on disk // if dbp is provided, the file is known to already reside on disk -bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp = NULL); +bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); +bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); @@ -866,6 +867,29 @@ public: { LogPrintf("%s\n", ToString().c_str()); } + + // Check whether this block index entry is valid up to the passed validity level. + bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); + } + + // Raise the validity level of this block index entry. + // Returns true if the validity was changed. + bool RaiseValidity(enum BlockStatus nUpTo) + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { + nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; + return true; + } + return false; + } }; From 68f7d1d7af39a8ea6510f888e8e058e8e8faa007 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 17:31:46 -0400 Subject: [PATCH 014/336] Create (MANDATORY|STANDARD)_SCRIPT_VERIFY_FLAGS constants --- src/main.cpp | 2 +- src/main.h | 2 +- src/miner.cpp | 5 ++++- src/rpcrawtransaction.cpp | 2 +- src/script.cpp | 2 +- src/script.h | 12 ++++++++++++ 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 40c713ce93..cee9d027f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -945,7 +945,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC)) + if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS)) { return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString()); } diff --git a/src/main.h b/src/main.h index 825e577d1e..470f158287 100644 --- a/src/main.h +++ b/src/main.h @@ -309,7 +309,7 @@ inline bool AllowFree(double dPriority) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline. bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &view, bool fScriptChecks = true, - unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, + unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS, std::vector *pvChecks = NULL); // Apply the effects of this transaction on the UTXO set represented by view diff --git a/src/miner.cpp b/src/miner.cpp index 3351908e65..12a5e7f845 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -276,8 +276,11 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; + // Note that flags: we don't want to set mempool/IsStandard() + // policy here, but we still have to ensure that the block we + // create only contains transactions that are valid in new blocks. CValidationState state; - if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS)) continue; CTxUndo txundo; diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 4b7dd617e0..70a5bdf29b 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -722,7 +722,7 @@ Value signrawtransaction(const Array& params, bool fHelp) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } - if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, 0)) + if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, STANDARD_SCRIPT_VERIFY_FLAGS, 0)) fComplete = false; } diff --git a/src/script.cpp b/src/script.cpp index 810ba16d28..dc0cd28bf8 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1670,7 +1670,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa } // Test solution - return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, 0); + return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0); } bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType) diff --git a/src/script.h b/src/script.h index 657ac0b388..0f26fb556d 100644 --- a/src/script.h +++ b/src/script.h @@ -44,6 +44,18 @@ enum SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it) }; +// Mandatory script verification flags that all new blocks must comply with for +// them to be valid. (but old blocks may not comply with) Currently just P2SH, +// but in the future other flags may be added, such as a soft-fork to enforce +// strict DER encoding. +static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; + +// Standard script verification flags that standard transactions will comply +// with. However scripts violating these flags may still be present in valid +// blocks and we must accept those blocks. +static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | + SCRIPT_VERIFY_STRICTENC; + enum txnouttype { TX_NONSTANDARD, From 29c17498a5d030f9d0a78cead3fbd37965b3cd40 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 18:17:56 -0400 Subject: [PATCH 015/336] Let tx (in)valid tests use any SCRIPT_VERIFY flag Previously only P2SH could be set. --- src/test/data/tx_invalid.json | 34 +++++++++++----------- src/test/data/tx_valid.json | 52 +++++++++++++++++----------------- src/test/transaction_tests.cpp | 49 ++++++++++++++++++++++++++++---- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index faf40ef23d..b9472ce00a 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -2,79 +2,79 @@ ["The following are deserialized transactions which are invalid."], ["They are in the form"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], -["serializedTransaction, enforceP2SH]"], +["serializedTransaction, verifyFlags]"], ["Objects that are only a single string (like this one) are ignored"], ["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"], [[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]], -"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true], +"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", "P2SH"], ["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"], ["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"], ["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], ["No inputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"0100000000010000000000000000015100000000", true], +"0100000000010000000000000000015100000000", "P2SH"], ["No outputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", "P2SH"], ["Negative output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", "P2SH"], ["MAX_MONEY + 1 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", "P2SH"], ["MAX_MONEY output + 1 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", "P2SH"], ["Duplicate inputs"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]], -"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", true], +"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 1"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 101"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"], ["Null txin"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", "P2SH"], ["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", "P2SH"], ["Incorrect signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], -"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], ["Empty stack when we try to run CHECKSIG"], [[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], -"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", true], +"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index c206f7a722..ddcb12ff14 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -2,7 +2,7 @@ ["The following are deserialized transactions which are valid."], ["They are in the form"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], -["serializedTransaction, enforceP2SH]"], +["serializedTransaction, verifyFlags]"], ["Objects that are only a single string (like this one) are ignored"], ["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], @@ -10,113 +10,113 @@ ["See http://r6.ca/blog/20111119T211504Z.html"], ["It is also the first OP_CHECKMULTISIG transaction in standard form"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], ["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], [[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], -"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true], +"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"], ["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], ["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], [[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], ["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], -"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true], +"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"], ["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], ["It results in signing the constant 1, instead of something generated based on the transaction,"], ["when the input doing the signing has an index greater than the maximum output index"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]], -"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true], +"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"], ["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], -"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"], ["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"], ["Tests for CheckTransaction()"], ["MAX_MONEY output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"], ["MAX_MONEY output + 0 output"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], -"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"], ["Coinbase of size 2"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 100"], ["Note the input is just required to make the tester happy"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], -"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"], ["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], - "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], ["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], [[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], - "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", true], + "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"], ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], - "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true], + "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"], ["Correct signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], -"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], ["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], [[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], -"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", true], +"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"], ["Empty pubkey"], [[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], -"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", true], +"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"], ["Empty signature"], [[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], -"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", true], +"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"], [[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], -"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", true], +"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"], [[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], -"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", true], +"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"], [[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], -"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", true], +"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"], [[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], -"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", true], +"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 24647950c4..9edc07ab16 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -13,16 +13,44 @@ #include #include +#include +#include #include #include "json/json_spirit_writer_template.h" using namespace std; using namespace json_spirit; +using namespace boost::algorithm; // In script_tests.cpp extern Array read_json(const std::string& jsondata); extern CScript ParseScript(string s); +unsigned int ParseFlags(string strFlags){ + unsigned int flags = 0; + vector words; + split(words, strFlags, is_any_of(",")); + + // Note how NOCACHE is not included as it is a runtime-only flag. + static map mapFlagNames; + if (mapFlagNames.size() == 0) + { + mapFlagNames["NONE"] = SCRIPT_VERIFY_NONE; + mapFlagNames["P2SH"] = SCRIPT_VERIFY_P2SH; + mapFlagNames["STRICTENC"] = SCRIPT_VERIFY_STRICTENC; + mapFlagNames["EVEN_S"] = SCRIPT_VERIFY_EVEN_S; + } + + BOOST_FOREACH(string word, words) + { + if (!mapFlagNames.count(word)) + BOOST_ERROR("Bad test: unknown verification flag '" << word << "'"); + flags |= mapFlagNames[word]; + } + + return flags; +} + BOOST_AUTO_TEST_SUITE(transaction_tests) BOOST_AUTO_TEST_CASE(tx_valid) @@ -30,8 +58,10 @@ BOOST_AUTO_TEST_CASE(tx_valid) // Read tests from test/data/tx_valid.json // Format is an array of arrays // Inner arrays are either [ "comment" ] - // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH + // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, verifyFlags // ... where all scripts are stringified scripts. + // + // verifyFlags is a comma separated list of script verification flags to apply, or "NONE" Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid))); BOOST_FOREACH(Value& tv, tests) @@ -40,7 +70,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) string strTest = write_string(tv, false); if (test[0].type() == array_type) { - if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type) + if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type) { BOOST_ERROR("Bad test: " << strTest); continue; @@ -88,7 +118,10 @@ BOOST_AUTO_TEST_CASE(tx_valid) break; } - BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool() ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, 0), strTest); + unsigned int verify_flags = ParseFlags(test[2].get_str()); + BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], + tx, i, verify_flags, 0), + strTest); } } } @@ -99,8 +132,10 @@ BOOST_AUTO_TEST_CASE(tx_invalid) // Read tests from test/data/tx_invalid.json // Format is an array of arrays // Inner arrays are either [ "comment" ] - // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH + // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, verifyFlags // ... where all scripts are stringified scripts. + // + // verifyFlags is a comma separated list of script verification flags to apply, or "NONE" Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid))); BOOST_FOREACH(Value& tv, tests) @@ -109,7 +144,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) string strTest = write_string(tv, false); if (test[0].type() == array_type) { - if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type) + if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type) { BOOST_ERROR("Bad test: " << strTest); continue; @@ -156,7 +191,9 @@ BOOST_AUTO_TEST_CASE(tx_invalid) break; } - fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool() ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, 0); + unsigned int verify_flags = ParseFlags(test[2].get_str()); + fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], + tx, i, verify_flags, 0); } BOOST_CHECK_MESSAGE(!fValid, strTest); From aa250f0453029afbf3c903899a3770c61e389468 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 5 May 2014 19:43:14 +0200 Subject: [PATCH 016/336] Remove NumBlocksOfPeers Generally useless information. Only updates on connect time, not after that. Peers can easily lie and the median filter is not effective in preventing that. In the past it was used for progress display in the GUI but `CheckPoints::guessVerificationProgress` provides a better way that is now used. It was too easy to mislead it. Peers do lie about it in practice, see issue #4065. From the RPC, `getpeerinfo` gives the peer raw values, which are more useful. --- src/main.cpp | 11 ----------- src/main.h | 2 -- src/qt/bitcoingui.cpp | 17 +++++------------ src/qt/bitcoingui.h | 2 +- src/qt/clientmodel.cpp | 14 +++----------- src/qt/clientmodel.h | 5 +---- src/qt/forms/rpcconsole.ui | 33 +++++---------------------------- src/qt/rpcconsole.cpp | 8 +++----- src/qt/rpcconsole.h | 2 +- 9 files changed, 19 insertions(+), 75 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 40c713ce93..46183bf431 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,8 +54,6 @@ int64_t CTransaction::nMinTxFee = 10000; // Override with -mintxfee /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ int64_t CTransaction::nMinRelayTxFee = 1000; -static CMedianFilter cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have - struct COrphanBlock { uint256 hashBlock; uint256 hashPrev; @@ -1303,12 +1301,6 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) return true; } -// Return maximum amount of blocks that other nodes claim to have -int GetNumBlocksOfPeers() -{ - return std::max(cPeerBlockCounts.median(), Checkpoints::GetTotalBlocksEstimate()); -} - bool IsInitialBlockDownload() { LOCK(cs_main); @@ -3484,9 +3476,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), addrFrom.ToString(), pfrom->addr.ToString()); AddTimeData(pfrom->addr, nTime); - - LOCK(cs_main); - cPeerBlockCounts.input(pfrom->nStartingHeight); } diff --git a/src/main.h b/src/main.h index 825e577d1e..e459772e88 100644 --- a/src/main.h +++ b/src/main.h @@ -160,8 +160,6 @@ void ThreadScriptCheck(); bool CheckProofOfWork(uint256 hash, unsigned int nBits); /** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); -/** Get the number of active peers */ -int GetNumBlocksOfPeers(); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index da7762282a..e6190aec13 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -403,8 +403,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) setNumConnections(clientModel->getNumConnections()); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers()); - connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + setNumBlocks(clientModel->getNumBlocks()); + connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); // Receive and report messages from client model connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); @@ -617,7 +617,7 @@ void BitcoinGUI::setNumConnections(int count) labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count)); } -void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) +void BitcoinGUI::setNumBlocks(int count) { // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbelled text) statusBar()->clearMessage(); @@ -646,17 +646,10 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) QDateTime currentDate = QDateTime::currentDateTime(); int secs = lastBlockDate.secsTo(currentDate); - if(count < nTotalBlocks) - { - tooltip = tr("Processed %1 of %2 (estimated) blocks of transaction history.").arg(count).arg(nTotalBlocks); - } - else - { - tooltip = tr("Processed %1 blocks of transaction history.").arg(count); - } + tooltip = tr("Processed %1 blocks of transaction history.").arg(count); // Set icon state: spinning if catching up, tick otherwise - if(secs < 90*60 && count >= nTotalBlocks) + if(secs < 90*60) { tooltip = tr("Up to date") + QString(".
") + tooltip; labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 0cc1ebc502..b4675b95ac 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -130,7 +130,7 @@ public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks shown in the UI */ - void setNumBlocks(int count, int nTotalBlocks); + void setNumBlocks(int count); /** Notify the user of an event from the core network or transaction handling code. @param[in] title the message box / notification title diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 3c0564c208..d1f68ebd22 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -23,7 +23,7 @@ static const int64_t nClientStartupTime = GetTime(); ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : QObject(parent), optionsModel(optionsModel), - cachedNumBlocks(0), cachedNumBlocksOfPeers(0), + cachedNumBlocks(0), cachedReindexing(0), cachedImporting(0), numBlocksAtStartup(-1), pollTimer(0) { @@ -101,19 +101,16 @@ void ClientModel::updateTimer() // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. // Periodically check and update with a timer. int newNumBlocks = getNumBlocks(); - int newNumBlocksOfPeers = getNumBlocksOfPeers(); // check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state - if (cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers || + if (cachedNumBlocks != newNumBlocks || cachedReindexing != fReindex || cachedImporting != fImporting) { cachedNumBlocks = newNumBlocks; - cachedNumBlocksOfPeers = newNumBlocksOfPeers; cachedReindexing = fReindex; cachedImporting = fImporting; - // ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI - emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks)); + emit numBlocksChanged(newNumBlocks); } emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); @@ -166,11 +163,6 @@ enum BlockSource ClientModel::getBlockSource() const return BLOCK_SOURCE_NONE; } -int ClientModel::getNumBlocksOfPeers() const -{ - return GetNumBlocksOfPeers(); -} - QString ClientModel::getStatusBarWarnings() const { return QString::fromStdString(GetWarnings("statusbar")); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index f29b695ea1..cab853d92d 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -60,8 +60,6 @@ public: bool inInitialBlockDownload() const; //! Return true if core is importing blocks enum BlockSource getBlockSource() const; - //! Return conservative estimate of total number of blocks, or 0 if unknown - int getNumBlocksOfPeers() const; //! Return warnings to be displayed in status bar QString getStatusBarWarnings() const; @@ -75,7 +73,6 @@ private: OptionsModel *optionsModel; int cachedNumBlocks; - int cachedNumBlocksOfPeers; bool cachedReindexing; bool cachedImporting; @@ -88,7 +85,7 @@ private: signals: void numConnectionsChanged(int count); - void numBlocksChanged(int count, int countOfPeers); + void numBlocksChanged(int count); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 31d61ec468..fcb6bb60bb 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -254,36 +254,13 @@ - - - Estimated total blocks - - - - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - Last block time - + IBeamCursor @@ -299,7 +276,7 @@ - + Qt::Vertical @@ -312,7 +289,7 @@ - + @@ -325,7 +302,7 @@ - + Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. @@ -338,7 +315,7 @@ - + Qt::Vertical diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ba5871ae2b..0a46a722e4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -271,8 +271,8 @@ void RPCConsole::setClientModel(ClientModel *model) setNumConnections(model->getNumConnections()); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers()); - connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + setNumBlocks(model->getNumBlocks()); + connect(model, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int))); updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); @@ -366,11 +366,9 @@ void RPCConsole::setNumConnections(int count) ui->numberOfConnections->setText(connections); } -void RPCConsole::setNumBlocks(int count, int countOfPeers) +void RPCConsole::setNumBlocks(int count) { ui->numberOfBlocks->setText(QString::number(count)); - // If there is no current countOfPeers available display N/A instead of 0, which can't ever be true - ui->totalBlocks->setText(countOfPeers == 0 ? tr("N/A") : QString::number(countOfPeers)); if(clientModel) ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString()); } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index f7a7772050..091a6d294f 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -52,7 +52,7 @@ public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); /** Set number of blocks shown in the UI */ - void setNumBlocks(int count, int countOfPeers); + void setNumBlocks(int count); /** Go forward or back in history */ void browseHistory(int offset); /** Scroll console view to end */ From 01ce7117988dc4a894b3cb2e182e3f20c1f7b6e0 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 6 May 2014 12:52:21 +0200 Subject: [PATCH 017/336] [Qt] fix Qt slot problem in receivecoinsdialog - fixes error from debug.log: QMetaObject::connectSlotsByName: No matching signal for on_recentRequestsView_selectionChanged(QItemSelection,QItemSelection) - small style fixes (e.g. alphabetical ordering if includes etc.) - fixes #3992 --- src/qt/receivecoinsdialog.cpp | 23 +++++++++++------------ src/qt/receivecoinsdialog.h | 8 ++++---- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 3ccfb429a6..f2c76c8355 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -5,21 +5,21 @@ #include "receivecoinsdialog.h" #include "ui_receivecoinsdialog.h" -#include "walletmodel.h" -#include "bitcoinunits.h" #include "addressbookpage.h" -#include "optionsmodel.h" -#include "guiutil.h" -#include "receiverequestdialog.h" #include "addresstablemodel.h" +#include "bitcoinunits.h" +#include "guiutil.h" +#include "optionsmodel.h" +#include "receiverequestdialog.h" #include "recentrequeststablemodel.h" +#include "walletmodel.h" #include #include -#include -#include -#include #include +#include +#include +#include ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) : QDialog(parent), @@ -78,7 +78,7 @@ void ReceiveCoinsDialog::setModel(WalletModel *model) connect(tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, - SLOT(on_recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); + SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); // Last 2 columns are set by the columnResizingFixer, when the table geometry is ready. columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH); } @@ -165,8 +165,7 @@ void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex & dialog->show(); } -void ReceiveCoinsDialog::on_recentRequestsView_selectionChanged(const QItemSelection &selected, - const QItemSelection &deselected) +void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { // Enable Show/Remove buttons only if anything is selected. bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty(); @@ -200,7 +199,7 @@ void ReceiveCoinsDialog::on_removeRequestButton_clicked() // We override the virtual resizeEvent of the QWidget to adjust tables column // sizes as the tables width is proportional to the dialogs width. -void ReceiveCoinsDialog::resizeEvent(QResizeEvent* event) +void ReceiveCoinsDialog::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message); diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index ab63331597..663cb157a4 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -18,8 +18,8 @@ namespace Ui { class ReceiveCoinsDialog; } -class WalletModel; class OptionsModel; +class WalletModel; QT_BEGIN_NAMESPACE class QModelIndex; @@ -57,16 +57,16 @@ private: WalletModel *model; QMenu *contextMenu; void copyColumnToClipboard(int column); - virtual void resizeEvent(QResizeEvent* event); + virtual void resizeEvent(QResizeEvent *event); private slots: void on_receiveButton_clicked(); void on_showRequestButton_clicked(); void on_removeRequestButton_clicked(); void on_recentRequestsView_doubleClicked(const QModelIndex &index); - void on_recentRequestsView_selectionChanged(const QItemSelection &, const QItemSelection &); + void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void updateDisplayUnit(); - void showMenu(const QPoint &); + void showMenu(const QPoint &point); void copyLabel(); void copyMessage(); void copyAmount(); From 783b182c8fa92674fa609b584c0b187469893ca4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 6 May 2014 15:25:01 +0200 Subject: [PATCH 018/336] Remove dummy PRIszX macros for formatting Size specifiers are no longer needed now that we use typesafe tinyformat for string formatting, instead of the system's sprintf. No functional changes. This continues the work in #3735. --- src/core.cpp | 4 ++-- src/init.cpp | 8 ++++---- src/main.cpp | 22 +++++++++++----------- src/miner.cpp | 2 +- src/rpcmisc.cpp | 2 +- src/rpcprotocol.cpp | 2 +- src/test/util_tests.cpp | 12 ++++++------ src/util.h | 12 ------------ src/wallet.cpp | 2 +- src/walletdb.cpp | 2 +- 10 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index cbdd24e806..7651ce9957 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -140,7 +140,7 @@ double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSiz std::string CTransaction::ToString() const { std::string str; - str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%u)\n", + str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n", GetHash().ToString().substr(0,10), nVersion, vin.size(), @@ -269,7 +269,7 @@ uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector& vMer void CBlock::print() const { - LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n", + LogPrintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", GetHash().ToString(), nVersion, hashPrevBlock.ToString(), diff --git a/src/init.cpp b/src/init.cpp index 77c32d0b49..821ac4c875 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1078,12 +1078,12 @@ bool AppInit2(boost::thread_group& threadGroup) RandAddSeedPerfmon(); //// debug print - LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size()); + LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("nBestHeight = %d\n", chainActive.Height()); #ifdef ENABLE_WALLET - LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0); - LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0); - LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); + LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0); + LogPrintf("mapWallet.size() = %u\n", pwalletMain ? pwalletMain->mapWallet.size() : 0); + LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); #endif StartNode(threadGroup); diff --git a/src/main.cpp b/src/main.cpp index 40c713ce93..77418bbd15 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -432,7 +432,7 @@ bool AddOrphanTx(const CTransaction& tx) BOOST_FOREACH(const CTxIn& txin, tx.vin) mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash); - LogPrint("mempool", "stored orphan tx %s (mapsz %"PRIszu")\n", hash.ToString(), + LogPrint("mempool", "stored orphan tx %s (mapsz %u)\n", hash.ToString(), mapOrphanTransactions.size()); return true; } @@ -3044,7 +3044,7 @@ void PrintBlockTree() // print item CBlock block; ReadBlockFromDisk(block, pindex); - LogPrintf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"\n", + LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n", pindex->nHeight, pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()), @@ -3371,7 +3371,7 @@ void static ProcessGetData(CNode* pfrom) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { RandAddSeedPerfmon(); - LogPrint("net", "received: %s (%"PRIszu" bytes)\n", strCommand, vRecv.size()); + LogPrint("net", "received: %s (%u bytes)\n", strCommand, vRecv.size()); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -3515,7 +3515,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (vAddr.size() > 1000) { Misbehaving(pfrom->GetId(), 20); - return error("message addr size() = %"PRIszu"", vAddr.size()); + return error("message addr size() = %u", vAddr.size()); } // Store the new addresses @@ -3578,7 +3578,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (vInv.size() > MAX_INV_SZ) { Misbehaving(pfrom->GetId(), 20); - return error("message inv size() = %"PRIszu"", vInv.size()); + return error("message inv size() = %u", vInv.size()); } LOCK(cs_main); @@ -3617,11 +3617,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (vInv.size() > MAX_INV_SZ) { Misbehaving(pfrom->GetId(), 20); - return error("message getdata size() = %"PRIszu"", vInv.size()); + return error("message getdata size() = %u", vInv.size()); } if (fDebug || (vInv.size() != 1)) - LogPrint("net", "received getdata (%"PRIszu" invsz)\n", vInv.size()); + LogPrint("net", "received getdata (%u invsz)\n", vInv.size()); if ((fDebug && vInv.size() > 0) || (vInv.size() == 1)) LogPrint("net", "received getdata for: %s\n", vInv[0].ToString()); @@ -3729,7 +3729,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) vEraseQueue.push_back(inv.hash); - LogPrint("mempool", "AcceptToMemoryPool: %s %s : accepted %s (poolsz %"PRIszu")\n", + LogPrint("mempool", "AcceptToMemoryPool: %s %s : accepted %s (poolsz %u)\n", pfrom->addr.ToString(), pfrom->cleanSubVer, tx.GetHash().ToString(), mempool.mapTx.size()); @@ -3914,7 +3914,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } if (!(sProblem.empty())) { - LogPrint("net", "pong %s %s: %s, %x expected, %x received, %"PRIszu" bytes\n", + LogPrint("net", "pong %s %s: %s, %x expected, %x received, %u bytes\n", pfrom->addr.ToString(), pfrom->cleanSubVer, sProblem, @@ -4049,7 +4049,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) bool ProcessMessages(CNode* pfrom) { //if (fDebug) - // LogPrintf("ProcessMessages(%"PRIszu" messages)\n", pfrom->vRecvMsg.size()); + // LogPrintf("ProcessMessages(%u messages)\n", pfrom->vRecvMsg.size()); // // Message format @@ -4077,7 +4077,7 @@ bool ProcessMessages(CNode* pfrom) CNetMessage& msg = *it; //if (fDebug) - // LogPrintf("ProcessMessages(message %u msgsz, %"PRIszu" bytes, complete:%s)\n", + // LogPrintf("ProcessMessages(message %u msgsz, %u bytes, complete:%s)\n", // msg.hdr.nMessageSize, msg.vRecv.size(), // msg.complete() ? "Y" : "N"); diff --git a/src/miner.cpp b/src/miner.cpp index 3351908e65..6bc6edf34f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -528,7 +528,7 @@ void static BitcoinMiner(CWallet *pwallet) CBlock *pblock = &pblocktemplate->block; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - LogPrintf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(), + LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); // diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index ae154f2ae4..6964b97be3 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -187,7 +187,7 @@ CScript _createmultisig(const Array& params) if ((int)keys.size() < nRequired) throw runtime_error( strprintf("not enough keys supplied " - "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); + "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); std::vector pubkeys; pubkeys.resize(keys.size()); for (unsigned int i = 0; i < keys.size(); i++) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 652b14d187..5cbaa535ab 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -92,7 +92,7 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive) "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" "Connection: %s\r\n" - "Content-Length: %"PRIszu"\r\n" + "Content-Length: %u\r\n" "Content-Type: application/json\r\n" "Server: bitcoin-json-rpc/%s\r\n" "\r\n" diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index b8f107f644..44998cbda7 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -321,15 +321,15 @@ BOOST_AUTO_TEST_CASE(strprintf_numbers) size_t st = 12345678; /* unsigned size_t test value */ ssize_t sst = -12345678; /* signed size_t test value */ - BOOST_CHECK(strprintf("%s %"PRIszd" %s", B, sst, E) == B" -12345678 "E); - BOOST_CHECK(strprintf("%s %"PRIszu" %s", B, st, E) == B" 12345678 "E); - BOOST_CHECK(strprintf("%s %"PRIszx" %s", B, st, E) == B" bc614e "E); + BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 "E); + BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 "E); + BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e "E); ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */ ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */ - BOOST_CHECK(strprintf("%s %"PRIpdd" %s", B, spt, E) == B" -87654321 "E); - BOOST_CHECK(strprintf("%s %"PRIpdu" %s", B, pt, E) == B" 87654321 "E); - BOOST_CHECK(strprintf("%s %"PRIpdx" %s", B, pt, E) == B" 5397fb1 "E); + BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 "E); + BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 "E); + BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 "E); } #undef B #undef E diff --git a/src/util.h b/src/util.h index fbd841f7a8..55d9308ab6 100644 --- a/src/util.h +++ b/src/util.h @@ -44,18 +44,6 @@ static const int64_t CENT = 1000000; #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) -/* Format characters for (s)size_t, ptrdiff_t. - * - * Define these as empty as the tinyformat-based formatting system is - * type-safe, no special format characters are needed to specify sizes. - */ -#define PRIszx "x" -#define PRIszu "u" -#define PRIszd "d" -#define PRIpdx "x" -#define PRIpdu "u" -#define PRIpdd "d" - // This is needed because the foreach macro can't get over the comma in pair #define PAIRTYPE(t1, t2) std::pair diff --git a/src/wallet.cpp b/src/wallet.cpp index 7cf2361096..22df7a9ad8 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1638,7 +1638,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey()))) throw runtime_error("TopUpKeyPool() : writing generated key failed"); setKeyPool.insert(nEnd); - LogPrintf("keypool added key %d, size=%"PRIszu"\n", nEnd, setKeyPool.size()); + LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size()); } } return true; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 359a1cef61..80e9dded5f 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -894,7 +894,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename); return false; } - LogPrintf("Salvage(aggressive) found %"PRIszu" records\n", salvagedData.size()); + LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); bool fSuccess = allOK; Db* pdbCopy = new Db(&dbenv.dbenv, 0); From bdc83e8f450456c9f547f1c4eab43571bac631c2 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 16 Nov 2013 01:54:29 +0100 Subject: [PATCH 019/336] [Qt] ensure payment request network matches client network - replaces checks in SendCoinsDialog::handlePaymentRequest() that belong to PaymentServer (normal URIs are special cased, as only an isValid check is done on BTC addresses) - prevents the client to handle payment requests that do not match the clients network and shows an error instead (mainly a problem with drag&drop payment requests onto the client window) - includes some small comment changes also --- src/qt/paymentserver.cpp | 81 ++++++++++++++++++++++++++++---------- src/qt/sendcoinsdialog.cpp | 22 +---------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index ca6ae17990..4c45585685 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -178,6 +178,9 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) // and the items in savedPaymentRequest will be handled // when uiReady() is called. // +// Warning: ipcSendCommandLine() is called early in init, +// so don't use "emit message()", but "QMessageBox::"! +// bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { for (int i = 1; i < argc; i++) @@ -411,7 +414,15 @@ void PaymentServer::handleURIOrFile(const QString& s) { SendCoinsRecipient recipient; if (GUIUtil::parseBitcoinURI(s, &recipient)) - emit receivedPaymentRequest(recipient); + { + CBitcoinAddress address(recipient.address.toStdString()); + if (!address.IsValid()) { + emit message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), + CClientUIInterface::MSG_ERROR); + } + else + emit receivedPaymentRequest(recipient); + } else emit message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."), @@ -425,12 +436,14 @@ void PaymentServer::handleURIOrFile(const QString& s) { PaymentRequestPlus request; SendCoinsRecipient recipient; - if (readPaymentRequest(s, request) && processPaymentRequest(request, recipient)) - emit receivedPaymentRequest(recipient); - else + if (!readPaymentRequest(s, request)) + { emit message(tr("Payment request file handling"), - tr("Payment request file can not be read or processed! This can be caused by an invalid payment request file."), + tr("Payment request file can not be read! This can be caused by an invalid payment request file."), CClientUIInterface::ICON_WARNING); + } + else if (processPaymentRequest(request, recipient)) + emit receivedPaymentRequest(recipient); return; } @@ -482,6 +495,35 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins if (!optionsModel) return false; + if (request.IsInitialized()) { + const payments::PaymentDetails& details = request.getDetails(); + + // Payment request network matches client network? + if ((details.network() == "main" && TestNet()) || + (details.network() == "test" && !TestNet())) + { + emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), + CClientUIInterface::MSG_ERROR); + + return false; + } + + // Expired payment request? + if (details.has_expires() && (int64_t)details.expires() < GetTime()) + { + emit message(tr("Payment request rejected"), tr("Payment request has expired."), + CClientUIInterface::MSG_ERROR); + + return false; + } + } + else { + emit message(tr("Payment request error"), tr("Payment request is not initialized."), + CClientUIInterface::MSG_ERROR); + + return false; + } + recipient.paymentRequest = request; recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo()); @@ -497,11 +539,11 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins // Append destination address addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString())); } - else if (!recipient.authenticatedMerchant.isEmpty()){ + else if (!recipient.authenticatedMerchant.isEmpty()) { // Insecure payments to custom bitcoin addresses are not supported // (there is no good way to tell the user where they are paying in a way // they'd have a chance of understanding). - emit message(tr("Payment request error"), + emit message(tr("Payment request rejected"), tr("Unverified payment requests to custom payment scripts are unsupported."), CClientUIInterface::MSG_ERROR); return false; @@ -510,11 +552,10 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); if (txOut.IsDust(CTransaction::nMinRelayTxFee)) { - QString msg = tr("Requested payment amount of %1 is too small (considered dust).") - .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)); + emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") + .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), + CClientUIInterface::MSG_ERROR); - qDebug() << "PaymentServer::processPaymentRequest : " << msg; - emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); return false; } @@ -581,8 +622,8 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien refund_to->set_script(&s[0], s.size()); } else { - // This should never happen, because sending coins should have just unlocked the wallet - // and refilled the keypool + // This should never happen, because sending coins should have + // just unlocked the wallet and refilled the keypool. qDebug() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set"; } } @@ -594,7 +635,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien netManager->post(netRequest, serData); } else { - // This should never happen, either: + // This should never happen, either. qDebug() << "PaymentServer::fetchPaymentACK : Error serializing payment message"; } } @@ -620,17 +661,15 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) { PaymentRequestPlus request; SendCoinsRecipient recipient; - if (request.parse(data) && processPaymentRequest(request, recipient)) + if (!request.parse(data)) { - emit receivedPaymentRequest(recipient); - } - else - { - qDebug() << "PaymentServer::netRequestFinished : Error processing payment request"; + qDebug() << "PaymentServer::netRequestFinished : Error parsing payment request"; emit message(tr("Payment request error"), - tr("Payment request can not be parsed or processed!"), + tr("Payment request can not be parsed!"), CClientUIInterface::MSG_ERROR); } + else if (processPaymentRequest(request, recipient)) + emit receivedPaymentRequest(recipient); return; } diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 33621e54b0..23b8ef83e2 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -377,26 +377,8 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv) bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) { - QString strSendCoins = tr("Send Coins"); - if (rv.paymentRequest.IsInitialized()) { - // Expired payment request? - const payments::PaymentDetails& details = rv.paymentRequest.getDetails(); - if (details.has_expires() && (int64_t)details.expires() < GetTime()) - { - emit message(strSendCoins, tr("Payment request expired"), - CClientUIInterface::MSG_WARNING); - return false; - } - } - else { - CBitcoinAddress address(rv.address.toStdString()); - if (!address.IsValid()) { - emit message(strSendCoins, tr("Invalid payment address %1").arg(rv.address), - CClientUIInterface::MSG_WARNING); - return false; - } - } - + // Just paste the entry, all pre-checks + // are done in paymentserver.cpp. pasteEntry(rv); return true; } From 6380180821917c22ecfd89128ee60aae6f4cac33 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 17:36:35 -0400 Subject: [PATCH 020/336] Add rejection of non-null CHECKMULTISIG dummy values This is a source of transaction mutability as the dummy value was previously not checked and could be modified to something other than the usual OP_0 value. --- src/script.cpp | 16 +++++++++++++++- src/script.h | 4 +++- src/test/data/tx_invalid.json | 29 ++++++++++++++++++++++++++++- src/test/data/tx_valid.json | 18 ++++++++++++++++-- src/test/transaction_tests.cpp | 1 + 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index dc0cd28bf8..a5cdc9712d 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -934,8 +934,22 @@ bool EvalScript(vector >& stack, const CScript& script, co fSuccess = false; } - while (i-- > 0) + // Clean up stack of actual arguments + while (i-- > 1) popstack(stack); + + // A bug causes CHECKMULTISIG to consume one extra argument + // whose contents were not checked in any way. + // + // Unfortunately this is a potential source of mutability, + // so optionally verify it is exactly equal to zero prior + // to removing it from the stack. + if (stack.size() < 1) + return false; + if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size()) + return error("CHECKMULTISIG dummy argument not null"); + popstack(stack); + stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKMULTISIGVERIFY) diff --git a/src/script.h b/src/script.h index 0f26fb556d..01779f550c 100644 --- a/src/script.h +++ b/src/script.h @@ -42,6 +42,7 @@ enum SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys SCRIPT_VERIFY_EVEN_S = (1U << 2), // enforce even S values in signatures (depends on STRICTENC) SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it) + SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length }; // Mandatory script verification flags that all new blocks must comply with for @@ -54,7 +55,8 @@ static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; // with. However scripts violating these flags may still be present in valid // blocks and we must accept those blocks. static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | - SCRIPT_VERIFY_STRICTENC; + SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_NULLDUMMY; enum txnouttype { diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index b9472ce00a..638a705f9f 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -67,11 +67,38 @@ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", "P2SH"], -["Incorrect signature order"], +["CHECKMULTISIG with incorrect signature order"], ["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], "01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value missing"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + + +["CHECKMULTISIG SCRIPT_VERIFY_NULLDUMMY tests:"], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a010047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but using a OP_1"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but using a OP_1NEGATE"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["As above, but with the dummy byte missing"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + + ["Empty stack when we try to run CHECKSIG"], [[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], "01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index ddcb12ff14..1f51d3ce55 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -13,9 +13,23 @@ "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], -["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], +["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], +["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + +["As above, but using a OP_1"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], + +["As above, but using a OP_1NEGATE"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], ["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 9edc07ab16..40961cbae0 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -39,6 +39,7 @@ unsigned int ParseFlags(string strFlags){ mapFlagNames["P2SH"] = SCRIPT_VERIFY_P2SH; mapFlagNames["STRICTENC"] = SCRIPT_VERIFY_STRICTENC; mapFlagNames["EVEN_S"] = SCRIPT_VERIFY_EVEN_S; + mapFlagNames["NULLDUMMY"] = SCRIPT_VERIFY_NULLDUMMY; } BOOST_FOREACH(string word, words) From f80cffa213cce7d7f82aef7cf3a2f7308fbeb009 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 22:36:46 -0400 Subject: [PATCH 021/336] Do not trigger a DoS ban if SCRIPT_VERIFY_NULLDUMMY fails --- src/main.cpp | 24 ++++++++++++++++++------ src/script.h | 6 ++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cee9d027f5..e8fb26de88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1588,14 +1588,26 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); } else if (!check()) { - if (flags & SCRIPT_VERIFY_STRICTENC) { - // For now, check whether the failure was caused by non-canonical - // encodings or not; if so, don't trigger DoS protection. - CScriptCheck check(coins, tx, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0); + if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) { + // Check whether the failure was caused by a + // non-mandatory script verification check, such as + // non-standard DER encodings or non-null dummy + // arguments; if so, don't trigger DoS protection to + // avoid splitting the network between upgraded and + // non-upgraded nodes. + CScriptCheck check(coins, tx, i, + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, 0); if (check()) - return state.Invalid(false, REJECT_NONSTANDARD, "non-canonical"); + return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag"); } - return state.DoS(100,false, REJECT_NONSTANDARD, "non-canonical"); + // Failures of other flags indicate a transaction that is + // invalid in new blocks, e.g. a invalid P2SH. We DoS ban + // such nodes as they are not following the protocol. That + // said during an upgrade careful thought should be taken + // as to the correct behavior - we may want to continue + // peering with non-upgraded nodes even after a soft-fork + // super-majority vote has passed. + return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed"); } } } diff --git a/src/script.h b/src/script.h index 01779f550c..bbcdad159c 100644 --- a/src/script.h +++ b/src/script.h @@ -49,6 +49,9 @@ enum // them to be valid. (but old blocks may not comply with) Currently just P2SH, // but in the future other flags may be added, such as a soft-fork to enforce // strict DER encoding. +// +// Failing one of these tests may trigger a DoS ban - see CheckInputs() for +// details. static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; // Standard script verification flags that standard transactions will comply @@ -58,6 +61,9 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_NULLDUMMY; +// For convenience, standard but not mandatory verify flags. +static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; + enum txnouttype { TX_NONSTANDARD, From 4d79098ad548874ca6e4c09d873fc2f481e6edb4 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 16:38:44 -0400 Subject: [PATCH 022/336] Increase IsStandard() scriptSig length Removes the limits on number of pubkeys for P2SH CHECKMULTISIG outputs. Previously with the 500 byte scriptSig limit there were odd restrictions where even a 1-of-12 P2SH could be spent in a standard transaction(1), yet multisig scriptPubKey's requiring more signatures quickly ran out of scriptSig space. From a "stuff-data-in-the-blockchain" point of view not much has changed as with the prior commit now only allowing the dummy value to be null the newly allowed scriptSig space can only be used for signatures. In any case, just using more outputs is trivial and doesn't cost much. 1) See 779b519480d8c5346de6e635119c7ee772e97ec872240c45e558f582a37b4b73 Mined by BTC Guild. --- src/main.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e8fb26de88..8ed811c1a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -515,10 +515,14 @@ bool IsStandardTx(const CTransaction& tx, string& reason) BOOST_FOREACH(const CTxIn& txin, tx.vin) { - // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG - // pay-to-script-hash, which is 3 ~80-byte signatures, 3 - // ~65-byte public keys, plus a few script ops. - if (txin.scriptSig.size() > 500) { + // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed + // keys. (remember the 520 byte limit on redeemScript size) That works + // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624 + // bytes of scriptSig, which we round off to 1650 bytes for some minor + // future-proofing. That's also enough to spend a 20-of-20 + // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not + // considered standard) + if (txin.scriptSig.size() > 1650) { reason = "scriptsig-size"; return false; } From 787ee0c91394b0ae16ca2500dbacf9349e65b6bc Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 10 Mar 2014 22:43:15 -0400 Subject: [PATCH 023/336] Check redeemScript size does not exceed 520 byte limit redeemScripts >520bytes can't be spent due to the MAX_SCRIPT_ELEMENT_SIZE limit; previously the addmultisigaddress and createmultisig RPC calls would let you violate that limit unknowingly. Also made the wallet code itself check the redeemScript prior to adding it to the wallet, which in the (rare) instance that a user has added an invalid oversized redeemScript to their wallet causes an error on startup. The affected key isn't added to the wallet; other keys are unaffected. --- src/keystore.cpp | 3 +++ src/rpcmisc.cpp | 9 +++++++-- src/rpcwallet.cpp | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/keystore.cpp b/src/keystore.cpp index 46402ea25b..594e0c61da 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -33,6 +33,9 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) bool CBasicKeyStore::AddCScript(const CScript& redeemScript) { + if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) + return error("CBasicKeyStore::AddCScript() : redeemScripts > %i bytes are invalid", MAX_SCRIPT_ELEMENT_SIZE); + LOCK(cs_KeyStore); mapScripts[redeemScript.GetID()] = redeemScript; return true; diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index ae154f2ae4..a2694d458a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -176,7 +176,7 @@ Value validateaddress(const Array& params, bool fHelp) // // Used by addmultisigaddress / createmultisig: // -CScript _createmultisig(const Array& params) +CScript _createmultisig_redeemScript(const Array& params) { int nRequired = params[0].get_int(); const Array& keys = params[1].get_array(); @@ -228,6 +228,11 @@ CScript _createmultisig(const Array& params) } CScript result; result.SetMultisig(nRequired, pubkeys); + + if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) + throw runtime_error( + strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)); + return result; } @@ -263,7 +268,7 @@ Value createmultisig(const Array& params, bool fHelp) } // Construct using pay-to-script-hash: - CScript inner = _createmultisig(params); + CScript inner = _createmultisig_redeemScript(params); CScriptID innerID = inner.GetID(); CBitcoinAddress address(innerID); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index a5a7df0867..e21881dbe9 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -871,7 +871,7 @@ Value sendmany(const Array& params, bool fHelp) } // Defined in rpcmisc.cpp -extern CScript _createmultisig(const Array& params); +extern CScript _createmultisig_redeemScript(const Array& params); Value addmultisigaddress(const Array& params, bool fHelp) { @@ -908,7 +908,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) strAccount = AccountFromValue(params[2]); // Construct using pay-to-script-hash: - CScript inner = _createmultisig(params); + CScript inner = _createmultisig_redeemScript(params); CScriptID innerID = inner.GetID(); pwalletMain->AddCScript(inner); From b1f0be0a05aca81e564139472206dee72410976e Mon Sep 17 00:00:00 2001 From: harry Date: Fri, 9 May 2014 12:06:20 +0800 Subject: [PATCH 024/336] build: fix: remove error output while git not found in path, error is output to console. --- share/genbuild.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/genbuild.sh b/share/genbuild.sh index 6890a6eba0..0800b31229 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -16,7 +16,7 @@ fi DESC="" SUFFIX="" LAST_COMMIT_DATE="" -if [ -e "$(which git)" -a -d ".git" ]; then +if [ -e "$(which git 2>/dev/null)" -a -d ".git" ]; then # clean 'dirty' status of touched files that haven't been modified git diff >/dev/null 2>/dev/null From e443ed2462b706650f51f08c8760dbf5047aa77f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 9 May 2014 16:33:37 +0200 Subject: [PATCH 025/336] Fix transaction tests Conflict between low-s (6fd7ef2) and test updates in d3a33fc. --- src/test/transaction_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 40961cbae0..feba5ee80e 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -38,7 +38,7 @@ unsigned int ParseFlags(string strFlags){ mapFlagNames["NONE"] = SCRIPT_VERIFY_NONE; mapFlagNames["P2SH"] = SCRIPT_VERIFY_P2SH; mapFlagNames["STRICTENC"] = SCRIPT_VERIFY_STRICTENC; - mapFlagNames["EVEN_S"] = SCRIPT_VERIFY_EVEN_S; + mapFlagNames["LOW_S"] = SCRIPT_VERIFY_LOW_S; mapFlagNames["NULLDUMMY"] = SCRIPT_VERIFY_NULLDUMMY; } From eb2cbd754d0ed02ab1c3f0889b6ee1776abd5082 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 19 Apr 2014 23:02:47 +0200 Subject: [PATCH 026/336] Deduplicate shared code between uint160 and uint256 --- src/uint256.h | 306 +++++++++++--------------------------------------- 1 file changed, 65 insertions(+), 241 deletions(-) diff --git a/src/uint256.h b/src/uint256.h index ba903bc8fc..a3f7835875 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -19,17 +19,56 @@ inline signed char HexDigit(char c) return p_util_hexdigit[(unsigned char)c]; } -/** Base class without constructors for uint256 and uint160. - * This makes the compiler let you use it in a union. - */ +/** Template base class for unsigned big integers. */ template class base_uint { -protected: +private: enum { WIDTH=BITS/32 }; uint32_t pn[WIDTH]; public: + base_uint() + { + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + } + + base_uint(const base_uint& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + } + + base_uint& operator=(const base_uint& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + return *this; + } + + base_uint(uint64_t b) + { + pn[0] = (unsigned int)b; + pn[1] = (unsigned int)(b >> 32); + for (int i = 2; i < WIDTH; i++) + pn[i] = 0; + } + + explicit base_uint(const std::string& str) + { + SetHex(str); + } + + explicit base_uint(const std::vector& vch) + { + if (vch.size() == sizeof(pn)) { + memcpy(pn, &vch[0], sizeof(pn)); + } else { + *this = 0; + } + } + bool operator!() const { for (int i = 0; i < WIDTH; i++) @@ -292,7 +331,13 @@ public: return (!(a == b)); } - + friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; } + friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; } + friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; } + friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; } + friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; } + friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; } + friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; } std::string GetHex() const { @@ -373,263 +418,42 @@ public: return pn[0] | (uint64_t)pn[1] << 32; } -// unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const unsigned int GetSerializeSize(int nType, int nVersion) const { return sizeof(pn); } template -// void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const void Serialize(Stream& s, int nType, int nVersion) const { s.write((char*)pn, sizeof(pn)); } template -// void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) void Unserialize(Stream& s, int nType, int nVersion) { s.read((char*)pn, sizeof(pn)); } - - - friend class uint160; - friend class uint256; }; -typedef base_uint<160> base_uint160; -typedef base_uint<256> base_uint256; - - - -// -// uint160 and uint256 could be implemented as templates, but to keep -// compile errors and debugging cleaner, they're copy and pasted. -// - - - -////////////////////////////////////////////////////////////////////////////// -// -// uint160 -// - -/** 160-bit unsigned integer */ -class uint160 : public base_uint160 -{ +/** 160-bit unsigned big integer. */ +class uint160 : public base_uint<160> { public: - typedef base_uint160 basetype; - - uint160() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint160(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint160& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint160(uint64_t b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint160& operator=(uint64_t b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint160(const std::string& str) - { - SetHex(str); - } - - explicit uint160(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } + uint160() {} + uint160(const base_uint<160>& b) : base_uint<160>(b) {} + uint160(uint64_t b) : base_uint<160>(b) {} + explicit uint160(const std::string& str) : base_uint<160>(str) {} + explicit uint160(const std::vector& vch) : base_uint<160>(vch) {} }; -inline bool operator==(const uint160& a, uint64_t b) { return (base_uint160)a == b; } -inline bool operator!=(const uint160& a, uint64_t b) { return (base_uint160)a != b; } -inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; } -inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; } -inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; } -inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; } - -inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; } -inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; } -inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; } -inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; } -inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; } - -inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } - -inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; } - -inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; } -inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; } -inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; } -inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; } -inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; } -inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; } - - - -////////////////////////////////////////////////////////////////////////////// -// -// uint256 -// - -/** 256-bit unsigned integer */ -class uint256 : public base_uint256 -{ +/** 256-bit unsigned big integer. */ +class uint256 : public base_uint<256> { public: - typedef base_uint256 basetype; - - uint256() - { - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - } - - uint256(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - } - - uint256& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - return *this; - } - - uint256(uint64_t b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - } - - uint256& operator=(uint64_t b) - { - pn[0] = (unsigned int)b; - pn[1] = (unsigned int)(b >> 32); - for (int i = 2; i < WIDTH; i++) - pn[i] = 0; - return *this; - } - - explicit uint256(const std::string& str) - { - SetHex(str); - } - - explicit uint256(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - *this = 0; - } + uint256() {} + uint256(const base_uint<256>& b) : base_uint<256>(b) {} + uint256(uint64_t b) : base_uint<256>(b) {} + explicit uint256(const std::string& str) : base_uint<256>(str) {} + explicit uint256(const std::vector& vch) : base_uint<256>(vch) {} }; -inline bool operator==(const uint256& a, uint64_t b) { return (base_uint256)a == b; } -inline bool operator!=(const uint256& a, uint64_t b) { return (base_uint256)a != b; } -inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; } -inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; } -inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; } -inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; } - -inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; } -inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; } -inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; } -inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; } -inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; } - -inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } - -inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; } - -inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; } -inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; } -inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; } -inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; } -inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; } -inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; } -inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; } -inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; } -inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; } -inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; } -inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; } - #endif From 4d480c8a3fe3c58eeb083ea544c6f9e991606692 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 19 Apr 2014 23:25:44 +0200 Subject: [PATCH 027/336] Exception instead of assigning 0 in case of wrong vector length --- src/test/uint256_tests.cpp | 10 +++++----- src/uint256.h | 15 ++++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 815babf107..8e4b63c8bc 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -160,11 +160,11 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality tmpS = ~R2S; BOOST_CHECK(tmpS == ~R2S); tmpS = ~MaxS; BOOST_CHECK(tmpS == ~MaxS); - // Wrong length must give 0 - BOOST_CHECK(uint256(std::vector(OneArray,OneArray+31)) == 0); - BOOST_CHECK(uint256(std::vector(OneArray,OneArray+20)) == 0); - BOOST_CHECK(uint160(std::vector(OneArray,OneArray+32)) == 0); - BOOST_CHECK(uint160(std::vector(OneArray,OneArray+19)) == 0); + // Wrong length must throw exception. + BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+31)), uint_error); + BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+20)), uint_error); + BOOST_CHECK_THROW(uint160(std::vector(OneArray,OneArray+32)), uint_error); + BOOST_CHECK_THROW(uint160(std::vector(OneArray,OneArray+19)), uint_error); } void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) diff --git a/src/uint256.h b/src/uint256.h index a3f7835875..b6365bb36b 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H +#include +#include #include #include #include @@ -19,6 +21,11 @@ inline signed char HexDigit(char c) return p_util_hexdigit[(unsigned char)c]; } +class uint_error : public std::runtime_error { +public: + explicit uint_error(const std::string& str) : std::runtime_error(str) {} +}; + /** Template base class for unsigned big integers. */ template class base_uint @@ -62,11 +69,9 @@ public: explicit base_uint(const std::vector& vch) { - if (vch.size() == sizeof(pn)) { - memcpy(pn, &vch[0], sizeof(pn)); - } else { - *this = 0; - } + if (vch.size() != sizeof(pn)) + throw uint_error("Converting vector of wrong size to base_uint"); + memcpy(pn, &vch[0], sizeof(pn)); } bool operator!() const From a7031507e647da0723bf289dadba10ef1a50f278 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 20 Apr 2014 01:03:19 +0200 Subject: [PATCH 028/336] Add multiplication and division to uint160/uint256 --- src/test/uint256_tests.cpp | 71 ++++++++++++++++++++++++++++++++++++++ src/uint256.h | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 8e4b63c8bc..226d737def 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -482,6 +482,77 @@ BOOST_AUTO_TEST_CASE( plusMinus ) } +BOOST_AUTO_TEST_CASE( multiply ) +{ + BOOST_CHECK((R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10"); + BOOST_CHECK((R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40"); + BOOST_CHECK((R1L * ZeroL) == ZeroL); + BOOST_CHECK((R1L * OneL) == R1L); + BOOST_CHECK((R1L * MaxL) == -R1L); + BOOST_CHECK((R2L * R1L) == (R1L * R2L)); + BOOST_CHECK((R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100"); + BOOST_CHECK((R2L * ZeroL) == ZeroL); + BOOST_CHECK((R2L * OneL) == R2L); + BOOST_CHECK((R2L * MaxL) == -R2L); + + BOOST_CHECK((R1S * R1S).ToString() == "a7761bf30d5237e9873f9bff3642a732c4d84f10"); + BOOST_CHECK((R1S * R2S).ToString() == "ba51c008df851987d9dd323f0e5de07760529c40"); + BOOST_CHECK((R1S * ZeroS) == ZeroS); + BOOST_CHECK((R1S * OneS) == R1S); + BOOST_CHECK((R1S * MaxS) == -R1S); + BOOST_CHECK((R2S * R1S) == (R1S * R2S)); + BOOST_CHECK((R2S * R2S).ToString() == "c28bb2b45a1d85ab7996ccd3e102a650f74ff100"); + BOOST_CHECK((R2S * ZeroS) == ZeroS); + BOOST_CHECK((R2S * OneS) == R2S); + BOOST_CHECK((R2S * MaxS) == -R2S); + + BOOST_CHECK(MaxL * MaxL == OneL); + BOOST_CHECK(MaxS * MaxS == OneS); + + BOOST_CHECK((R1L * 0) == 0); + BOOST_CHECK((R1L * 1) == R1L); + BOOST_CHECK((R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4"); + BOOST_CHECK((R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070"); + BOOST_CHECK((R1S * 0) == 0); + BOOST_CHECK((R1S * 1) == R1S); + BOOST_CHECK((R1S * 7).ToString() == "f7a987f3c3bf758d927f202d7e795faeff084244"); + BOOST_CHECK((R2S * 0xFFFFFFFFUL).ToString() == "1c6f6c930353e17f7d6127213bb18d2883e2cd90"); +} + +BOOST_AUTO_TEST_CASE( divide ) +{ + uint256 D1L("AD7133AC1977FA2B7"); + uint256 D2L("ECD751716"); + BOOST_CHECK((R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a"); + BOOST_CHECK((R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a"); + BOOST_CHECK(R1L / OneL == R1L); + BOOST_CHECK(R1L / MaxL == ZeroL); + BOOST_CHECK(MaxL / R1L == 2); + BOOST_CHECK_THROW(R1L / ZeroL, uint_error); + BOOST_CHECK((R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5"); + BOOST_CHECK((R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4"); + BOOST_CHECK(R2L / OneL == R2L); + BOOST_CHECK(R2L / MaxL == ZeroL); + BOOST_CHECK(MaxL / R2L == 1); + BOOST_CHECK_THROW(R2L / ZeroL, uint_error); + + uint160 D1S("D3C5EDCDEA54EB92679F0A4B4"); + uint160 D2S("13037"); + BOOST_CHECK((R1S / D1S).ToString() == "0000000000000000000000000db9af3beade6c02"); + BOOST_CHECK((R1S / D2S).ToString() == "000098dfb6cc40ca592bf74366794f298ada205c"); + BOOST_CHECK(R1S / OneS == R1S); + BOOST_CHECK(R1S / MaxS == ZeroS); + BOOST_CHECK(MaxS / R1S == 1); + BOOST_CHECK_THROW(R1S / ZeroS, uint_error); + BOOST_CHECK((R2S / D1S).ToString() == "0000000000000000000000000c5608e781182047"); + BOOST_CHECK((R2S / D2S).ToString() == "00008966751b7187c3c67c1fda5cea7db2c1c069"); + BOOST_CHECK(R2S / OneS == R2S); + BOOST_CHECK(R2S / MaxS == ZeroS); + BOOST_CHECK(MaxS / R2S == 1); + BOOST_CHECK_THROW(R2S / ZeroS, uint_error); +} + + bool almostEqual(double d1, double d2) { return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits::epsilon(); diff --git a/src/uint256.h b/src/uint256.h index b6365bb36b..7b17694eb2 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -222,6 +222,57 @@ public: return *this; } + base_uint& operator*=(uint32_t b32) + { + uint64_t carry = 0; + for (int i = 0; i < WIDTH; i++) + { + uint64_t n = carry + (uint64_t)b32 * pn[i]; + pn[i] = n & 0xffffffff; + carry = n >> 32; + } + return *this; + } + + base_uint& operator*=(const base_uint& b) + { + base_uint a = *this; + *this = 0; + for (int j = 0; j < WIDTH; j++) { + uint64_t carry = 0; + for (int i = 0; i + j < WIDTH; i++) { + uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; + pn[i + j] = n & 0xffffffff; + carry = n >> 32; + } + } + return *this; + } + + base_uint& operator/=(const base_uint& b) + { + base_uint div = b; // make a copy, so we can shift. + base_uint num = *this; // make a copy, so we can subtract. + *this = 0; // the quotient. + int num_bits = num.bits(); + int div_bits = div.bits(); + if (div_bits == 0) + throw uint_error("Division by zero"); + if (div_bits > num_bits) // the result is certainly 0. + return *this; + int shift = num_bits - div_bits; + div <<= shift; // shift so that div and nun align. + while (shift >= 0) { + if (num >= div) { + num -= div; + pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. + } + div >>= 1; // shift back. + shift--; + } + // num now contains the remainder of the division. + return *this; + } base_uint& operator++() { @@ -338,11 +389,14 @@ public: friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; } friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; } + friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; } + friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; } friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; } friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; } friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; } friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; } friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; } + friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; } std::string GetHex() const { @@ -417,6 +471,22 @@ public: return sizeof(pn); } + // Returns the position of the highest bit set plus one, or zero if the + // value is zero. + unsigned int bits() const + { + for (int pos = WIDTH-1; pos >= 0; pos--) { + if (pn[pos]) { + for (int bits = 31; bits > 0; bits--) { + if (pn[pos] & 1<= 2); From df9eb5e14fa8072bc8a82b59e712c2ba36f13f4c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 20 Apr 2014 03:19:20 +0200 Subject: [PATCH 029/336] Move {Get,Set}Compact from bignum to uint256 --- src/bignum.h | 65 ------------------- src/chainparams.cpp | 4 +- src/chainparams.h | 4 +- src/main.cpp | 43 +++++++------ src/main.h | 17 +++-- src/miner.cpp | 6 +- src/rpcmining.cpp | 4 +- src/test/DoS_tests.cpp | 4 +- src/test/bignum_tests.cpp | 88 ------------------------- src/test/uint256_tests.cpp | 129 +++++++++++++++++++++++++++++++++++++ src/txdb.cpp | 6 -- src/txdb.h | 2 - src/uint256.h | 70 ++++++++++++++++++++ 13 files changed, 243 insertions(+), 199 deletions(-) diff --git a/src/bignum.h b/src/bignum.h index 0259338b31..6b77462d83 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -269,71 +269,6 @@ public: return vch; } - // The "compact" format is a representation of a whole - // number N using an unsigned 32bit number similar to a - // floating point format. - // The most significant 8 bits are the unsigned exponent of base 256. - // This exponent can be thought of as "number of bytes of N". - // The lower 23 bits are the mantissa. - // Bit number 24 (0x800000) represents the sign of N. - // N = (-1^sign) * mantissa * 256^(exponent-3) - // - // Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). - // MPI uses the most significant bit of the first byte as sign. - // Thus 0x1234560000 is compact (0x05123456) - // and 0xc0de000000 is compact (0x0600c0de) - // (0x05c0de00) would be -0x40de000000 - // - // Bitcoin only uses this "compact" format for encoding difficulty - // targets, which are unsigned 256bit quantities. Thus, all the - // complexities of the sign bit and using base 256 are probably an - // implementation accident. - // - // This implementation directly uses shifts instead of going - // through an intermediate MPI representation. - CBigNum& SetCompact(unsigned int nCompact) - { - unsigned int nSize = nCompact >> 24; - bool fNegative =(nCompact & 0x00800000) != 0; - unsigned int nWord = nCompact & 0x007fffff; - if (nSize <= 3) - { - nWord >>= 8*(3-nSize); - BN_set_word(this, nWord); - } - else - { - BN_set_word(this, nWord); - BN_lshift(this, this, 8*(nSize-3)); - } - BN_set_negative(this, fNegative); - return *this; - } - - unsigned int GetCompact() const - { - unsigned int nSize = BN_num_bytes(this); - unsigned int nCompact = 0; - if (nSize <= 3) - nCompact = BN_get_word(this) << 8*(3-nSize); - else - { - CBigNum bn; - BN_rshift(&bn, this, 8*(nSize-3)); - nCompact = BN_get_word(&bn); - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if (nCompact & 0x00800000) - { - nCompact >>= 8; - nSize++; - } - nCompact |= nSize << 24; - nCompact |= (BN_is_negative(this) ? 0x00800000 : 0); - return nCompact; - } - void SetHex(const std::string& str) { // skip 0x diff --git a/src/chainparams.cpp b/src/chainparams.cpp index eb56800b92..f5cf846a01 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -110,7 +110,7 @@ public: vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; nRPCPort = 8332; - bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32); + bnProofOfWorkLimit = ~uint256(0) >> 32; nSubsidyHalvingInterval = 210000; // Build the genesis block. Note that the output of the genesis coinbase cannot @@ -233,7 +233,7 @@ public: pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; nSubsidyHalvingInterval = 150; - bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); + bnProofOfWorkLimit = ~uint256(0) >> 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; genesis.nNonce = 2; diff --git a/src/chainparams.h b/src/chainparams.h index 542afeaf92..f3f24efd99 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -56,7 +56,7 @@ public: const MessageStartChars& MessageStart() const { return pchMessageStart; } const vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } - const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; } virtual const CBlock& GenesisBlock() const = 0; virtual bool RequireRPCPassword() const { return true; } @@ -75,7 +75,7 @@ protected: vector vAlertPubKey; int nDefaultPort; int nRPCPort; - CBigNum bnProofOfWorkLimit; + uint256 bnProofOfWorkLimit; int nSubsidyHalvingInterval; string strDataDir; vector vSeeds; diff --git a/src/main.cpp b/src/main.cpp index a0f4f40cb1..6a7bb9206c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1209,13 +1209,13 @@ static const int64_t nInterval = nTargetTimespan / nTargetSpacing; // unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) { - const CBigNum &bnLimit = Params().ProofOfWorkLimit(); + const uint256 &bnLimit = Params().ProofOfWorkLimit(); // Testnet has min-difficulty blocks // after nTargetSpacing*2 time between blocks: if (TestNet() && nTime > nTargetSpacing*2) return bnLimit.GetCompact(); - CBigNum bnResult; + uint256 bnResult; bnResult.SetCompact(nBase); while (nTime > 0 && bnResult < bnLimit) { @@ -1274,8 +1274,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead nActualTimespan = nTargetTimespan*4; // Retarget - CBigNum bnNew; + uint256 bnNew; + uint256 bnOld; bnNew.SetCompact(pindexLast->nBits); + bnOld = bnNew; bnNew *= nActualTimespan; bnNew /= nTargetTimespan; @@ -1285,23 +1287,25 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); - LogPrintf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString()); - LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString()); + LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); + LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); return bnNew.GetCompact(); } bool CheckProofOfWork(uint256 hash, unsigned int nBits) { - CBigNum bnTarget; - bnTarget.SetCompact(nBits); + bool fNegative; + bool fOverflow; + uint256 bnTarget; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range - if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit()) + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) return error("CheckProofOfWork() : nBits below minimum work"); // Check proof of work matches claimed amount - if (hash > bnTarget.getuint256()) + if (hash > bnTarget) return error("CheckProofOfWork() : hash doesn't match nBits"); return true; @@ -1346,7 +1350,7 @@ void CheckForkWarningConditions() if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72) pindexBestForkTip = NULL; - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6).getuint256())) + if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6))) { if (!fLargeWorkForkFound) { @@ -1402,7 +1406,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) // We define it this way because it allows us to only store the highest fork tip (+ base) which meets // the 7-block condition and from this always have the most-likely-to-cause-warning fork if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) && - pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() && + pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7) && chainActive.Height() - pindexNewForkTip->nHeight < 72) { pindexBestForkTip = pindexNewForkTip; @@ -1436,10 +1440,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew) if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork) { pindexBestInvalid = pindexNew; - // The current code doesn't actually read the BestInvalidWork entry in - // the block database anymore, as it is derived from the flags in block - // index entry. We only write it for backward compatibility. - pblocktree->WriteBestInvalidWork(CBigNum(pindexBestInvalid->nChainWork)); uiInterface.NotifyBlocksChanged(); } LogPrintf("InvalidChainFound: invalid block=%s height=%d log2_work=%.8g date=%s\n", @@ -2182,7 +2182,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block) pindexNew->pprev = (*miPrev).second; pindexNew->nHeight = pindexNew->pprev->nHeight + 1; } - pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256(); + pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork(); pindexNew->RaiseValidity(BLOCK_VALID_TREE); return pindexNew; @@ -2359,11 +2359,12 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), REJECT_CHECKPOINT, "time-too-old"); } - CBigNum bnNewBlock; - bnNewBlock.SetCompact(block.nBits); - CBigNum bnRequired; + bool fOverflow = false; + uint256 bnNewBlock; + bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow); + uint256 bnRequired; bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); - if (bnNewBlock > bnRequired) + if (fOverflow || bnNewBlock > bnRequired) { return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), REJECT_INVALID, "bad-diffbits"); @@ -2934,7 +2935,7 @@ bool static LoadBlockIndexDB() BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; - pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork().getuint256(); + pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork(); pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx; if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) setBlockIndexValid.insert(pindex); diff --git a/src/main.h b/src/main.h index c69e0d2a3c..796a3031c9 100644 --- a/src/main.h +++ b/src/main.h @@ -10,7 +10,6 @@ #include "bitcoin-config.h" #endif -#include "bignum.h" #include "chainparams.h" #include "coins.h" #include "core.h" @@ -816,13 +815,19 @@ public: return (int64_t)nTime; } - CBigNum GetBlockWork() const + uint256 GetBlockWork() const { - CBigNum bnTarget; - bnTarget.SetCompact(nBits); - if (bnTarget <= 0) + uint256 bnTarget; + bool fNegative; + bool fOverflow; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + if (fNegative || fOverflow || bnTarget == 0) return 0; - return (CBigNum(1)<<256) / (bnTarget+1); + // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 + // as it's too large for a uint256. However, as 2**256 is at least as large + // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, + // or ~bnTarget / (nTarget+1) + 1. + return (~bnTarget / (bnTarget + 1)) + 1; } bool CheckIndex() const diff --git a/src/miner.cpp b/src/miner.cpp index 01fc56601b..50be4fad40 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -466,7 +466,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) { uint256 hash = pblock->GetHash(); - uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); if (hash > hashTarget) return false; @@ -552,7 +552,7 @@ void static BitcoinMiner(CWallet *pwallet) // Search // int64_t nStart = GetTime(); - uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); uint256 hashbuf[2]; uint256& hash = *alignup<16>(hashbuf); while (true) @@ -636,7 +636,7 @@ void static BitcoinMiner(CWallet *pwallet) { // Changing pblock->nTime can change work required on testnet: nBlockBits = ByteReverse(pblock->nBits); - hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + hashTarget.SetCompact(pblock->nBits); } } } } diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 070cf1cb2a..cb903b585a 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -363,7 +363,7 @@ Value getwork(const Array& params, bool fHelp) char phash1[64]; FormatHashBuffers(pblock, pmidstate, pdata, phash1); - uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); Object result; result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated @@ -559,7 +559,7 @@ Value getblocktemplate(const Array& params, bool fHelp) Object aux; aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); - uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); static Array aMutable; if (aMutable.empty()) diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index d86cc7a290..897fb87e46 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -106,9 +106,9 @@ static bool CheckNBits(unsigned int nbits1, int64_t time1, unsigned int nbits2, return CheckNBits(nbits2, time2, nbits1, time1); int64_t deltaTime = time2-time1; - CBigNum required; + uint256 required; required.SetCompact(ComputeMinWork(nbits1, deltaTime)); - CBigNum have; + uint256 have; have.SetCompact(nbits2); return (have <= required); } diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index d5ee8c9778..01967c7684 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -125,94 +125,6 @@ BOOST_AUTO_TEST_CASE(bignum_setint64) } -BOOST_AUTO_TEST_CASE(bignum_SetCompact) -{ - CBigNum num; - num.SetCompact(0); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x00123456); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x01003456); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x02000056); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x03000000); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x04000000); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x00923456); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x01803456); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x02800056); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x03800000); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x04800000); - BOOST_CHECK_EQUAL(num.GetHex(), "0"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - - num.SetCompact(0x01123456); - BOOST_CHECK_EQUAL(num.GetHex(), "12"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); - - // Make sure that we don't generate compacts with the 0x00800000 bit set - num = 0x80; - BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U); - - num.SetCompact(0x01fedcba); - BOOST_CHECK_EQUAL(num.GetHex(), "-7e"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000U); - - num.SetCompact(0x02123456); - BOOST_CHECK_EQUAL(num.GetHex(), "1234"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U); - - num.SetCompact(0x03123456); - BOOST_CHECK_EQUAL(num.GetHex(), "123456"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U); - - num.SetCompact(0x04123456); - BOOST_CHECK_EQUAL(num.GetHex(), "12345600"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U); - - num.SetCompact(0x04923456); - BOOST_CHECK_EQUAL(num.GetHex(), "-12345600"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456U); - - num.SetCompact(0x05009234); - BOOST_CHECK_EQUAL(num.GetHex(), "92340000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U); - - num.SetCompact(0x20123456); - BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U); - - num.SetCompact(0xff123456); - BOOST_CHECK_EQUAL(num.GetHex(), "123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456U); -} - BOOST_AUTO_TEST_CASE(bignum_SetHex) { std::string hexStr = "deecf97fd890808b9cc0f1b6a3e7a60b400f52710e6ad075b1340755bfa58cc9"; diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index 226d737def..4b1a2ae58f 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -675,6 +675,135 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G } } +BOOST_AUTO_TEST_CASE(bignum_SetCompact) +{ + uint256 num; + bool fNegative; + bool fOverflow; + num.SetCompact(0, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x00123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x01003456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x02000056, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x03000000, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x04000000, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x00923456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x01803456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x02800056, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x03800000, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x04800000, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x01123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000012"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + // Make sure that we don't generate compacts with the 0x00800000 bit set + num = 0x80; + BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U); + + num.SetCompact(0x01fedcba, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "000000000000000000000000000000000000000000000000000000000000007e"); + BOOST_CHECK_EQUAL(num.GetCompact(true), 0x01fe0000U); + BOOST_CHECK_EQUAL(fNegative, true); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x02123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000001234"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x03123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000123456"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x04123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x04923456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); + BOOST_CHECK_EQUAL(num.GetCompact(true), 0x04923456U); + BOOST_CHECK_EQUAL(fNegative, true); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x05009234, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000092340000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0x20123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000"); + BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, false); + + num.SetCompact(0xff123456, &fNegative, &fOverflow); + BOOST_CHECK_EQUAL(fNegative, false); + BOOST_CHECK_EQUAL(fOverflow, true); +} + + BOOST_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% coverage { // ~R1L give a base_uint<256> diff --git a/src/txdb.cpp b/src/txdb.cpp index cb92922a35..4eab8525a5 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -73,12 +73,6 @@ bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); } -bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork) -{ - // Obsolete; only written for backward compatibility. - return Write('I', bnBestInvalidWork); -} - bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { return Write(make_pair('f', nFile), info); } diff --git a/src/txdb.h b/src/txdb.h index 5eb5731db3..7257b0dd21 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -14,7 +14,6 @@ #include #include -class CBigNum; class CCoins; class uint256; @@ -52,7 +51,6 @@ private: void operator=(const CBlockTreeDB&); public: bool WriteBlockIndex(const CDiskBlockIndex& blockindex); - bool WriteBestInvalidWork(const CBigNum& bnBestInvalidWork); bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo); bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo); bool ReadLastBlockFile(int &nFile); diff --git a/src/uint256.h b/src/uint256.h index 7b17694eb2..10c6657c76 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -529,6 +529,76 @@ public: uint256(uint64_t b) : base_uint<256>(b) {} explicit uint256(const std::string& str) : base_uint<256>(str) {} explicit uint256(const std::vector& vch) : base_uint<256>(vch) {} + + // The "compact" format is a representation of a whole + // number N using an unsigned 32bit number similar to a + // floating point format. + // The most significant 8 bits are the unsigned exponent of base 256. + // This exponent can be thought of as "number of bytes of N". + // The lower 23 bits are the mantissa. + // Bit number 24 (0x800000) represents the sign of N. + // N = (-1^sign) * mantissa * 256^(exponent-3) + // + // Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). + // MPI uses the most significant bit of the first byte as sign. + // Thus 0x1234560000 is compact (0x05123456) + // and 0xc0de000000 is compact (0x0600c0de) + // (0x05c0de00) would be -0x40de000000 + // + // Bitcoin only uses this "compact" format for encoding difficulty + // targets, which are unsigned 256bit quantities. Thus, all the + // complexities of the sign bit and using base 256 are probably an + // implementation accident. + // + // This implementation directly uses shifts instead of going + // through an intermediate MPI representation. + uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL) + { + int nSize = nCompact >> 24; + uint32_t nWord = nCompact & 0x007fffff; + if (nSize <= 3) + { + nWord >>= 8*(3-nSize); + *this = nWord; + } + else + { + *this = nWord; + *this <<= 8*(nSize-3); + } + if (pfNegative) + *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; + if (pfOverflow) + *pfOverflow = nWord != 0 && ((nSize > 34) || + (nWord > 0xff && nSize > 33) || + (nWord > 0xffff && nSize > 32)); + return *this; + } + + uint32_t GetCompact(bool fNegative = false) const + { + int nSize = (bits() + 7) / 8; + uint32_t nCompact = 0; + if (nSize <= 3) + nCompact = GetLow64() << 8*(3-nSize); + else + { + uint256 bn = *this >> 8*(nSize-3); + nCompact = bn.GetLow64(); + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if (nCompact & 0x00800000) + { + nCompact >>= 8; + nSize++; + } + assert((nCompact & ~0x007fffff) == 0); + assert(nSize < 256); + nCompact |= nSize << 24; + nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); + return nCompact; + } }; #endif From 397668ea63e148a92f68e9fae578595585616770 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 21 Apr 2014 08:28:43 +0200 Subject: [PATCH 030/336] Deduplicate uint* comparison operator logic --- src/uint256.h | 93 ++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 71 deletions(-) diff --git a/src/uint256.h b/src/uint256.h index 10c6657c76..1acedd14bf 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -308,85 +308,28 @@ public: return ret; } + int CompareTo(const base_uint& b) const { + for (int i = base_uint::WIDTH-1; i >= 0; i--) { + if (pn[i] < b.pn[i]) + return -1; + if (pn[i] > b.pn[i]) + return 1; + } + return 0; + } - friend inline bool operator<(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] < b.pn[i]) - return true; - else if (a.pn[i] > b.pn[i]) + bool EqualTo(uint64_t b) const { + for (int i = base_uint::WIDTH-1; i >= 2; i--) { + if (pn[i]) return false; } - return false; - } - - friend inline bool operator<=(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] < b.pn[i]) - return true; - else if (a.pn[i] > b.pn[i]) - return false; - } - return true; - } - - friend inline bool operator>(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] > b.pn[i]) - return true; - else if (a.pn[i] < b.pn[i]) - return false; - } - return false; - } - - friend inline bool operator>=(const base_uint& a, const base_uint& b) - { - for (int i = base_uint::WIDTH-1; i >= 0; i--) - { - if (a.pn[i] > b.pn[i]) - return true; - else if (a.pn[i] < b.pn[i]) - return false; - } - return true; - } - - friend inline bool operator==(const base_uint& a, const base_uint& b) - { - for (int i = 0; i < base_uint::WIDTH; i++) - if (a.pn[i] != b.pn[i]) - return false; - return true; - } - - friend inline bool operator==(const base_uint& a, uint64_t b) - { - if (a.pn[0] != (unsigned int)b) + if (pn[1] != (b >> 32)) return false; - if (a.pn[1] != (unsigned int)(b >> 32)) + if (pn[0] != (b & 0xfffffffful)) return false; - for (int i = 2; i < base_uint::WIDTH; i++) - if (a.pn[i] != 0) - return false; return true; } - friend inline bool operator!=(const base_uint& a, const base_uint& b) - { - return (!(a == b)); - } - - friend inline bool operator!=(const base_uint& a, uint64_t b) - { - return (!(a == b)); - } - friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; } friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; } friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; } @@ -397,6 +340,14 @@ public: friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; } friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; } friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; } + friend inline bool operator==(const base_uint& a, const base_uint& b) { return a.CompareTo(b) == 0; } + friend inline bool operator!=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) != 0; } + friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; } + friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; } + friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; } + friend inline bool operator<=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) <= 0; } + friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); } + friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); } std::string GetHex() const { From 0d4ea1cf8a349cf59795ac68645afe70e98c6b3a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 3 May 2014 10:20:58 +0200 Subject: [PATCH 031/336] util: add parseint32 function with strict error reporting None of the current integer parsing functions in util check whether the result is valid and fits in the range of the type. This is required for less sloppy error reporting. --- src/test/util_tests.cpp | 22 ++++++++++++++++++++++ src/util.cpp | 14 ++++++++++++++ src/util.h | 7 +++++++ 3 files changed, 43 insertions(+) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index b8f107f644..7e7c05a59d 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -342,4 +342,26 @@ BOOST_AUTO_TEST_CASE(gettime) BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0); } +BOOST_AUTO_TEST_CASE(test_ParseInt32) +{ + int32_t n; + // Valid values + BOOST_CHECK(ParseInt32("1234", NULL)); + BOOST_CHECK(ParseInt32("0", &n) && n == 0); + BOOST_CHECK(ParseInt32("1234", &n) && n == 1234); + BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal + BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647); + BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648); + BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234); + // Invalid values + BOOST_CHECK(!ParseInt32("1a", &n)); + BOOST_CHECK(!ParseInt32("aap", &n)); + BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex + // Overflow and underflow + BOOST_CHECK(!ParseInt32("-2147483649", NULL)); + BOOST_CHECK(!ParseInt32("2147483648", NULL)); + BOOST_CHECK(!ParseInt32("-32482348723847471234", NULL)); + BOOST_CHECK(!ParseInt32("32482348723847471234", NULL)); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.cpp b/src/util.cpp index a919b4b854..36ac23b1d5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1427,3 +1427,17 @@ void RenameThread(const char* name) #endif } +bool ParseInt32(const std::string& str, int32_t *out) +{ + char *endp = NULL; + errno = 0; // strtol will not set errno if valid + long int n = strtol(str.c_str(), &endp, 10); + if(out) *out = (int)n; + // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow + // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit + // platforms the size of these types may be different. + return endp && *endp == 0 && !errno && + n >= std::numeric_limits::min() && + n <= std::numeric_limits::max(); +} + diff --git a/src/util.h b/src/util.h index fbd841f7a8..fa1e664c92 100644 --- a/src/util.h +++ b/src/util.h @@ -256,6 +256,13 @@ inline int atoi(const std::string& str) return atoi(str.c_str()); } +/** + * Convert string to signed 32-bit integer with strict parse error feedback. + * @returns true if the entire string could be parsed as valid integer, + * false if not the entire string could be parsed or when overflow or underflow occured. + */ +bool ParseInt32(const std::string& str, int32_t *out); + inline int roundint(double d) { return (int)(d > 0 ? d + 0.5 : d - 0.5); From d8642752992799b0695cf97ada03c56d0526830c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 3 May 2014 10:25:58 +0200 Subject: [PATCH 032/336] Use new function parseint32 in SplitHostPort Use the new function parseint32 in SplitHostPort instead of calling strtol directly. --- src/netbase.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index ec275f738c..4f7e3f6b78 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -47,12 +47,10 @@ void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos); if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) { - char *endp = NULL; - int n = strtol(in.c_str() + colon + 1, &endp, 10); - if (endp && *endp == 0 && n >= 0) { + int32_t n; + if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) { in = in.substr(0, colon); - if (n > 0 && n < 0x10000) - portOut = n; + portOut = n; } } if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']') From e16be73753d870c5ce77094d3a402bbe8e3bf542 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Apr 2014 11:08:57 +0200 Subject: [PATCH 033/336] net: Add CSubNet class for subnet matching --- src/netbase.cpp | 123 ++++++++++++++++++++++++++++++++++++- src/netbase.h | 30 +++++++++ src/test/netbase_tests.cpp | 37 +++++++++++ 3 files changed, 187 insertions(+), 3 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 4f7e3f6b78..82a681281d 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -546,6 +546,22 @@ void CNetAddr::SetIP(const CNetAddr& ipIn) memcpy(ip, ipIn.ip, sizeof(ip)); } +void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) +{ + switch(network) + { + case NET_IPV4: + memcpy(ip, pchIPv4, 12); + memcpy(ip+12, ip_in, 4); + break; + case NET_IPV6: + memcpy(ip, ip_in, 16); + break; + default: + assert(!"invalid network"); + } +} + static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; bool CNetAddr::SetSpecial(const std::string &strName) @@ -569,13 +585,12 @@ CNetAddr::CNetAddr() CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) { - memcpy(ip, pchIPv4, 12); - memcpy(ip+12, &ipv4Addr, 4); + SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); } CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) { - memcpy(ip, &ipv6Addr, 16); + SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr); } CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) @@ -1120,3 +1135,105 @@ void CService::SetPort(unsigned short portIn) { port = portIn; } + +CSubNet::CSubNet(): + valid(false) +{ + memset(netmask, 0, sizeof(netmask)); +} + +CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup) +{ + size_t slash = strSubnet.find_last_of('/'); + std::vector vIP; + + valid = true; + // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address + memset(netmask, 255, sizeof(netmask)); + + std::string strAddress = strSubnet.substr(0, slash); + if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup)) + { + network = vIP[0]; + if (slash != strSubnet.npos) + { + std::string strNetmask = strSubnet.substr(slash + 1); + int32_t n; + // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n + int noffset = network.IsIPv4() ? (12 * 8) : 0; + if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex + { + if(n >= 0 && n <= (128 - noffset)) // Only valid if in range of bits of address + { + n += noffset; + // Clear bits [n..127] + for (; n < 128; ++n) + netmask[n>>3] &= ~(1<<(n&7)); + } + else + { + valid = false; + } + } + else // If not a valid number, try full netmask syntax + { + if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask + { + // Remember: GetByte returns bytes in reversed order + // Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as + // we don't want pchIPv4 to be part of the mask. + int asize = network.IsIPv4() ? 4 : 16; + for(int x=0; x Date: Mon, 28 Apr 2014 13:48:26 +0200 Subject: [PATCH 034/336] rpc: Use netmasks instead of wildcards for IP address matching `-rpcallowip` currently has a wacky wildcard-based format. After this commit it will accept the more standard format, for example: - Ranges with netmask 127.0.0.0/255.255.255.0, ::/0 - Ranges with cidr 12.3.4.5/24, 12:34:56:78:9a:bc:de:00/112 - Loose IPs ::1, 127.0.0.1 Trying to use the old *?-based format will result in an error message at launch. --- src/rpcserver.cpp | 59 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f78cb420f4..5740cca13a 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -38,6 +38,7 @@ static map > deadlineTimers; static ssl::context* rpc_ssl_context = NULL; static boost::thread_group* rpc_worker_group = NULL; static boost::asio::io_service::work *rpc_dummy_work = NULL; +static std::vector rpc_allow_subnets; //!< List of subnets to allow RPC connections from void RPCTypeCheck(const Array& params, const list& typesExpected, @@ -358,25 +359,34 @@ void ErrorReply(std::ostream& stream, const Object& objError, const Value& id) stream << HTTPReply(nStatus, strReply, false) << std::flush; } -bool ClientAllowed(const boost::asio::ip::address& address) +// Convert boost::asio address to CNetAddr +static CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address) { + CNetAddr netaddr; // Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses if (address.is_v6() && (address.to_v6().is_v4_compatible() || address.to_v6().is_v4_mapped())) - return ClientAllowed(address.to_v6().to_v4()); + address = address.to_v6().to_v4(); - if (address == asio::ip::address_v4::loopback() - || address == asio::ip::address_v6::loopback() - || (address.is_v4() - // Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet) - && (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000)) - return true; + if(address.is_v4()) + { + boost::asio::ip::address_v4::bytes_type bytes = address.to_v4().to_bytes(); + netaddr.SetRaw(NET_IPV4, &bytes[0]); + } + else + { + boost::asio::ip::address_v6::bytes_type bytes = address.to_v6().to_bytes(); + netaddr.SetRaw(NET_IPV6, &bytes[0]); + } + return netaddr; +} - const string strAddress = address.to_string(); - const vector& vAllow = mapMultiArgs["-rpcallowip"]; - BOOST_FOREACH(string strAllow, vAllow) - if (WildcardMatch(strAddress, strAllow)) +bool ClientAllowed(const boost::asio::ip::address& address) +{ + CNetAddr netaddr = BoostAsioToCNetAddr(address); + BOOST_FOREACH(const CSubNet &subnet, rpc_allow_subnets) + if (subnet.Match(netaddr)) return true; return false; } @@ -502,6 +512,31 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor& vAllow = mapMultiArgs["-rpcallowip"]; + BOOST_FOREACH(string strAllow, vAllow) + { + CSubNet subnet(strAllow); + if(!subnet.IsValid()) + { + uiInterface.ThreadSafeMessageBox( + strprintf("Invalid -rpcallowip subnet specification: %s", strAllow), + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return; + } + rpc_allow_subnets.push_back(subnet); + } + } + std::string strAllowed; + BOOST_FOREACH(const CSubNet &subnet, rpc_allow_subnets) + strAllowed += subnet.ToString() + " "; + LogPrint("rpc", "Allowing RPC connections from: %s\n", strAllowed); + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; if (((mapArgs["-rpcpassword"] == "") || (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword()) From fdbd7075cab8d54f90c038e68afba868a9ff9f63 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Apr 2014 13:48:57 +0200 Subject: [PATCH 035/336] Remove unused function WildcardMatch No longer necessary after implementing netmask-based matching. Also remove a longer-unused function `skipspaces`. --- src/test/util_tests.cpp | 11 ----------- src/util.cpp | 37 ------------------------------------- src/util.h | 9 --------- 3 files changed, 57 deletions(-) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 7e7c05a59d..f4ca8c0539 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -165,17 +165,6 @@ BOOST_AUTO_TEST_CASE(util_GetArg) BOOST_CHECK_EQUAL(GetBoolArg("booltest4", false), true); } -BOOST_AUTO_TEST_CASE(util_WildcardMatch) -{ - BOOST_CHECK(WildcardMatch("127.0.0.1", "*")); - BOOST_CHECK(WildcardMatch("127.0.0.1", "127.*")); - BOOST_CHECK(WildcardMatch("abcdef", "a?cde?")); - BOOST_CHECK(!WildcardMatch("abcdef", "a?cde??")); - BOOST_CHECK(WildcardMatch("abcdef", "a*f")); - BOOST_CHECK(!WildcardMatch("abcdef", "a*x")); - BOOST_CHECK(WildcardMatch("", "*")); -} - BOOST_AUTO_TEST_CASE(util_FormatMoney) { BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00"); diff --git a/src/util.cpp b/src/util.cpp index 36ac23b1d5..00e29446d5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -889,43 +889,6 @@ string DecodeBase32(const string& str) return string((const char*)&vchRet[0], vchRet.size()); } - -bool WildcardMatch(const char* psz, const char* mask) -{ - while (true) - { - switch (*mask) - { - case '\0': - return (*psz == '\0'); - case '*': - return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask)); - case '?': - if (*psz == '\0') - return false; - break; - default: - if (*psz != *mask) - return false; - break; - } - psz++; - mask++; - } -} - -bool WildcardMatch(const string& str, const string& mask) -{ - return WildcardMatch(str.c_str(), mask.c_str()); -} - - - - - - - - static std::string FormatException(std::exception* pex, const char* pszThread) { #ifdef WIN32 diff --git a/src/util.h b/src/util.h index fa1e664c92..011a40e540 100644 --- a/src/util.h +++ b/src/util.h @@ -182,8 +182,6 @@ std::string DecodeBase32(const std::string& str); std::string EncodeBase32(const unsigned char* pch, size_t len); std::string EncodeBase32(const std::string& str); void ParseParameters(int argc, const char*const argv[]); -bool WildcardMatch(const char* psz, const char* mask); -bool WildcardMatch(const std::string& str, const std::string& mask); void FileCommit(FILE *fileout); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); @@ -348,13 +346,6 @@ inline std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) return pszTime; } -template -void skipspaces(T& it) -{ - while (isspace(*it)) - ++it; -} - inline bool IsSwitchChar(char c) { #ifdef WIN32 From 21bf3d257b88c45e2bb0b47e36e73d7462760c2c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Apr 2014 15:23:29 +0200 Subject: [PATCH 036/336] Add tests for BoostAsioToCNetAddr --- src/rpcserver.cpp | 3 +-- src/rpcserver.h | 4 ++++ src/test/rpc_tests.cpp | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 5740cca13a..ac40ea7cf1 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -359,8 +359,7 @@ void ErrorReply(std::ostream& stream, const Object& objError, const Value& id) stream << HTTPReply(nStatus, strReply, false) << std::flush; } -// Convert boost::asio address to CNetAddr -static CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address) +CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address) { CNetAddr netaddr; // Make sure that IPv4-compatible and IPv4-mapped IPv6 addresses are treated as IPv4 addresses diff --git a/src/rpcserver.h b/src/rpcserver.h index 1092c691be..e8cd2cd0fc 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -19,6 +19,7 @@ #include "json/json_spirit_writer_template.h" class CBlockIndex; +class CNetAddr; /* Start RPC threads */ void StartRPCThreads(); @@ -50,6 +51,9 @@ void RPCTypeCheck(const json_spirit::Object& o, */ void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds); +//! Convert boost::asio address to CNetAddr +extern CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address); + typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp); class CRPCCommand diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 5bc38ce2de..107c0f06e7 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -6,6 +6,7 @@ #include "rpcclient.h" #include "base58.h" +#include "netbase.h" #include #include @@ -138,4 +139,19 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_CHECK(AmountFromValue(ValueFromString("20999999.99999999")) == 2099999999999999LL); } +BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) +{ + // Check IPv4 addresses + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("1.2.3.4")).ToString(), "1.2.3.4"); + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("127.0.0.1")).ToString(), "127.0.0.1"); + // Check IPv6 addresses + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::1")).ToString(), "::1"); + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("123:4567:89ab:cdef:123:4567:89ab:cdef")).ToString(), + "123:4567:89ab:cdef:123:4567:89ab:cdef"); + // v4 compatible must be interpreted as IPv4 + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::0:127.0.0.1")).ToString(), "127.0.0.1"); + // v4 mapped must be interpreted as IPv4 + BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1"); +} + BOOST_AUTO_TEST_SUITE_END() From ccc84e0963dab2ee6276ccc9766c2c19b0ebb3e3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 May 2014 17:38:44 +0200 Subject: [PATCH 037/336] Reduce bignum.h now it is only needed for scriptnum_tests --- src/bignum.h | 355 +------------------------------------- src/chainparams.h | 1 - src/protocol.h | 1 + src/test/DoS_tests.cpp | 1 - src/test/Makefile.am | 1 - src/test/bignum_tests.cpp | 136 --------------- 6 files changed, 3 insertions(+), 492 deletions(-) delete mode 100644 src/test/bignum_tests.cpp diff --git a/src/bignum.h b/src/bignum.h index 6b77462d83..b57800f372 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -6,17 +6,14 @@ #ifndef BITCOIN_BIGNUM_H #define BITCOIN_BIGNUM_H -#include "serialize.h" -#include "uint256.h" -#include "version.h" - +#include +#include #include #include #include #include -/** Errors thrown by the bignum class */ class bignum_error : public std::runtime_error { public: @@ -24,34 +21,6 @@ public: }; -/** RAII encapsulated BN_CTX (OpenSSL bignum context) */ -class CAutoBN_CTX -{ -protected: - BN_CTX* pctx; - BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; } - -public: - CAutoBN_CTX() - { - pctx = BN_CTX_new(); - if (pctx == NULL) - throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL"); - } - - ~CAutoBN_CTX() - { - if (pctx != NULL) - BN_CTX_free(pctx); - } - - operator BN_CTX*() { return pctx; } - BN_CTX& operator*() { return *pctx; } - BN_CTX** operator&() { return &pctx; } - bool operator!() { return (pctx == NULL); } -}; - - /** C++ wrapper for BIGNUM (OpenSSL bignum) */ class CBigNum : public BIGNUM { @@ -83,18 +52,7 @@ public: BN_clear_free(this); } - //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. - CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } CBigNum(long long n) { BN_init(this); setint64(n); } - CBigNum(unsigned char n) { BN_init(this); setulong(n); } - CBigNum(unsigned short n) { BN_init(this); setulong(n); } - CBigNum(unsigned int n) { BN_init(this); setulong(n); } - CBigNum(unsigned long n) { BN_init(this); setulong(n); } - CBigNum(unsigned long long n) { BN_init(this); setuint64(n); } - explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); } explicit CBigNum(const std::vector& vch) { @@ -102,22 +60,6 @@ public: setvch(vch); } - void setulong(unsigned long n) - { - if (!BN_set_word(this, n)) - throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); - } - - unsigned long getulong() const - { - return BN_get_word(this); - } - - unsigned int getuint() const - { - return BN_get_word(this); - } - int getint() const { unsigned long n = BN_get_word(this); @@ -172,76 +114,6 @@ public: BN_mpi2bn(pch, p - pch, this); } - void setuint64(uint64_t n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - for (int i = 0; i < 8; i++) - { - unsigned char c = (n >> 56) & 0xff; - n <<= 8; - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - void setuint256(uint256 n) - { - unsigned char pch[sizeof(n) + 6]; - unsigned char* p = pch + 4; - bool fLeadingZeroes = true; - unsigned char* pbegin = (unsigned char*)&n; - unsigned char* psrc = pbegin + sizeof(n); - while (psrc != pbegin) - { - unsigned char c = *(--psrc); - if (fLeadingZeroes) - { - if (c == 0) - continue; - if (c & 0x80) - *p++ = 0; - fLeadingZeroes = false; - } - *p++ = c; - } - unsigned int nSize = p - (pch + 4); - pch[0] = (nSize >> 24) & 0xff; - pch[1] = (nSize >> 16) & 0xff; - pch[2] = (nSize >> 8) & 0xff; - pch[3] = (nSize >> 0) & 0xff; - BN_mpi2bn(pch, p - pch, this); - } - - uint256 getuint256() const - { - unsigned int nSize = BN_bn2mpi(this, NULL); - if (nSize < 4) - return 0; - std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); - if (vch.size() > 4) - vch[4] &= 0x7f; - uint256 n = 0; - for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--) - ((unsigned char*)&n)[i] = vch[j]; - return n; - } - void setvch(const std::vector& vch) { std::vector vch2(vch.size() + 4); @@ -269,188 +141,7 @@ public: return vch; } - void SetHex(const std::string& str) - { - // skip 0x - const char* psz = str.c_str(); - while (isspace(*psz)) - psz++; - bool fNegative = false; - if (*psz == '-') - { - fNegative = true; - psz++; - } - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - while (isspace(*psz)) - psz++; - - // hex string to bignum - *this = 0; - int n; - while ((n = HexDigit(*psz)) != -1) - { - *this <<= 4; - *this += n; - ++psz; - } - if (fNegative) - *this = 0 - *this; - } - - std::string ToString(int nBase=10) const - { - CAutoBN_CTX pctx; - CBigNum bnBase = nBase; - CBigNum bn0 = 0; - std::string str; - CBigNum bn = *this; - BN_set_negative(&bn, false); - CBigNum dv; - CBigNum rem; - if (BN_cmp(&bn, &bn0) == 0) - return "0"; - while (BN_cmp(&bn, &bn0) > 0) - { - if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) - throw bignum_error("CBigNum::ToString() : BN_div failed"); - bn = dv; - unsigned int c = rem.getulong(); - str += "0123456789abcdef"[c]; - } - if (BN_is_negative(this)) - str += "-"; - reverse(str.begin(), str.end()); - return str; - } - - std::string GetHex() const - { - return ToString(16); - } - - unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const - { - return ::GetSerializeSize(getvch(), nType, nVersion); - } - - template - void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const - { - ::Serialize(s, getvch(), nType, nVersion); - } - - template - void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) - { - std::vector vch; - ::Unserialize(s, vch, nType, nVersion); - setvch(vch); - } - - - bool operator!() const - { - return BN_is_zero(this); - } - - CBigNum& operator+=(const CBigNum& b) - { - if (!BN_add(this, this, &b)) - throw bignum_error("CBigNum::operator+= : BN_add failed"); - return *this; - } - - CBigNum& operator-=(const CBigNum& b) - { - *this = *this - b; - return *this; - } - - CBigNum& operator*=(const CBigNum& b) - { - CAutoBN_CTX pctx; - if (!BN_mul(this, this, &b, pctx)) - throw bignum_error("CBigNum::operator*= : BN_mul failed"); - return *this; - } - - CBigNum& operator/=(const CBigNum& b) - { - *this = *this / b; - return *this; - } - - CBigNum& operator%=(const CBigNum& b) - { - *this = *this % b; - return *this; - } - - CBigNum& operator<<=(unsigned int shift) - { - if (!BN_lshift(this, this, shift)) - throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); - return *this; - } - - CBigNum& operator>>=(unsigned int shift) - { - // Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number - // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL - CBigNum a = 1; - a <<= shift; - if (BN_cmp(&a, this) > 0) - { - *this = 0; - return *this; - } - - if (!BN_rshift(this, this, shift)) - throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); - return *this; - } - - - CBigNum& operator++() - { - // prefix operator - if (!BN_add(this, this, BN_value_one())) - throw bignum_error("CBigNum::operator++ : BN_add failed"); - return *this; - } - - const CBigNum operator++(int) - { - // postfix operator - const CBigNum ret = *this; - ++(*this); - return ret; - } - - CBigNum& operator--() - { - // prefix operator - CBigNum r; - if (!BN_sub(&r, this, BN_value_one())) - throw bignum_error("CBigNum::operator-- : BN_sub failed"); - *this = r; - return *this; - } - - const CBigNum operator--(int) - { - // postfix operator - const CBigNum ret = *this; - --(*this); - return ret; - } - - friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); }; @@ -478,48 +169,6 @@ inline const CBigNum operator-(const CBigNum& a) return r; } -inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_mul(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator* : BN_mul failed"); - return r; -} - -inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_div(&r, NULL, &a, &b, pctx)) - throw bignum_error("CBigNum::operator/ : BN_div failed"); - return r; -} - -inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) -{ - CAutoBN_CTX pctx; - CBigNum r; - if (!BN_mod(&r, &a, &b, pctx)) - throw bignum_error("CBigNum::operator% : BN_div failed"); - return r; -} - -inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) -{ - CBigNum r; - if (!BN_lshift(&r, &a, shift)) - throw bignum_error("CBigNum:operator<< : BN_lshift failed"); - return r; -} - -inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) -{ - CBigNum r = a; - r >>= shift; - return r; -} - inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } diff --git a/src/chainparams.h b/src/chainparams.h index f3f24efd99..5600b904cc 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -6,7 +6,6 @@ #ifndef BITCOIN_CHAIN_PARAMS_H #define BITCOIN_CHAIN_PARAMS_H -#include "bignum.h" #include "uint256.h" #include diff --git a/src/protocol.h b/src/protocol.h index 86e08ddcfa..e6f105fe5c 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -14,6 +14,7 @@ #include "netbase.h" #include "serialize.h" #include "uint256.h" +#include "version.h" #include #include diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 897fb87e46..fb06fb3435 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -8,7 +8,6 @@ -#include "bignum.h" #include "keystore.h" #include "main.h" #include "net.h" diff --git a/src/test/Makefile.am b/src/test/Makefile.am index e12f4904f1..fbc79cf996 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -37,7 +37,6 @@ test_bitcoin_SOURCES = \ base32_tests.cpp \ base58_tests.cpp \ base64_tests.cpp \ - bignum_tests.cpp \ bloom_tests.cpp \ canonical_tests.cpp \ checkblock_tests.cpp \ diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp deleted file mode 100644 index 01967c7684..0000000000 --- a/src/test/bignum_tests.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2012-2014 The Bitcoin Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "bignum.h" - -#include -#include - -#include - -BOOST_AUTO_TEST_SUITE(bignum_tests) - -// Unfortunately there's no standard way of preventing a function from being -// inlined, so we define a macro for it. -// -// You should use it like this: -// NOINLINE void function() {...} -#if defined(__GNUC__) -// This also works and will be defined for any compiler implementing GCC -// extensions, such as Clang and ICC. -#define NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define NOINLINE __declspec(noinline) -#else -// We give out a warning because it impacts the correctness of one bignum test. -#warning You should define NOINLINE for your compiler. -#define NOINLINE -#endif - -// For the following test case, it is useful to use additional tools. -// -// The simplest one to use is the compiler flag -ftrapv, which detects integer -// overflows and similar errors. However, due to optimizations and compilers -// taking advantage of undefined behavior sometimes it may not actually detect -// anything. -// -// You can also use compiler-based stack protection to possibly detect possible -// stack buffer overruns. -// -// For more accurate diagnostics, you can use an undefined arithmetic operation -// detector such as the clang's undefined behaviour checker. -// See also: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation -// -// It might also be useful to use Google's AddressSanitizer to detect -// stack buffer overruns, which valgrind can't currently detect. - -// Let's force this code not to be inlined, in order to actually -// test a generic version of the function. This increases the chance -// that -ftrapv will detect overflows. -NOINLINE void mysetint64(CBigNum& num, int64_t n) -{ - num.setint64(n); -} - -// For each number, we do 2 tests: one with inline code, then we reset the -// value to 0, then the second one with a non-inlined function. -BOOST_AUTO_TEST_CASE(bignum_setint64) -{ - int64_t n; - - { - n = 0; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "0"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "0"); - } - { - n = 1; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "1"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "1"); - } - { - n = -1; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-1"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-1"); - } - { - n = 5; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "5"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "5"); - } - { - n = -5; - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-5"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-5"); - } - { - n = std::numeric_limits::min(); - CBigNum num(n); - BOOST_CHECK(num.ToString() == "-9223372036854775808"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "-9223372036854775808"); - } - { - n = std::numeric_limits::max(); - CBigNum num(n); - BOOST_CHECK(num.ToString() == "9223372036854775807"); - num.setulong(0); - BOOST_CHECK(num.ToString() == "0"); - mysetint64(num, n); - BOOST_CHECK(num.ToString() == "9223372036854775807"); - } -} - - -BOOST_AUTO_TEST_CASE(bignum_SetHex) -{ - std::string hexStr = "deecf97fd890808b9cc0f1b6a3e7a60b400f52710e6ad075b1340755bfa58cc9"; - CBigNum num; - num.SetHex(hexStr); - BOOST_CHECK_EQUAL(num.GetHex(), hexStr); -} - -BOOST_AUTO_TEST_SUITE_END() From 7cd0af7cc222d0694ce72e71458aef460698ee2c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 May 2014 17:56:16 +0200 Subject: [PATCH 038/336] Move bignum.h to test/ --- src/Makefile.am | 2 +- src/test/Makefile.am | 1 + src/{ => test}/bignum.h | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename src/{ => test}/bignum.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 215d0319f9..a49ad58716 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,7 +28,7 @@ BITCOIN_CORE_H = \ addrman.h \ alert.h \ allocators.h \ - base58.h bignum.h \ + base58.h \ bloom.h \ chainparams.h \ checkpoints.h \ diff --git a/src/test/Makefile.am b/src/test/Makefile.am index fbc79cf996..cde3a31e2f 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -32,6 +32,7 @@ endif test_bitcoin_LDADD += $(BDB_LIBS) test_bitcoin_SOURCES = \ + bignum.h \ alert_tests.cpp \ allocator_tests.cpp \ base32_tests.cpp \ diff --git a/src/bignum.h b/src/test/bignum.h similarity index 100% rename from src/bignum.h rename to src/test/bignum.h From 938b68984668445035b2505e1b7ec07649dd2bbc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 May 2014 18:23:34 +0200 Subject: [PATCH 039/336] Squashed 'src/leveldb/' changes from 9094c7f..7924331 42dcc7e Merge upstream LevelDB 1.17. e353fbc Release LevelDB 1.17 269fc6c Release LevelDB 1.16 REVERT: 9094c7f Temporarily revert to writing .sst files instead of .ldb git-subtree-dir: src/leveldb git-subtree-split: 79243314e40ac31d79c68e5658a1d6a64800d50b --- Makefile | 11 ++++++----- db/filename.cc | 9 ++------- db/log_reader.cc | 23 +++++++++++++++-------- db/log_test.cc | 40 +++++++++++++++++++++++++++++++++++----- db/repair.cc | 1 - db/version_set.cc | 14 -------------- include/leveldb/c.h | 1 - include/leveldb/db.h | 2 +- include/leveldb/slice.h | 2 +- 9 files changed, 60 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index 344ff2972a..f8903b69e4 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ SHARED = $(SHARED1) else # Update db.h if you change these. SHARED_MAJOR = 1 -SHARED_MINOR = 15 +SHARED_MINOR = 17 SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) SHARED2 = $(SHARED1).$(SHARED_MAJOR) SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR) @@ -190,19 +190,20 @@ PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBundleShortVersionString) +IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 .cc.o: mkdir -p ios-x86/$(dir $@) - $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@ + $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ mkdir -p ios-arm/$(dir $@) - xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@ + xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ lipo ios-x86/$@ ios-arm/$@ -create -output $@ .c.o: mkdir -p ios-x86/$(dir $@) - $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@ + $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ mkdir -p ios-arm/$(dir $@) - xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@ + xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ lipo ios-x86/$@ ios-arm/$@ -create -output $@ else diff --git a/db/filename.cc b/db/filename.cc index 27d750697b..da32946d99 100644 --- a/db/filename.cc +++ b/db/filename.cc @@ -29,19 +29,14 @@ std::string LogFileName(const std::string& name, uint64_t number) { return MakeFileName(name, number, "log"); } -// TableFileName returns the filenames we usually write to, while -// SSTTableFileName returns the alternative filenames we also try to read from -// for backward compatibility. For now, swap them around. -// TODO: when compatibility is no longer necessary, swap them back -// (TableFileName to use "ldb" and SSTTableFileName to use "sst"). std::string TableFileName(const std::string& name, uint64_t number) { assert(number > 0); - return MakeFileName(name, number, "sst"); + return MakeFileName(name, number, "ldb"); } std::string SSTTableFileName(const std::string& name, uint64_t number) { assert(number > 0); - return MakeFileName(name, number, "ldb"); + return MakeFileName(name, number, "sst"); } std::string DescriptorFileName(const std::string& dbname, uint64_t number) { diff --git a/db/log_reader.cc b/db/log_reader.cc index b35f115aad..4919216d04 100644 --- a/db/log_reader.cc +++ b/db/log_reader.cc @@ -133,7 +133,9 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) { case kEof: if (in_fragmented_record) { - ReportCorruption(scratch->size(), "partial record without end(3)"); + // This can be caused by the writer dying immediately after + // writing a physical record but before completing the next; don't + // treat it as a corruption, just ignore the entire logical record. scratch->clear(); } return false; @@ -193,13 +195,12 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result) { eof_ = true; } continue; - } else if (buffer_.size() == 0) { - // End of file - return kEof; } else { - size_t drop_size = buffer_.size(); + // Note that if buffer_ is non-empty, we have a truncated header at the + // end of the file, which can be caused by the writer crashing in the + // middle of writing the header. Instead of considering this an error, + // just report EOF. buffer_.clear(); - ReportCorruption(drop_size, "truncated record at end of file"); return kEof; } } @@ -213,8 +214,14 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result) { if (kHeaderSize + length > buffer_.size()) { size_t drop_size = buffer_.size(); buffer_.clear(); - ReportCorruption(drop_size, "bad record length"); - return kBadRecord; + if (!eof_) { + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + // If the end of the file has been reached without reading |length| bytes + // of payload, assume the writer died in the middle of writing the record. + // Don't report a corruption. + return kEof; } if (type == kZeroType && length == 0) { diff --git a/db/log_test.cc b/db/log_test.cc index 4c5cf87573..91d3caafc3 100644 --- a/db/log_test.cc +++ b/db/log_test.cc @@ -351,20 +351,32 @@ TEST(LogTest, BadRecordType) { ASSERT_EQ("OK", MatchError("unknown record type")); } -TEST(LogTest, TruncatedTrailingRecord) { +TEST(LogTest, TruncatedTrailingRecordIsIgnored) { Write("foo"); ShrinkSize(4); // Drop all payload as well as a header byte ASSERT_EQ("EOF", Read()); - ASSERT_EQ(kHeaderSize - 1, DroppedBytes()); - ASSERT_EQ("OK", MatchError("truncated record at end of file")); + // Truncated last record is ignored, not treated as an error. + ASSERT_EQ(0, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); } TEST(LogTest, BadLength) { + const int kPayloadSize = kBlockSize - kHeaderSize; + Write(BigString("bar", kPayloadSize)); + Write("foo"); + // Least significant size byte is stored in header[4]. + IncrementByte(4, 1); + ASSERT_EQ("foo", Read()); + ASSERT_EQ(kBlockSize, DroppedBytes()); + ASSERT_EQ("OK", MatchError("bad record length")); +} + +TEST(LogTest, BadLengthAtEndIsIgnored) { Write("foo"); ShrinkSize(1); ASSERT_EQ("EOF", Read()); - ASSERT_EQ(kHeaderSize + 2, DroppedBytes()); - ASSERT_EQ("OK", MatchError("bad record length")); + ASSERT_EQ(0, DroppedBytes()); + ASSERT_EQ("", ReportMessage()); } TEST(LogTest, ChecksumMismatch) { @@ -415,6 +427,24 @@ TEST(LogTest, UnexpectedFirstType) { ASSERT_EQ("OK", MatchError("partial record without end")); } +TEST(LogTest, MissingLastIsIgnored) { + Write(BigString("bar", kBlockSize)); + // Remove the LAST block, including header. + ShrinkSize(14); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("", ReportMessage()); + ASSERT_EQ(0, DroppedBytes()); +} + +TEST(LogTest, PartialLastIsIgnored) { + Write(BigString("bar", kBlockSize)); + // Cause a bad record length in the LAST block. + ShrinkSize(1); + ASSERT_EQ("EOF", Read()); + ASSERT_EQ("", ReportMessage()); + ASSERT_EQ(0, DroppedBytes()); +} + TEST(LogTest, ErrorJoinsRecords) { // Consider two fragmented records: // first(R1) last(R1) first(R2) last(R2) diff --git a/db/repair.cc b/db/repair.cc index 96c9b37af1..7727fafc58 100644 --- a/db/repair.cc +++ b/db/repair.cc @@ -242,7 +242,6 @@ class Repairer { } void ExtractMetaData() { - std::vector kept; for (size_t i = 0; i < table_numbers_.size(); i++) { ScanTable(table_numbers_[i]); } diff --git a/db/version_set.cc b/db/version_set.cc index 517edd3b18..aa83df55e4 100644 --- a/db/version_set.cc +++ b/db/version_set.cc @@ -54,20 +54,6 @@ static int64_t TotalFileSize(const std::vector& files) { return sum; } -namespace { -std::string IntSetToString(const std::set& s) { - std::string result = "{"; - for (std::set::const_iterator it = s.begin(); - it != s.end(); - ++it) { - result += (result.size() > 1) ? "," : ""; - result += NumberToString(*it); - } - result += "}"; - return result; -} -} // namespace - Version::~Version() { assert(refs_ == 0); diff --git a/include/leveldb/c.h b/include/leveldb/c.h index 1fa58866c3..1048fe3b86 100644 --- a/include/leveldb/c.h +++ b/include/leveldb/c.h @@ -9,7 +9,6 @@ Does not support: . getters for the option types . custom comparators that implement key shortening - . capturing post-write-snapshot . custom iter, db, env, cache implementations using just the C bindings Some conventions: diff --git a/include/leveldb/db.h b/include/leveldb/db.h index 5ffb29d526..40851b2aa8 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -14,7 +14,7 @@ namespace leveldb { // Update Makefile if you change these static const int kMajorVersion = 1; -static const int kMinorVersion = 15; +static const int kMinorVersion = 17; struct Options; struct ReadOptions; diff --git a/include/leveldb/slice.h b/include/leveldb/slice.h index 74ea8fa49a..bc367986f7 100644 --- a/include/leveldb/slice.h +++ b/include/leveldb/slice.h @@ -94,7 +94,7 @@ inline bool operator!=(const Slice& x, const Slice& y) { } inline int Slice::compare(const Slice& b) const { - const int min_len = (size_ < b.size_) ? size_ : b.size_; + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; int r = memcmp(data_, b.data_, min_len); if (r == 0) { if (size_ < b.size_) r = -1; From 90fd87376d4ccb1ce9eec703b756dd292bee8288 Mon Sep 17 00:00:00 2001 From: Matthew Bogosian Date: Fri, 9 May 2014 12:39:24 -0700 Subject: [PATCH 040/336] fixes #4163 --- src/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index e21881dbe9..2479a1f87e 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1747,7 +1747,7 @@ Value lockunspent(const Array& params, bool fHelp) throw runtime_error( "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n" "\nUpdates list of temporarily unspendable outputs.\n" - "Temporarily lock (lock=true) or unlock (lock=false) specified transaction outputs.\n" + "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n" "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n" "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n" "is always cleared (by virtue of process exit) when a node stops or fails.\n" From b641c9cd217f7789726bb25ab87cd35e2e5fcaad Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Sat, 10 May 2014 00:39:49 +0200 Subject: [PATCH 041/336] Fix addnode "onetry": Connect with OpenNetworkConnection --- src/net.cpp | 3 --- src/net.h | 1 + src/rpcnet.cpp | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 6bde1e7999..9f7096f133 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -41,9 +41,6 @@ using namespace boost; static const int MAX_OUTBOUND_CONNECTIONS = 8; -bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); - - // // Global state variables // diff --git a/src/net.h b/src/net.h index 729b1bcd57..3a8cf1ac8f 100644 --- a/src/net.h +++ b/src/net.h @@ -49,6 +49,7 @@ void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CService& ip); CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL); +bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 573d6cd3f6..0a2bfbac60 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -166,7 +166,7 @@ Value addnode(const Array& params, bool fHelp) if (strCommand == "onetry") { CAddress addr; - ConnectNode(addr, strNode.c_str()); + OpenNetworkConnection(addr, NULL, strNode.c_str()); return Value::null; } From f6b7c644c998799c10704be4a5b42d9cacc8a746 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 May 2014 23:42:20 +0200 Subject: [PATCH 042/336] Move base58.h implementation code to base58.cpp --- src/base58.cpp | 183 +++++++++++++++++++++++++++ src/base58.h | 257 +++++--------------------------------- src/test/base58_tests.cpp | 4 +- 3 files changed, 218 insertions(+), 226 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 0b08ee3d06..5975703887 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -2,11 +2,18 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "base58.h" + +#include "hash.h" +#include "uint256.h" + #include #include #include #include #include +#include +#include /* All alphanumeric characters except for "0", "I", "O", and "l" */ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -89,3 +96,179 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) str += pszBase58[*(it++)]; return str; } + +std::string EncodeBase58(const std::vector& vch) { + return EncodeBase58(&vch[0], &vch[0] + vch.size()); +} + +bool DecodeBase58(const std::string& str, std::vector& vchRet) { + return DecodeBase58(str.c_str(), vchRet); +} + +std::string EncodeBase58Check(const std::vector& vchIn) { + // add 4-byte hash check to the end + std::vector vch(vchIn); + uint256 hash = Hash(vch.begin(), vch.end()); + vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); + return EncodeBase58(vch); +} + +bool DecodeBase58Check(const char* psz, std::vector& vchRet) { + if (!DecodeBase58(psz, vchRet)) + return false; + if (vchRet.size() < 4) + { + vchRet.clear(); + return false; + } + // re-calculate the checksum, insure it matches the included 4-byte checksum + uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); + if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) + { + vchRet.clear(); + return false; + } + vchRet.resize(vchRet.size()-4); + return true; +} + +bool DecodeBase58Check(const std::string& str, std::vector& vchRet) { + return DecodeBase58Check(str.c_str(), vchRet); +} + +CBase58Data::CBase58Data() { + vchVersion.clear(); + vchData.clear(); +} + +void CBase58Data::SetData(const std::vector &vchVersionIn, const void* pdata, size_t nSize) { + vchVersion = vchVersionIn; + vchData.resize(nSize); + if (!vchData.empty()) + memcpy(&vchData[0], pdata, nSize); +} + +void CBase58Data::SetData(const std::vector &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend) { + SetData(vchVersionIn, (void*)pbegin, pend - pbegin); +} + +bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) { + std::vector vchTemp; + DecodeBase58Check(psz, vchTemp); + if (vchTemp.size() < nVersionBytes) { + vchData.clear(); + vchVersion.clear(); + return false; + } + vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes); + vchData.resize(vchTemp.size() - nVersionBytes); + if (!vchData.empty()) + memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size()); + OPENSSL_cleanse(&vchTemp[0], vchData.size()); + return true; +} + +bool CBase58Data::SetString(const std::string& str) { + return SetString(str.c_str()); +} + +std::string CBase58Data::ToString() const { + std::vector vch = vchVersion; + vch.insert(vch.end(), vchData.begin(), vchData.end()); + return EncodeBase58Check(vch); +} + +int CBase58Data::CompareTo(const CBase58Data& b58) const { + if (vchVersion < b58.vchVersion) return -1; + if (vchVersion > b58.vchVersion) return 1; + if (vchData < b58.vchData) return -1; + if (vchData > b58.vchData) return 1; + return 0; +} + +namespace { + class CBitcoinAddressVisitor : public boost::static_visitor { + private: + CBitcoinAddress *addr; + public: + CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } + + bool operator()(const CKeyID &id) const { return addr->Set(id); } + bool operator()(const CScriptID &id) const { return addr->Set(id); } + bool operator()(const CNoDestination &no) const { return false; } + }; +}; + +bool CBitcoinAddress::Set(const CKeyID &id) { + SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20); + return true; +} + +bool CBitcoinAddress::Set(const CScriptID &id) { + SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20); + return true; +} + +bool CBitcoinAddress::Set(const CTxDestination &dest) { + return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); +} + +bool CBitcoinAddress::IsValid() const { + bool fCorrectSize = vchData.size() == 20; + bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) || + vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); + return fCorrectSize && fKnownVersion; +} + +CTxDestination CBitcoinAddress::Get() const { + if (!IsValid()) + return CNoDestination(); + uint160 id; + memcpy(&id, &vchData[0], 20); + if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) + return CKeyID(id); + else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) + return CScriptID(id); + else + return CNoDestination(); +} + +bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const { + if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) + return false; + uint160 id; + memcpy(&id, &vchData[0], 20); + keyID = CKeyID(id); + return true; +} + +bool CBitcoinAddress::IsScript() const { + return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); +} + +void CBitcoinSecret::SetKey(const CKey& vchSecret) { + assert(vchSecret.IsValid()); + SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size()); + if (vchSecret.IsCompressed()) + vchData.push_back(1); +} + +CKey CBitcoinSecret::GetKey() { + CKey ret; + ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1); + return ret; +} + +bool CBitcoinSecret::IsValid() const { + bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1); + bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY); + return fExpectedFormat && fCorrectVersion; +} + +bool CBitcoinSecret::SetString(const char* pszSecret) { + return CBase58Data::SetString(pszSecret) && IsValid(); +} + +bool CBitcoinSecret::SetString(const std::string& strSecret) { + return SetString(strSecret.c_str()); +} diff --git a/src/base58.h b/src/base58.h index 4fb436c5ed..70681f589a 100644 --- a/src/base58.h +++ b/src/base58.h @@ -15,17 +15,12 @@ #define BITCOIN_BASE58_H #include "chainparams.h" -#include "hash.h" #include "key.h" #include "script.h" -#include "uint256.h" #include #include -#include -#include - /** * Encode a byte sequence as a base58-encoded string. * pbegin and pend cannot be NULL, unless both are. @@ -35,10 +30,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend) /** * Encode a byte vector as a base58-encoded string */ -inline std::string EncodeBase58(const std::vector& vch) -{ - return EncodeBase58(&vch[0], &vch[0] + vch.size()); -} +std::string EncodeBase58(const std::vector& vch); /** * Decode a base58-encoded string (psz) into a byte vector (vchRet). @@ -51,55 +43,24 @@ bool DecodeBase58(const char* psz, std::vector& vchRet); * Decode a base58-encoded string (str) into a byte vector (vchRet). * return true if decoding is successful. */ -inline bool DecodeBase58(const std::string& str, std::vector& vchRet) -{ - return DecodeBase58(str.c_str(), vchRet); -} +bool DecodeBase58(const std::string& str, std::vector& vchRet); /** * Encode a byte vector into a base58-encoded string, including checksum */ -inline std::string EncodeBase58Check(const std::vector& vchIn) -{ - // add 4-byte hash check to the end - std::vector vch(vchIn); - uint256 hash = Hash(vch.begin(), vch.end()); - vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); - return EncodeBase58(vch); -} +std::string EncodeBase58Check(const std::vector& vchIn); /** * Decode a base58-encoded string (psz) that includes a checksum into a byte * vector (vchRet), return true if decoding is successful */ -inline bool DecodeBase58Check(const char* psz, std::vector& vchRet) -{ - if (!DecodeBase58(psz, vchRet)) - return false; - if (vchRet.size() < 4) - { - vchRet.clear(); - return false; - } - // re-calculate the checksum, insure it matches the included 4-byte checksum - uint256 hash = Hash(vchRet.begin(), vchRet.end()-4); - if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) - { - vchRet.clear(); - return false; - } - vchRet.resize(vchRet.size()-4); - return true; -} +inline bool DecodeBase58Check(const char* psz, std::vector& vchRet); /** * Decode a base58-encoded string (str) that includes a checksum into a byte * vector (vchRet), return true if decoding is successful */ -inline bool DecodeBase58Check(const std::string& str, std::vector& vchRet) -{ - return DecodeBase58Check(str.c_str(), vchRet); -} +inline bool DecodeBase58Check(const std::string& str, std::vector& vchRet); /** * Base class for all base58-encoded data @@ -114,64 +75,15 @@ protected: typedef std::vector > vector_uchar; vector_uchar vchData; - CBase58Data() - { - vchVersion.clear(); - vchData.clear(); - } - - void SetData(const std::vector &vchVersionIn, const void* pdata, size_t nSize) - { - vchVersion = vchVersionIn; - vchData.resize(nSize); - if (!vchData.empty()) - memcpy(&vchData[0], pdata, nSize); - } - - void SetData(const std::vector &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend) - { - SetData(vchVersionIn, (void*)pbegin, pend - pbegin); - } + CBase58Data(); + void SetData(const std::vector &vchVersionIn, const void* pdata, size_t nSize); + void SetData(const std::vector &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend); public: - bool SetString(const char* psz, unsigned int nVersionBytes = 1) - { - std::vector vchTemp; - DecodeBase58Check(psz, vchTemp); - if (vchTemp.size() < nVersionBytes) - { - vchData.clear(); - vchVersion.clear(); - return false; - } - vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes); - vchData.resize(vchTemp.size() - nVersionBytes); - if (!vchData.empty()) - memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size()); - OPENSSL_cleanse(&vchTemp[0], vchData.size()); - return true; - } - - bool SetString(const std::string& str) - { - return SetString(str.c_str()); - } - - std::string ToString() const - { - std::vector vch = vchVersion; - vch.insert(vch.end(), vchData.begin(), vchData.end()); - return EncodeBase58Check(vch); - } - - int CompareTo(const CBase58Data& b58) const - { - if (vchVersion < b58.vchVersion) return -1; - if (vchVersion > b58.vchVersion) return 1; - if (vchData < b58.vchData) return -1; - if (vchData > b58.vchData) return 1; - return 0; - } + bool SetString(const char* psz, unsigned int nVersionBytes = 1); + bool SetString(const std::string& str); + std::string ToString() const; + int CompareTo(const CBase58Data& b58) const; bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } @@ -186,140 +98,37 @@ public: * Script-hash-addresses have version 5 (or 196 testnet). * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. */ -class CBitcoinAddress; -class CBitcoinAddressVisitor : public boost::static_visitor -{ -private: - CBitcoinAddress *addr; +class CBitcoinAddress : public CBase58Data { public: - CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } - bool operator()(const CKeyID &id) const; - bool operator()(const CScriptID &id) const; - bool operator()(const CNoDestination &no) const; + bool Set(const CKeyID &id); + bool Set(const CScriptID &id); + bool Set(const CTxDestination &dest); + bool IsValid() const; + + CBitcoinAddress() {} + CBitcoinAddress(const CTxDestination &dest) { Set(dest); } + CBitcoinAddress(const std::string& strAddress) { SetString(strAddress); } + CBitcoinAddress(const char* pszAddress) { SetString(pszAddress); } + + CTxDestination Get() const; + bool GetKeyID(CKeyID &keyID) const; + bool IsScript() const; }; -class CBitcoinAddress : public CBase58Data -{ -public: - bool Set(const CKeyID &id) { - SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20); - return true; - } - - bool Set(const CScriptID &id) { - SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20); - return true; - } - - bool Set(const CTxDestination &dest) - { - return boost::apply_visitor(CBitcoinAddressVisitor(this), dest); - } - - bool IsValid() const - { - bool fCorrectSize = vchData.size() == 20; - bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) || - vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); - return fCorrectSize && fKnownVersion; - } - - CBitcoinAddress() - { - } - - CBitcoinAddress(const CTxDestination &dest) - { - Set(dest); - } - - CBitcoinAddress(const std::string& strAddress) - { - SetString(strAddress); - } - - CBitcoinAddress(const char* pszAddress) - { - SetString(pszAddress); - } - - CTxDestination Get() const { - if (!IsValid()) - return CNoDestination(); - uint160 id; - memcpy(&id, &vchData[0], 20); - if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) - return CKeyID(id); - else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) - return CScriptID(id); - else - return CNoDestination(); - } - - bool GetKeyID(CKeyID &keyID) const { - if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) - return false; - uint160 id; - memcpy(&id, &vchData[0], 20); - keyID = CKeyID(id); - return true; - } - - bool IsScript() const { - return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); - } -}; - -bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); } -bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); } -bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; } - /** * A base58-encoded secret key */ class CBitcoinSecret : public CBase58Data { public: - void SetKey(const CKey& vchSecret) - { - assert(vchSecret.IsValid()); - SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size()); - if (vchSecret.IsCompressed()) - vchData.push_back(1); - } + void SetKey(const CKey& vchSecret); + CKey GetKey(); + bool IsValid() const; + bool SetString(const char* pszSecret); + bool SetString(const std::string& strSecret); - CKey GetKey() - { - CKey ret; - ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1); - return ret; - } - - bool IsValid() const - { - bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1); - bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY); - return fExpectedFormat && fCorrectVersion; - } - - bool SetString(const char* pszSecret) - { - return CBase58Data::SetString(pszSecret) && IsValid(); - } - - bool SetString(const std::string& strSecret) - { - return SetString(strSecret.c_str()); - } - - CBitcoinSecret(const CKey& vchSecret) - { - SetKey(vchSecret); - } - - CBitcoinSecret() - { - } + CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); } + CBitcoinSecret() {} }; template class CBitcoinExtKeyBase : public CBase58Data diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 5689e69995..b81a19cfd8 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) continue; } CBitcoinAddress addrOut; - BOOST_CHECK_MESSAGE(boost::apply_visitor(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest); + BOOST_CHECK_MESSAGE(addrOut.Set(dest), "encode dest: " + strTest); BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest); } } @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) // Visiting a CNoDestination must fail CBitcoinAddress dummyAddr; CTxDestination nodest = CNoDestination(); - BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest)); + BOOST_CHECK(!dummyAddr.Set(nodest)); SelectParams(CChainParams::MAIN); } From 7a0e84dd63ac98a92fd7aafd2d432f1da71eb8da Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Sun, 11 May 2014 00:30:18 -0500 Subject: [PATCH 043/336] ProcessGetData(): abort if a block file is missing from disk --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 379ca3ef74..f90f038016 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3373,7 +3373,7 @@ void static ProcessGetData(CNode* pfrom) { // Send block from disk CBlock block; - ReadBlockFromDisk(block, (*mi).second); + assert(ReadBlockFromDisk(block, (*mi).second)); if (inv.type == MSG_BLOCK) pfrom->PushMessage("block", block); else // MSG_FILTERED_BLOCK) From 283e405c063acfca304acbff505badcbbcb814c9 Mon Sep 17 00:00:00 2001 From: shshshsh Date: Sun, 11 May 2014 13:29:16 +0000 Subject: [PATCH 044/336] Switch stdout to line buffering Use line buffering (instead of block buffering) so that messages arrive immediately in systemd-journald, tail -f debug.log, and the like. --- src/init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 77c32d0b49..2c3bb02758 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -25,6 +25,7 @@ #endif #include +#include #ifndef WIN32 #include @@ -530,6 +531,7 @@ bool AppInit2(boost::thread_group& threadGroup) fServer = GetBoolArg("-server", false); fPrintToConsole = GetBoolArg("-printtoconsole", false); fLogTimestamps = GetBoolArg("-logtimestamps", true); + setvbuf(stdout, NULL, _IOLBF, 0); #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); #endif From 0a0cd345520382bd726fef50c62864715b03f164 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 7 May 2014 09:09:13 +0200 Subject: [PATCH 045/336] rpc: pass errors from async_accept According to the [boost::asio documentation](http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept/overload2.html), the function signature of the handler must be: void handler( const boost::system::error_code& error // Result of operation. ); We were binding *all* the arguments, instead of all but the error, resulting in nullary function that never got the error. Fix this by adding an input argument substitution. --- src/rpcserver.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index ac40ea7cf1..44f329dd15 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -466,7 +466,7 @@ static void RPCListen(boost::shared_ptr< basic_socket_acceptor Date: Wed, 7 May 2014 09:24:44 +0200 Subject: [PATCH 046/336] rpc: Make sure conn object is always cleaned up Make sure conn object always gets cleaned up by using a `boost::shared_ptr`. This makes valgrind happy - before this commit, one connection object always leaked at shutdown, as well as can avoid other leaks, when for example an exception happens. Also add an explicit Close() to the !ClientAllowed path to make it similar to the normal path (I'm not sure whether it is needed, but it can't hurt). --- src/rpcserver.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 44f329dd15..442bf5c9cb 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -444,7 +444,7 @@ template static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, ssl::context& context, bool fUseSSL, - AcceptedConnection* conn, + boost::shared_ptr< AcceptedConnection > conn, const boost::system::error_code& error); /** @@ -456,7 +456,7 @@ static void RPCListen(boost::shared_ptr< basic_socket_acceptor* conn = new AcceptedConnectionImpl(acceptor->get_io_service(), context, fUseSSL); + boost::shared_ptr< AcceptedConnectionImpl > conn(new AcceptedConnectionImpl(acceptor->get_io_service(), context, fUseSSL)); acceptor->async_accept( conn->sslStream.lowest_layer(), @@ -477,23 +477,20 @@ template static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, ssl::context& context, const bool fUseSSL, - AcceptedConnection* conn, + boost::shared_ptr< AcceptedConnection > conn, const boost::system::error_code& error) { // Immediately start accepting new connections, except when we're cancelled or our socket is closed. if (error != asio::error::operation_aborted && acceptor->is_open()) RPCListen(acceptor, context, fUseSSL); - AcceptedConnectionImpl* tcp_conn = dynamic_cast< AcceptedConnectionImpl* >(conn); + AcceptedConnectionImpl* tcp_conn = dynamic_cast< AcceptedConnectionImpl* >(conn.get()); - // TODO: Actually handle errors if (error) { - delete conn; // TODO: Actually handle errors LogPrintf("%s: Error: %s\n", __func__, error.message()); } - // Restrict callers by IP. It is important to // do this before starting client thread, to filter out // certain DoS and misbehaving clients. @@ -502,12 +499,11 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptorstream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush; - delete conn; + conn->close(); } else { - ServiceConnection(conn); + ServiceConnection(conn.get()); conn->close(); - delete conn; } } From 381b25dfde013efae4e0360f82cd34e27662e743 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 7 May 2014 11:47:16 +0200 Subject: [PATCH 047/336] doc: remove mention of `-rpctimeout` from man page That option hasn't existed for a long time. --- contrib/debian/manpages/bitcoin.conf.5 | 3 --- 1 file changed, 3 deletions(-) diff --git a/contrib/debian/manpages/bitcoin.conf.5 b/contrib/debian/manpages/bitcoin.conf.5 index eef213149d..7438b4b66a 100644 --- a/contrib/debian/manpages/bitcoin.conf.5 +++ b/contrib/debian/manpages/bitcoin.conf.5 @@ -37,9 +37,6 @@ You must set *rpcuser* to secure the JSON-RPC api. \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 From cef44941e798c33f7334bf90a2dd531f9bada8c3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 9 May 2014 10:01:50 +0200 Subject: [PATCH 048/336] rpc: keep track of acceptors, and cancel them in StopRPCThreads Fixes #4156. The problem is that the boost::asio::io_service destructor waits for the acceptors to finish (on windows, and boost 1.55). Fix this by keeping track of the acceptors and cancelling them before stopping the event loops. --- src/rpcserver.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 442bf5c9cb..d4a229b092 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -39,6 +39,7 @@ static ssl::context* rpc_ssl_context = NULL; static boost::thread_group* rpc_worker_group = NULL; static boost::asio::io_service::work *rpc_dummy_work = NULL; static std::vector rpc_allow_subnets; //!< List of subnets to allow RPC connections from +static std::vector< boost::shared_ptr > rpc_acceptors; void RPCTypeCheck(const Array& params, const list& typesExpected, @@ -593,12 +594,13 @@ void StartRPCThreads() asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort())); boost::system::error_code v6_only_error; - boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); bool fListening = false; std::string strerr; try { + boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); + rpc_acceptors.push_back(acceptor); acceptor->open(endpoint.protocol()); acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); @@ -616,7 +618,6 @@ void StartRPCThreads() { strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s"), endpoint.port(), e.what()); } - try { // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately if (!fListening || loopback || v6_only_error) @@ -624,7 +625,8 @@ void StartRPCThreads() bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any(); endpoint.address(bindAddress); - acceptor.reset(new ip::tcp::acceptor(*rpc_io_service)); + boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); + rpc_acceptors.push_back(acceptor); acceptor->open(endpoint.protocol()); acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); acceptor->bind(endpoint); @@ -668,7 +670,16 @@ void StopRPCThreads() { if (rpc_io_service == NULL) return; + // First, cancel all timers and acceptors + // This is not done automatically by ->stop(), and in some cases the destructor of + // asio::io_service can hang if this is skipped. + BOOST_FOREACH(const boost::shared_ptr &acceptor, rpc_acceptors) + acceptor->cancel(); + rpc_acceptors.clear(); + BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr) &timer, deadlineTimers) + timer.second->cancel(); deadlineTimers.clear(); + rpc_io_service->stop(); if (rpc_worker_group != NULL) rpc_worker_group->join_all(); From 9ec030622f6c12c75f98b6dcd0c18bd9ef1fc223 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Thu, 13 Mar 2014 02:45:33 -0400 Subject: [PATCH 049/336] Add CODESEPARATOR/FindAndDelete() tests --- src/test/data/tx_valid.json | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index 1f51d3ce55..40275cd194 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -132,5 +132,51 @@ [[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], "0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"], + +["OP_CODESEPARATOR tests"], + +["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"], +[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"], +[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"], + +["Hashed data starts at the CODESEPARATOR"], +[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]], +"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"], + +["But only if execution has reached it"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"], + +["CHECKSIG is legal in scriptSigs"], +[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Same semantics for OP_CODESEPARATOR"], +[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."], +[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["That also includes ahead of the opcode being executed."], +[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], + +["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], + +["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"], +[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], + ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]], +"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"], + +["Same idea, but with bare CHECKMULTISIG"], +[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], + ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]], +"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], + + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] From 8c93bf4c2857cdc01f0e5efca2becef08d2c5f1e Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Sun, 11 May 2014 07:05:04 -0500 Subject: [PATCH 050/336] LoadBlockIndexDB(): Require block db reindex if any blk*.dat files are missing. --- src/main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index f90f038016..4b0e3af649 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2941,6 +2941,24 @@ bool static LoadBlockIndexDB() if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) LogPrintf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString()); + // Check presence of blk files + LogPrintf("Checking all blk files are present...\n"); + set setBlkDataFiles; + BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + if (pindex->nStatus & BLOCK_HAVE_DATA) { + setBlkDataFiles.insert(pindex->nFile); + } + } + for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) + { + CDiskBlockPos pos(*it, 0); + if (!CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION)) { + return false; + } + } + // Check whether we need to continue reindexing bool fReindexing = false; pblocktree->ReadReindexing(fReindexing); From f25e3adf7d158283ef4bc1dd61df940c383dfebe Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Tue, 13 May 2014 01:39:42 -0300 Subject: [PATCH 051/336] Fix build in OS X 10.9 --- src/test/bignum.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/bignum.h b/src/test/bignum.h index b57800f372..a75f5250fa 100644 --- a/src/test/bignum.h +++ b/src/test/bignum.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include From 795b921dd22ec133a105404fe1b79c08a021768f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 May 2014 07:06:37 +0200 Subject: [PATCH 052/336] qt: periodic language update Pull updated translations from Transifex. Add mn (Mongolian) language. Do not update English translation for now as we want to keep compatibility with 0.9. --- src/qt/Makefile.am | 1 + src/qt/bitcoin.qrc | 1 + src/qt/locale/bitcoin_ach.ts | 12 +- src/qt/locale/bitcoin_af_ZA.ts | 12 +- src/qt/locale/bitcoin_ar.ts | 12 +- src/qt/locale/bitcoin_be_BY.ts | 12 +- src/qt/locale/bitcoin_bg.ts | 12 +- src/qt/locale/bitcoin_bs.ts | 12 +- src/qt/locale/bitcoin_ca.ts | 12 +- src/qt/locale/bitcoin_ca@valencia.ts | 12 +- src/qt/locale/bitcoin_ca_ES.ts | 12 +- src/qt/locale/bitcoin_cmn.ts | 12 +- src/qt/locale/bitcoin_cs.ts | 130 +- src/qt/locale/bitcoin_cy.ts | 12 +- src/qt/locale/bitcoin_da.ts | 20 +- src/qt/locale/bitcoin_de.ts | 12 +- src/qt/locale/bitcoin_el_GR.ts | 12 +- src/qt/locale/bitcoin_eo.ts | 12 +- src/qt/locale/bitcoin_es.ts | 16 +- src/qt/locale/bitcoin_es_CL.ts | 12 +- src/qt/locale/bitcoin_es_DO.ts | 12 +- src/qt/locale/bitcoin_es_MX.ts | 12 +- src/qt/locale/bitcoin_es_UY.ts | 12 +- src/qt/locale/bitcoin_et.ts | 12 +- src/qt/locale/bitcoin_eu_ES.ts | 12 +- src/qt/locale/bitcoin_fa.ts | 12 +- src/qt/locale/bitcoin_fa_IR.ts | 12 +- src/qt/locale/bitcoin_fi.ts | 14 +- src/qt/locale/bitcoin_fr.ts | 14 +- src/qt/locale/bitcoin_fr_CA.ts | 12 +- src/qt/locale/bitcoin_gl.ts | 12 +- src/qt/locale/bitcoin_gu_IN.ts | 12 +- src/qt/locale/bitcoin_he.ts | 12 +- src/qt/locale/bitcoin_hi_IN.ts | 12 +- src/qt/locale/bitcoin_hr.ts | 22 +- src/qt/locale/bitcoin_hu.ts | 12 +- src/qt/locale/bitcoin_id_ID.ts | 12 +- src/qt/locale/bitcoin_it.ts | 15 +- src/qt/locale/bitcoin_ja.ts | 190 +- src/qt/locale/bitcoin_ka.ts | 12 +- src/qt/locale/bitcoin_kk_KZ.ts | 12 +- src/qt/locale/bitcoin_ko_KR.ts | 12 +- src/qt/locale/bitcoin_ky.ts | 12 +- src/qt/locale/bitcoin_la.ts | 12 +- src/qt/locale/bitcoin_lt.ts | 12 +- src/qt/locale/bitcoin_lv_LV.ts | 12 +- src/qt/locale/bitcoin_mn.ts | 3375 ++++++++++++++++++++++++++ src/qt/locale/bitcoin_ms_MY.ts | 12 +- src/qt/locale/bitcoin_nb.ts | 14 +- src/qt/locale/bitcoin_nl.ts | 16 +- src/qt/locale/bitcoin_pam.ts | 12 +- src/qt/locale/bitcoin_pl.ts | 38 +- src/qt/locale/bitcoin_pt_BR.ts | 12 +- src/qt/locale/bitcoin_pt_PT.ts | 12 +- src/qt/locale/bitcoin_ro_RO.ts | 12 +- src/qt/locale/bitcoin_ru.ts | 14 +- src/qt/locale/bitcoin_sah.ts | 12 +- src/qt/locale/bitcoin_sk.ts | 344 +-- src/qt/locale/bitcoin_sl_SI.ts | 12 +- src/qt/locale/bitcoin_sq.ts | 12 +- src/qt/locale/bitcoin_sr.ts | 12 +- src/qt/locale/bitcoin_sv.ts | 14 +- src/qt/locale/bitcoin_th_TH.ts | 12 +- src/qt/locale/bitcoin_tr.ts | 12 +- src/qt/locale/bitcoin_uk.ts | 12 +- src/qt/locale/bitcoin_ur_PK.ts | 12 +- src/qt/locale/bitcoin_uz@Cyrl.ts | 12 +- src/qt/locale/bitcoin_vi.ts | 12 +- src/qt/locale/bitcoin_vi_VN.ts | 12 +- src/qt/locale/bitcoin_zh_CN.ts | 12 +- src/qt/locale/bitcoin_zh_HK.ts | 12 +- src/qt/locale/bitcoin_zh_TW.ts | 12 +- 72 files changed, 4414 insertions(+), 484 deletions(-) create mode 100644 src/qt/locale/bitcoin_mn.ts diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 8ec1ae2583..648971bd8f 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -57,6 +57,7 @@ QT_TS = \ locale/bitcoin_la.ts \ locale/bitcoin_lt.ts \ locale/bitcoin_lv_LV.ts \ + locale/bitcoin_mn.ts \ locale/bitcoin_ms_MY.ts \ locale/bitcoin_nb.ts \ locale/bitcoin_nl.ts \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 75078581ce..e1c739b022 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -130,6 +130,7 @@ locale/bitcoin_la.qm locale/bitcoin_lt.qm locale/bitcoin_lv_LV.qm + locale/bitcoin_mn.qm locale/bitcoin_ms_MY.qm locale/bitcoin_nb.qm locale/bitcoin_nl.qm diff --git a/src/qt/locale/bitcoin_ach.ts b/src/qt/locale/bitcoin_ach.ts index cfe916093b..de5619bfc0 100644 --- a/src/qt/locale/bitcoin_ach.ts +++ b/src/qt/locale/bitcoin_ach.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index a1f1abde69..80e4de010f 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index daf09183c4..32b0d4b0fc 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1041,6 +1041,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1343,7 +1351,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be_BY.ts index f7beb808d1..c384aa6d2d 100644 --- a/src/qt/locale/bitcoin_be_BY.ts +++ b/src/qt/locale/bitcoin_be_BY.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1344,7 +1352,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index 6b94dc8978..367e223784 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1043,6 +1043,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1345,7 +1353,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts index 01c37b0278..2ec28af777 100644 --- a/src/qt/locale/bitcoin_bs.ts +++ b/src/qt/locale/bitcoin_bs.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 592cb337d5..c225967cac 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts index 053cc82ebb..b36d6b7d67 100644 --- a/src/qt/locale/bitcoin_ca@valencia.ts +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index f01e48a435..5bf7fbfba7 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_cmn.ts b/src/qt/locale/bitcoin_cmn.ts index 402ce7cb10..696cbedd0a 100644 --- a/src/qt/locale/bitcoin_cmn.ts +++ b/src/qt/locale/bitcoin_cmn.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index f77e7f34db..ba4d2def35 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -333,7 +333,7 @@ Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v Open Open &URI... - + Načíst &URI... Importing blocks from disk... @@ -433,7 +433,7 @@ Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v Open Request payments (generates QR codes and bitcoin: URIs) - + Požaduj platby (generuje QR kódy a bitcoin: URI) &About Bitcoin Core @@ -441,15 +441,15 @@ Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v Open Show the list of used sending addresses and labels - + Ukaž seznam použitých odesílacích adres a jejich označení Show the list of used receiving addresses and labels - + Ukaž seznam použitých přijímacích adres a jejich označení Open a bitcoin: URI or payment request - + Načti bitcoin: URI nebo platební požadavek &Command-line options @@ -457,7 +457,7 @@ Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v Open Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - Seznam argumentů Bitcoinu pro příkazovou řádku získáš v nápovědě Bitcoinu Core. + Seznam argumentů Bitcoinu pro příkazovou řádku získáš v nápovědě Bitcoinu Core Bitcoin client @@ -497,7 +497,7 @@ Tento produkt zahrnuje programy vyvinuté OpenSSL Projektem pro použití v Open %n year(s) - + rok%n roky%n roků %1 behind @@ -579,7 +579,7 @@ Adresa: %4 Quantity: - + Počet: Bytes: @@ -599,11 +599,11 @@ Adresa: %4 Low Output: - + Malý výstup: After Fee: - + Čistá částka: Change: @@ -611,15 +611,15 @@ Adresa: %4 (un)select all - + (od)označit všechny Tree mode - + Zobrazit jako strom List mode - + Vypsat jako seznam Amount @@ -663,15 +663,15 @@ Adresa: %4 Lock unspent - + Zamkni neutracené Unlock unspent - + Odemkni k utracení Copy quantity - + Kopíruj počet Copy fee @@ -679,7 +679,7 @@ Adresa: %4 Copy after fee - + Kopíruj čistou částku Copy bytes @@ -691,7 +691,7 @@ Adresa: %4 Copy low output - + Kopíruj malý výstup Copy change @@ -699,47 +699,47 @@ Adresa: %4 highest - + nejvyšší higher - + vyšší high - + vysoká medium-high - + vyšší střední medium - + střední low-medium - + nižší střední low - + nízká lower - + nižší lowest - + nejnižší (%1 locked) - + (%1 zamčeno) none - + žádná Dust @@ -747,11 +747,11 @@ Adresa: %4 yes - + ano no - + ne This label turns red, if the transaction size is greater than 1000 bytes. @@ -759,11 +759,11 @@ Adresa: %4 This means a fee of at least %1 per kB is required. - + To znamená, že je vyžadován poplatek alespoň %1 za kB. Can vary +/- 1 byte per input. - + Může se lišit o +/– 1 bajt na každý vstup. Transactions with higher priority are more likely to get included into a block. @@ -1047,6 +1047,14 @@ Adresa: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP adresa proxy (např. IPv4: 127.0.0.1/IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1181,7 +1189,7 @@ Adresa: %4 none - + žádná Confirm options reset @@ -1189,7 +1197,7 @@ Adresa: %4 Client restart required to activate changes. - + K aktivaci změn je potřeba restartovat klienta. Client will be shutdown, do you want to proceed? @@ -1291,7 +1299,7 @@ Adresa: %4 Payment request fetch URL is invalid: %1 - + Zdrojová URL platebního požadavku není platná: %1 Payment request file handling @@ -1303,7 +1311,7 @@ Adresa: %4 Unverified payment requests to custom payment scripts are unsupported. - + Neověřené platební požadavky k uživatelským platebním skriptům nejsou podporované. Refund from %1 @@ -1349,7 +1357,7 @@ Adresa: %4 Chyba: Neplatná kombinace -regtest a -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... Bitcoin Core ještě bezpečně neskončil... @@ -1614,15 +1622,15 @@ Adresa: %4 Copy &URI - + Kopíruj &URI Copy &Address - + Kopíruj &adresu &Save Image... - &Ulož Obrázek... + &Ulož obrázek... Request payment to %1 @@ -1630,7 +1638,7 @@ Adresa: %4 Payment information - + Informace o platbě URI @@ -1712,11 +1720,11 @@ Adresa: %4 Insufficient funds! - + Nedostatek prostředků! Quantity: - + Počet: Bytes: @@ -1736,11 +1744,11 @@ Adresa: %4 Low Output: - + Malý výstup: After Fee: - + Čistá částka: Change: @@ -1792,7 +1800,7 @@ Adresa: %4 Copy quantity - + Kopíruj počet Copy amount @@ -1804,7 +1812,7 @@ Adresa: %4 Copy after fee - + Kopíruj čistou částku Copy bytes @@ -1816,7 +1824,7 @@ Adresa: %4 Copy low output - + Kopíruj malý výstup Copy change @@ -1824,7 +1832,7 @@ Adresa: %4 Total Amount %1 (= %2) - + Celková částka %1 (= %2) or @@ -1876,11 +1884,11 @@ Adresa: %4 added as transaction fee - + přidán jako transakční poplatek Payment request expired - + Platební požadavek vypršel Invalid payment address %1 @@ -1911,7 +1919,7 @@ Adresa: %4 Choose previously used address - + Vyber již použitou adresu This is a normal payment. @@ -1955,7 +1963,7 @@ Adresa: %4 Pay To: - + Komu: Memo: @@ -1993,7 +2001,7 @@ Adresa: %4 Choose previously used address - + Vyber již použitou adresu Alt+A @@ -2823,7 +2831,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connect through SOCKS proxy - + Připojit se přes SOCKS proxy Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) @@ -2831,7 +2839,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + Možnosti připojení: Corrupted block database detected @@ -2839,7 +2847,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Debugging/Testing options: - + Možnosti ladění/testování: Disable safemode, override a real safe mode event (default: 0) @@ -2851,7 +2859,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Do not load the wallet and disable wallet RPC calls - + Nenačítat peněženku a vypnout její RPC volání Do you want to rebuild the block database now? @@ -3035,7 +3043,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Wallet options: - + Možnosti peněženky: Warning: Deprecated argument -debugnet ignored, use -debug=net diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts index b7624f07f2..d2f41739cb 100644 --- a/src/qt/locale/bitcoin_cy.ts +++ b/src/qt/locale/bitcoin_cy.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 3d89d2e5c5..442a86b7c0 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -96,11 +96,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Sending addresses - + Afsendelsesadresser Receiving addresses - + Modtagelsesadresser These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. @@ -325,11 +325,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Sending addresses... - + &Afsendelsesadresser... &Receiving addresses... - + &Modtagelsesadresser... Open &URI... @@ -1047,6 +1047,14 @@ Adresse: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Adresse: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 7f7e505e1d..888b48c251 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Adresse: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP-Adresse des Proxies (z.B. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Externe URLs (z.B. ein Block-Explorer), die im Kontextmenü des Transaktionsverlaufs eingefügt werden. In der URL wird %s durch den Transaktionshash ersetzt. Bei Angabe mehrerer URLs müssen diese durch "|" voneinander getrennt werden. + + + Third party transaction URLs + Externe Transaktions-URLs + Active command-line options that override above options: Aktive Kommandozeilenoptionen, die obige Konfiguration überschreiben: @@ -1348,7 +1356,7 @@ Adresse: %4 Fehler: Ungültige Kombination von -regtest und -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... Bitcoin Core wurde noch nicht sicher beendet... diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index d13b974b8c..687947e3b9 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1048,6 +1048,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1350,7 +1358,7 @@ Address: %4 Σφάλμα: Άκυρος συνδυασμός των -regtest και -testnet - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index 7f5dc3de2f..8c2869abac 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adreso: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Adreso: %4 Eraro: nevalida kunigo de -regtest kaj -testnet - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 0bd60be101..8ca8360ef6 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1050,6 +1050,14 @@ Dirección: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Dirección IP del proxy (p. ej. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: Opciones activas de consola de comandos que tienen preferencia sobre las opciones antes mencionadas: @@ -1352,8 +1360,8 @@ Dirección: %4 Error: Combinación no válida de -regtest y -testnet. - Bitcoin Core did't yet exit safely... - + Bitcoin Core didn't yet exit safely... + Bitcoin core no se ha cerrado de forma segura todavía... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2971,7 +2979,7 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Importing... - + Importando... Incorrect or no genesis block found. Wrong datadir for network? diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index b63743e5d6..758a190f75 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1050,6 +1050,14 @@ Dirección: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1352,7 +1360,7 @@ Dirección: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts index 6fca831017..6944c3157f 100644 --- a/src/qt/locale/bitcoin_es_DO.ts +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1050,6 +1050,14 @@ Dirección: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Dirección IP del proxy (ej. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1352,7 +1360,7 @@ Dirección: %4 Error: Combinación no válida de -regtest y -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index 6920f2300b..9a39551d6b 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: Activar las opciones de linea de comando que sobre escriben las siguientes opciones: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts index d94ad1c938..03ecce46c0 100644 --- a/src/qt/locale/bitcoin_es_UY.ts +++ b/src/qt/locale/bitcoin_es_UY.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index 8affc8a5d2..e6c27bf21c 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Aadress: %4⏎ IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1348,7 +1356,7 @@ Aadress: %4⏎ - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts index afa4d6c540..1fce25d6da 100644 --- a/src/qt/locale/bitcoin_eu_ES.ts +++ b/src/qt/locale/bitcoin_eu_ES.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index 805c7bb856..0dfbafb811 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1344,7 +1352,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index 18a0dca224..3b82ffa5e5 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1041,6 +1041,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1343,7 +1351,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index 942dad5411..ece70f6075 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Osoite: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP osoite proxille (esim. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Ulkopuoliset URL-osoitteet (esim. block explorer,) jotka esiintyvät siirrot-välilehdellä valikossa. %s URL-osoitteessa korvataan siirtotunnuksella. Useampi URL-osoite on eroteltu pystyviivalla |. + + + Third party transaction URLs + + Active command-line options that override above options: Aktiiviset komentorivivalinnat jotka ohittavat ylläolevat valinnat: @@ -1349,8 +1357,8 @@ Osoite: %4 Virhe: Virheellinen yhdistelmä -regtest ja -testnet. - Bitcoin Core did't yet exit safely... - Bitcoin Core ei vielä sulkeutunut turvallisesti... + Bitcoin Core didn't yet exit safely... + Bitcoin Core ei ole vielä sulkeutunut turvallisesti... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index e0d5bbdbcd..05089f0416 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adresse : %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Adresse IP du mandataire (par ex. IPv4 : 127.0.0.1 / IPv6 : ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + URL de tiers (par ex. un explorateur de blocs) apparaissant dans l'onglet des transactions comme éléments du menu contextuel. %s dans l'URL est remplacé par le hachage de la transaction. Les URL multiples sont séparées par une barre verticale |. + + + Third party transaction URLs + URL de transaction d'un tiers + Active command-line options that override above options: Options actives de ligne de commande qui annulent les options ci-dessus : @@ -1349,8 +1357,8 @@ Adresse : %4 Erreur : combinaison invalide de -regtest et de -testnet. - Bitcoin Core did't yet exit safely... - Bitcoin Core ne s’est pas arrêté correctement... + Bitcoin Core didn't yet exit safely... + Bitcoin Core ne s'est pas encore arrêté en toute sécurité... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_fr_CA.ts index 0df3eb3edd..ff22c2fd1c 100644 --- a/src/qt/locale/bitcoin_fr_CA.ts +++ b/src/qt/locale/bitcoin_fr_CA.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1043,6 +1043,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1345,7 +1353,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts index a1ee3545bf..ecf1fa2222 100644 --- a/src/qt/locale/bitcoin_gl.ts +++ b/src/qt/locale/bitcoin_gl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Dirección: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Dirección: %4 Erro: combinación inválida de -regtest e -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_gu_IN.ts b/src/qt/locale/bitcoin_gu_IN.ts index 66b341545e..ed4a9265e4 100644 --- a/src/qt/locale/bitcoin_gu_IN.ts +++ b/src/qt/locale/bitcoin_gu_IN.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 73378535a7..ae13df4524 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1348,7 +1356,7 @@ Address: %4 שגיאה: שילוב בלתי חוקי של regtest- ו testnet-. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_hi_IN.ts b/src/qt/locale/bitcoin_hi_IN.ts index d27e26b871..3ccac8899e 100644 --- a/src/qt/locale/bitcoin_hi_IN.ts +++ b/src/qt/locale/bitcoin_hi_IN.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1344,7 +1352,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index b5f1595515..bd2b773d2f 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Adresa:%4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1196,7 +1204,7 @@ Adresa:%4 The supplied proxy address is invalid. - + Priložena proxy adresa je nevažeća. @@ -1207,7 +1215,7 @@ Adresa:%4 The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. - + Prikazani podatci mogu biti zastarjeli. Vaš novčanik se automatski sinkronizira s Bitcoin mrežom kada je veza uspostavljena, ali taj proces još nije završen. Wallet @@ -1344,7 +1352,7 @@ Adresa:%4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... @@ -1483,7 +1491,7 @@ Adresa:%4 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. - + Kako bi navigirali kroz povijest koristite strelice gore i dolje. <b>Ctrl-L</b> kako bi očistili ekran. Type <b>help</b> for an overview of available commands. @@ -2466,7 +2474,7 @@ Adresa:%4 Show transaction details - + Prikaži detalje transakcije Export Transaction History @@ -2622,7 +2630,7 @@ Adresa:%4 Specify your own public address - + Odaberi vlastitu javnu adresu Threshold for disconnecting misbehaving peers (default: 100) diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index de57490847..3d8d45a61d 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Cím: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Cím: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index bd92878fed..c4dee5f92d 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Alamat: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Alamat IP proxy (cth. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: pilihan perintah-baris aktif menimpa atas pilihan-pilihan: @@ -1349,7 +1357,7 @@ Alamat: %4 Gagal: Gabungan -regtest dan -testnet salah - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index b9ef5e4d0b..cb9fed1ab9 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1048,6 +1048,15 @@ Indirizzo: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Indirizzo IP del proxy (es: IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + URL di terze parti (es: un block explorer) che appaiono nella tabella delle transazioni come voci nel menu contestuale. %s nell'URL è sostituito dall'hash della transazione. +Più URL vengono separati da una barra verticale |. + + + Third party transaction URLs + URL di transazione di terze parti + Active command-line options that override above options: Opzioni command-line attive che sostituiscono i settaggi sopra elencati: @@ -1350,8 +1359,8 @@ Indirizzo: %4 Errore: combinazione di -regtest e -testnet non valida. - Bitcoin Core did't yet exit safely... - Bitcoin Core non è ancora stato chiuso in modo sicuro ... + Bitcoin Core didn't yet exit safely... + Bitcoin Core non si è ancora chiuso con sicurezza... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index c7e4fe6091..5edfc0746a 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -7,7 +7,7 @@ <b>Bitcoin Core</b> version - + <b>ビットコインコア</b> バージョン @@ -29,7 +29,7 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 The Bitcoin Core developers - + ビットコインコアの開発者 (%1-bit) @@ -128,7 +128,7 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 Exporting Failed - + エクスポート失敗 There was an error trying to save the address list to %1. @@ -273,7 +273,7 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 Node - + ノード Show general overview of wallet @@ -325,15 +325,15 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 &Sending addresses... - + 送金先アドレス一覧 (&S)... &Receiving addresses... - + 受け取り用アドレス一覧 (&R)... Open &URI... - + URI を開く (&U)... Importing blocks from disk... @@ -437,7 +437,7 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 &About Bitcoin Core - + ビットコインコアについて (&A) Show the list of used sending addresses and labels @@ -453,7 +453,7 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 &Command-line options - + コマンドラインオプション (&C) Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options @@ -493,11 +493,11 @@ MIT/X11 ソフトウェア ライセンスの下で配布されています。 %1 and %2 - + %1 と %2 %n year(s) - + %n 年 %1 behind @@ -579,11 +579,11 @@ Address: %4 Quantity: - + 数量: Bytes: - + バイト: Amount: @@ -591,11 +591,11 @@ Address: %4 Priority: - + 優先度: Fee: - + 手数料: Low Output: @@ -603,7 +603,7 @@ Address: %4 After Fee: - + 手数料差引後: Change: @@ -615,11 +615,11 @@ Address: %4 Tree mode - + ツリーモード List mode - + リストモード Amount @@ -635,7 +635,7 @@ Address: %4 Confirmations - + 検証数 Confirmed @@ -643,7 +643,7 @@ Address: %4 Priority - + 優先度 Copy address @@ -671,23 +671,23 @@ Address: %4 Copy quantity - + 数量をコピーする Copy fee - + 手数料をコピーする Copy after fee - + 手数料差引後の値をコピーする Copy bytes - + バイト数をコピーする Copy priority - + 優先度をコピーする Copy low output @@ -771,7 +771,7 @@ Address: %4 This label turns red, if the priority is smaller than "medium". - + 優先度が「中」未満の場合には、このラベルは赤くなります。 This label turns red, if any recipient receives an amount smaller than %1. @@ -978,11 +978,11 @@ Address: %4 OpenURIDialog Open URI - + URI を開く Open payment request from URI or file - + URI またはファイルから支払いリクエストを開く URI: @@ -990,11 +990,11 @@ Address: %4 Select payment request file - + 支払いリクエストファイルを選択してください Select payment request file to open - + 開きたい支払いリクエストファイルを選択してください @@ -1025,11 +1025,11 @@ Address: %4 Size of &database cache - + データベースキャッシュのサイズ (&D) MB - + MB Number of script &verification threads @@ -1045,6 +1045,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + プロキシのIPアドレス (例えば IPv4: 127.0.0.1 / IPv6: ::1) + + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs @@ -1069,15 +1077,15 @@ Address: %4 W&allet - + ウォレット (&A) Expert - + エクスポート Enable coin &control features - + コインコントロール機能を有効化する (&C) If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. @@ -1350,7 +1358,7 @@ Address: %4 エラー: -regtestと-testnetは一緒にするのは無効です。 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... @@ -1461,11 +1469,11 @@ Address: %4 In: - + 入力: Out: - + 出力: Build date @@ -1497,31 +1505,31 @@ Address: %4 %1 B - + %1 B %1 KB - + %1 KB %1 MB - + %1 MB %1 GB - + %1 GB %1 m - + %1 m %1 h - + %1 h %1 h %2 m - + %1 h %2 m @@ -1536,7 +1544,7 @@ Address: %4 &Message: - + メッセージ (&M): Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. @@ -1600,7 +1608,7 @@ Address: %4 Copy message - + メッセージをコピーする Copy amount @@ -1615,11 +1623,11 @@ Address: %4 Copy &URI - + URI をコピーする (&U) Copy &Address - + アドレスをコピーする (&A) &Save Image... @@ -1627,7 +1635,7 @@ Address: %4 Request payment to %1 - + %1 への支払いリクエストを行う Payment information @@ -1635,7 +1643,7 @@ Address: %4 URI - + URI Address @@ -1701,27 +1709,27 @@ Address: %4 Coin Control Features - + コインコントロール機能 Inputs... - + 入力... automatically selected - + 自動選択 Insufficient funds! - + 残高不足です! Quantity: - + 数量: Bytes: - + バイト: Amount: @@ -1729,11 +1737,11 @@ Address: %4 Priority: - + 優先度: Fee: - + 手数料: Low Output: @@ -1741,7 +1749,7 @@ Address: %4 After Fee: - + 手数料差引後: Change: @@ -1793,7 +1801,7 @@ Address: %4 Copy quantity - + 数量をコピーする Copy amount @@ -1801,19 +1809,19 @@ Address: %4 Copy fee - + 手数料をコピーする Copy after fee - + 手数料差引後の値をコピーする Copy bytes - + バイト数をコピーする Copy priority - + 優先度をコピーする Copy low output @@ -1956,7 +1964,7 @@ Address: %4 Pay To: - + 支払先: Memo: @@ -2125,7 +2133,7 @@ Address: %4 The Bitcoin Core developers - + ビットコインコアの開発者 [testnet] @@ -2136,7 +2144,7 @@ Address: %4 TrafficGraphWidget KB/s - + KB/s @@ -2333,11 +2341,11 @@ Address: %4 Offline - + オフライン Unconfirmed - + 未検証 Confirming (%1 of %2 recommended confirmations) @@ -2476,19 +2484,19 @@ Address: %4 Export Transaction History - + トランザクション履歴をエクスポートする Exporting Failed - + エクスポートに失敗しました There was an error trying to save the transaction history to %1. - + トランザクション履歴を %1 へ保存する際にエラーが発生しました。 Exporting Successful - + エクスポートに成功しました The transaction history was successfully saved to %1. @@ -2652,7 +2660,7 @@ Address: %4 Bitcoin Core RPC client version - + ビットコインコアRPCクライアントのバージョン Run in the background as a daemon and accept commands @@ -2791,11 +2799,11 @@ rpcpassword=%s (default: 1) - + (デフォルト: 1) (default: wallet.dat) - + (デフォルト: wallet.dat) <category> can be: @@ -2823,7 +2831,7 @@ rpcpassword=%s Connect through SOCKS proxy - + SOCKS プロキシ経由で接続する Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) @@ -2840,7 +2848,7 @@ rpcpassword=%s Debugging/Testing options: - + デバッグ/テスト用オプション: Disable safemode, override a real safe mode event (default: 0) @@ -2932,11 +2940,11 @@ rpcpassword=%s Fee per kB to add to transactions you send - + 送信するトランザクションの1kBあたりの手数料 Fees smaller than this are considered zero fee (for relaying) (default: - + この値未満の (中継) 手数料はゼロであるとみなす (デフォルト: Find peers using DNS lookup (default: 1 unless -connect) @@ -2944,7 +2952,7 @@ rpcpassword=%s Force safe mode (default: 0) - + セーフモードを矯正する (デフォルト: 0) Generate coins (default: 0) @@ -2956,7 +2964,7 @@ rpcpassword=%s If <category> is not supplied, output all debugging information. - + <category> が与えられなかった場合には、すべてのデバッグ情報が出力されます。 Importing... @@ -2980,7 +2988,7 @@ rpcpassword=%s RPC client options: - + RPC クライアントのオプション: Rebuild block chain index from current blk000??.dat files @@ -3028,7 +3036,7 @@ rpcpassword=%s Wait for RPC server to start - + RPC サーバが開始するのを待つ Wallet %s resides outside data directory %s @@ -3040,7 +3048,7 @@ rpcpassword=%s Warning: Deprecated argument -debugnet ignored, use -debug=net - + 警告: 非推奨の引数 -debugnet は無視されました。-debug=net を使用してください You need to rebuild the database using -reindex to change -txindex @@ -3080,11 +3088,11 @@ rpcpassword=%s Limit size of signature cache to <n> entries (default: 50000) - + 署名キャッシュのサイズを <n> エントリーに制限する (デフォルト: 50000) Log transaction priority and fee per kB when mining blocks (default: 0) - + ブロックの採掘時にトランザクションの優先度と1kBあたりの手数料をログに残す (デフォルト: 0) Maintain a full transaction index (default: 0) @@ -3116,11 +3124,11 @@ rpcpassword=%s RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) - + RPC SSL オプション: (SSLのセットアップ手順はビットコインWikiを参照してください) RPC server options: - + RPCサーバのオプション: Randomly drop 1 of every <n> network messages diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index fd14152b04..fda2e97037 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) პროქსის IP-მისამართი (მაგ.: IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: საკომანდო სტრიქონის აქტიური ოპციები, რომლებიც გადაფარავენ ზემოთნაჩვენებს: @@ -1349,7 +1357,7 @@ Address: %4 შეცდომა: -regtest-ისა და -testnet-ის დაუშვებელი კომბინაცია. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_kk_KZ.ts b/src/qt/locale/bitcoin_kk_KZ.ts index e35055ebd1..b913ba9858 100644 --- a/src/qt/locale/bitcoin_kk_KZ.ts +++ b/src/qt/locale/bitcoin_kk_KZ.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index c1584600cf..f5d2dddbe4 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) 프록시 아이피 주소(예. IPv4:127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts index 375e72d359..d0db034e86 100644 --- a/src/qt/locale/bitcoin_ky.ts +++ b/src/qt/locale/bitcoin_ky.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts index 89f4be8202..425519514a 100644 --- a/src/qt/locale/bitcoin_la.ts +++ b/src/qt/locale/bitcoin_la.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Inscriptio: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1348,7 +1356,7 @@ Inscriptio: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index 103cd5f53d..a9898adb2b 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1045,6 +1045,14 @@ Adresas: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1347,7 +1355,7 @@ Adresas: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index 0db0b77a47..c17f65e125 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Adrese: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1344,7 +1352,7 @@ Adrese: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts new file mode 100644 index 0000000000..e765931b2c --- /dev/null +++ b/src/qt/locale/bitcoin_mn.ts @@ -0,0 +1,3375 @@ + + + AboutDialog + + About Bitcoin Core + + + + <b>Bitcoin Core</b> version + + + + +This is experimental software. + +Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. + + + + Copyright + + + + The Bitcoin Core developers + + + + (%1-bit) + + + + + AddressBookPage + + Double-click to edit address or label + Хаяг эсвэл шошгыг ѳѳрчлѳхийн тулд хоёр удаа дар + + + Create a new address + Шинэ хаяг нээх + + + &New + + + + Copy the currently selected address to the system clipboard + Одоогоор сонгогдсон байгаа хаягуудыг сануулах + + + &Copy + + + + C&lose + + + + &Copy Address + Хаягийг &Хуулбарлах + + + Delete the currently selected address from the list + + + + Export the data in the current tab to a file + + + + &Export + + + + &Delete + &Устгах + + + Choose the address to send coins to + + + + Choose the address to receive coins with + + + + C&hoose + + + + Sending addresses + + + + Receiving addresses + + + + These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. + + + + These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. + + + + Copy &Label + &Шошгыг хуулбарлах + + + &Edit + &Ѳѳрчлѳх + + + Export Address List + + + + Comma separated file (*.csv) + Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv) + + + Exporting Failed + + + + There was an error trying to save the address list to %1. + + + + + AddressTableModel + + Label + Шошго + + + Address + Хаяг + + + (no label) + (шошго алга) + + + + AskPassphraseDialog + + Passphrase Dialog + + + + Enter passphrase + Нууц үгийг оруул + + + New passphrase + Шинэ нууц үг + + + Repeat new passphrase + Шинэ нууц үгийг давтана уу + + + Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. + Түрүйвчийн шинэ нууц үгийг оруул. <br/><b>Дор хаяж 10 дурын үсэг/тоо бүхий</b> эсвэл <b>дор хаяж 8 дурын үгнээс бүрдсэн</b> нууц үгийг ашиглана уу. + + + Encrypt wallet + Түрүйвчийг цоожлох + + + This operation needs your wallet passphrase to unlock the wallet. + Энэ үйлдэлийг гүйцэтгэхийн тулд та нууц үгээрээ түрүйвчийн цоожийг тайлах хэрэгтэй + + + Unlock wallet + Түрүйвчийн цоожийг тайлах + + + This operation needs your wallet passphrase to decrypt the wallet. + Энэ үйлдэлийг гүйцэтгэхийн тулд та эхлээд түрүйвчийн нууц үгийг оруулж цоожийг тайлах шаардлагтай. + + + Decrypt wallet + Түрүйвчийн цоожийг устгах + + + Change passphrase + Нууц үгийг солих + + + Enter the old and new passphrase to the wallet. + Түрүйвчийн хуучин болоод шинэ нууц үгсийг оруулна уу + + + Confirm wallet encryption + Түрүйвчийн цоожийг баталгаажуулах + + + Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! + + + + Are you sure you wish to encrypt your wallet? + + + + IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. + + + + Warning: The Caps Lock key is on! + + + + Wallet encrypted + Түрүйвч цоожлогдлоо + + + 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. + Цоожлолтын процесыг дуусгахын тулд Биткойн одоо хаагдана. Ѳѳрийн түрүйвчийг цоожлох нь таны биткойнуудыг компьютерийн вирус хулгайлахаас бүрэн сэргийлж чадахгүй гэдгийг санаарай. + + + Wallet encryption failed + Түрүйвчийн цоожлол амжилттай болсонгүй + + + Wallet encryption failed due to an internal error. Your wallet was not encrypted. + Түрүйвчийн цоожлол дотоод алдаанаас үүдэн амжилттай болсонгүй. Түрүйвч цоожлогдоогүй байна. + + + The supplied passphrases do not match. + Таны оруулсан нууц үг таарсангүй + + + Wallet unlock failed + Түрүйвчийн цоож тайлагдсангүй + + + The passphrase entered for the wallet decryption was incorrect. + Таны оруулсан түрүйвчийн цоожийг тайлах нууц үг буруу байна + + + Wallet decryption failed + Түрүйвчийн цоож амжилттай устгагдсангүй + + + Wallet passphrase was successfully changed. + Түрүйвчийн нууц үг амжилттай ѳѳр + + + + BitcoinGUI + + Sign &message... + &Зурвас хавсаргах... + + + Synchronizing with network... + Сүлжээтэй тааруулж байна... + + + &Overview + + + + Node + Нод + + + Show general overview of wallet + + + + &Transactions + Гүйлгээнүүд + + + Browse transaction history + Гүйлгээнүүдийн түүхийг харах + + + E&xit + Гарах + + + Quit application + Програмаас Гарах + + + Show information about Bitcoin + Биткойны мэдээллийг харуулах + + + About &Qt + &Клиентийн тухай + + + Show information about Qt + Клиентийн тухай мэдээллийг харуул + + + &Options... + &Сонголтууд... + + + &Encrypt Wallet... + &Түрүйвчийг цоожлох... + + + &Backup Wallet... + &Түрүйвчийг Жоорлох... + + + &Change Passphrase... + &Нууц Үгийг Солих... + + + &Sending addresses... + + + + &Receiving addresses... + + + + Open &URI... + + + + Importing blocks from disk... + + + + Reindexing blocks on disk... + + + + Send coins to a Bitcoin address + + + + Modify configuration options for Bitcoin + + + + Backup wallet to another location + + + + Change the passphrase used for wallet encryption + Түрүйвчийг цоожлох нууц үгийг солих + + + &Debug window + + + + Open debugging and diagnostic console + Оношилгоо ба засварын консолыг онгойлго + + + &Verify message... + + + + Bitcoin + Биткойн + + + Wallet + Түрүйвч + + + &Send + + + + &Receive + + + + &Show / Hide + &Харуул / Нуу + + + Show or hide the main Window + + + + Encrypt the private keys that belong to your wallet + + + + Sign messages with your Bitcoin addresses to prove you own them + + + + Verify messages to ensure they were signed with specified Bitcoin addresses + + + + &File + &Файл + + + &Settings + &Тохиргоо + + + &Help + &Тусламж + + + Tabs toolbar + + + + [testnet] + + + + Bitcoin Core + + + + Request payments (generates QR codes and bitcoin: URIs) + + + + &About Bitcoin Core + + + + Show the list of used sending addresses and labels + + + + Show the list of used receiving addresses and labels + + + + Open a bitcoin: URI or payment request + + + + &Command-line options + + + + Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options + + + + Bitcoin client + Биткойн клиент + + + %n active connection(s) to Bitcoin network + Биткойны сүлжээрүү %n идэвхитэй холболт байна Биткойны сүлжээрүү %n идэвхитэй холболтууд байна + + + No block source available... + + + + Processed %1 of %2 (estimated) blocks of transaction history. + + + + Processed %1 blocks of transaction history. + + + + %n hour(s) + %n цаг%n цаг + + + %n day(s) + %n ѳдѳр%n ѳдрүүд + + + %n week(s) + + + + %1 and %2 + + + + %n year(s) + + + + %1 behind + + + + Last received block was generated %1 ago. + + + + Transactions after this will not yet be visible. + + + + Error + Алдаа + + + Warning + + + + Information + + + + Up to date + Шинэчлэгдсэн + + + Catching up... + + + + Sent transaction + Гадагшаа гүйлгээ + + + Incoming transaction + Дотогшоо гүйлгээ + + + Date: %1 +Amount: %2 +Type: %3 +Address: %4 + + Огноо: %1 + +Хэмжээ: %2 + +Тѳрѳл: %3 + +Хаяг: %4 + + + + Wallet is <b>encrypted</b> and currently <b>unlocked</b> + Түрүйвч <b>цоожтой</b> ба одоогоор цоож <b>онгорхой</b> байна + + + Wallet is <b>encrypted</b> and currently <b>locked</b> + Түрүйвч <b>цоожтой</b> ба одоогоор цоож <b>хаалттай</b> байна + + + A fatal error occurred. Bitcoin can no longer continue safely and will quit. + + + + + ClientModel + + Network Alert + + + + + CoinControlDialog + + Coin Control Address Selection + + + + Quantity: + + + + Bytes: + + + + Amount: + Хэмжээ: + + + Priority: + + + + Fee: + Тѳлбѳр: + + + Low Output: + + + + After Fee: + + + + Change: + + + + (un)select all + + + + Tree mode + + + + List mode + + + + Amount + Хэмжээ + + + Address + Хаяг + + + Date + Огноо + + + Confirmations + + + + Confirmed + Баталгаажлаа + + + Priority + + + + Copy address + Хаягийг санах + + + Copy label + Шошгыг санах + + + Copy amount + Хэмжээг санах + + + Copy transaction ID + + + + Lock unspent + + + + Unlock unspent + + + + Copy quantity + + + + Copy fee + + + + Copy after fee + + + + Copy bytes + + + + Copy priority + + + + Copy low output + + + + Copy change + Ѳѳрчлѳлтийг санах + + + highest + + + + higher + + + + high + + + + medium-high + + + + medium + + + + low-medium + + + + low + + + + lower + + + + lowest + + + + (%1 locked) + + + + none + + + + Dust + + + + yes + + + + no + + + + This label turns red, if the transaction size is greater than 1000 bytes. + + + + This means a fee of at least %1 per kB is required. + + + + Can vary +/- 1 byte per input. + + + + Transactions with higher priority are more likely to get included into a block. + + + + This label turns red, if the priority is smaller than "medium". + + + + This label turns red, if any recipient receives an amount smaller than %1. + + + + This means a fee of at least %1 is required. + + + + Amounts below 0.546 times the minimum relay fee are shown as dust. + + + + This label turns red, if the change is smaller than %1. + + + + (no label) + (шошгогүй) + + + change from %1 (%2) + + + + (change) + (ѳѳрчлѳх) + + + + EditAddressDialog + + Edit Address + Хаягийг ѳѳрчлѳх + + + &Label + &Шошго + + + The label associated with this address list entry + + + + The address associated with this address list entry. This can only be modified for sending addresses. + + + + &Address + &Хаяг + + + New receiving address + Шинэ хүлээн авах хаяг + + + New sending address + Шинэ явуулах хаяг + + + Edit receiving address + Хүлээн авах хаягийг ѳѳрчлѳх + + + Edit sending address + Явуулах хаягийг ѳѳрчлѳх + + + The entered address "%1" is already in the address book. + Таны оруулсан хаяг "%1" нь хаягийн бүртгэлд ѳмнѳ нь орсон байна + + + The entered address "%1" is not a valid Bitcoin address. + + + + Could not unlock wallet. + Түрүйвчийн цоожийг тайлж чадсангүй + + + New key generation failed. + Шинэ түлхүүр амжилттай гарсангүй + + + + FreespaceChecker + + A new data directory will be created. + + + + name + + + + Directory already exists. Add %1 if you intend to create a new directory here. + + + + Path already exists, and is not a directory. + + + + Cannot create data directory here. + + + + + HelpMessageDialog + + Bitcoin Core - Command-line options + + + + Bitcoin Core + + + + version + хувилбар + + + Usage: + Хэрэглээ: + + + command-line options + + + + UI options + + + + Set language, for example "de_DE" (default: system locale) + + + + Start minimized + + + + Set SSL root certificates for payment request (default: -system-) + + + + Show splash screen on startup (default: 1) + + + + Choose data directory on startup (default: 0) + + + + + Intro + + Welcome + + + + Welcome to Bitcoin Core. + + + + As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. + + + + Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. + + + + Use the default data directory + + + + Use a custom data directory: + + + + Bitcoin + Биткойн + + + Error: Specified data directory "%1" can not be created. + + + + Error + Алдаа + + + GB of free space available + + + + (of %1GB needed) + + + + + OpenURIDialog + + Open URI + + + + Open payment request from URI or file + + + + URI: + + + + Select payment request file + + + + Select payment request file to open + + + + + OptionsDialog + + Options + Сонголтууд + + + &Main + + + + Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. + + + + Pay transaction &fee + + + + Automatically start Bitcoin after logging in to the system. + + + + &Start Bitcoin on system login + + + + Size of &database cache + + + + MB + МБ + + + Number of script &verification threads + + + + Connect to the Bitcoin network through a SOCKS proxy. + Биткойны сүлжээрүү SOCKS проксигоор холбогдох. + + + &Connect through SOCKS proxy (default proxy): + + + + IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + проксигийн IP хаяг (жишээ нь: IPv4: 127.0.0.1 / IPv6: ::1) + + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + + + Active command-line options that override above options: + + + + Reset all client options to default. + + + + &Reset Options + + + + &Network + + + + (0 = auto, <0 = leave that many cores free) + + + + W&allet + + + + Expert + + + + Enable coin &control features + + + + If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. + + + + &Spend unconfirmed change + + + + Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. + + + + Map port using &UPnP + + + + Proxy &IP: + + + + &Port: + + + + Port of the proxy (e.g. 9050) + + + + SOCKS &Version: + + + + SOCKS version of the proxy (e.g. 5) + + + + &Window + + + + Show only a tray icon after minimizing the window. + + + + &Minimize to the tray instead of the taskbar + + + + Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. + + + + M&inimize on close + + + + &Display + + + + User Interface &language: + + + + The user interface language can be set here. This setting will take effect after restarting Bitcoin. + + + + &Unit to show amounts in: + + + + Choose the default subdivision unit to show in the interface and when sending coins. + + + + Whether to show Bitcoin addresses in the transaction list or not. + + + + &Display addresses in transaction list + + + + Whether to show coin control features or not. + + + + &OK + + + + &Cancel + + + + default + + + + none + + + + Confirm options reset + + + + Client restart required to activate changes. + Ѳѳрчлѳлтүүдийг идэвхижүүлхийн тулд клиентийг ахин эхлүүлэх шаардлагтай + + + Client will be shutdown, do you want to proceed? + Клиент унтрах гэж байна, яг унтраах уу? + + + This change would require a client restart. + Энэ ѳѳрчлѳлтийг оруулахын тулд кли1нт програмыг ахин эхлүүлэх шаардлагтай + + + The supplied proxy address is invalid. + + + + + OverviewPage + + Form + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. + + + + Wallet + Түрүйвч + + + Available: + Хэрэглэж болох хэмжээ: + + + Your current spendable balance + + + + Pending: + + + + Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance + + + + Immature: + + + + Mined balance that has not yet matured + + + + Total: + + + + Your current total balance + + + + <b>Recent transactions</b> + <b>Сүүлд хийгдсэн гүйлгээнүүд</b> + + + out of sync + + + + + PaymentServer + + URI handling + + + + URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. + + + + Requested payment amount of %1 is too small (considered dust). + + + + Payment request error + + + + Cannot start bitcoin: click-to-pay handler + + + + Net manager warning + + + + Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. + + + + Payment request fetch URL is invalid: %1 + + + + Payment request file handling + + + + Payment request file can not be read or processed! This can be caused by an invalid payment request file. + + + + Unverified payment requests to custom payment scripts are unsupported. + + + + Refund from %1 + + + + Error communicating with %1: %2 + + + + Payment request can not be parsed or processed! + + + + Bad response from server %1 + + + + Payment acknowledged + + + + Network request error + + + + + QObject + + Bitcoin + Биткойн + + + Error: Specified data directory "%1" does not exist. + + + + Error: Cannot parse configuration file: %1. Only use key=value syntax. + + + + Error: Invalid combination of -regtest and -testnet. + + + + Bitcoin Core didn't yet exit safely... + + + + Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + + + + + QRImageWidget + + &Save Image... + + + + &Copy Image + + + + Save QR Code + + + + PNG Image (*.png) + PNG форматын зураг (*.png) + + + + RPCConsole + + Client name + Клиентийн нэр + + + N/A + Алга Байна + + + Client version + Клиентийн хувилбар + + + &Information + &Мэдээллэл + + + Debug window + + + + General + Ерѳнхий + + + Using OpenSSL version + + + + Startup time + + + + Network + Сүлжээ + + + Name + Нэр + + + Number of connections + Холболтын тоо + + + Block chain + Блокийн цуваа + + + Current number of blocks + Одоогийн блокийн тоо + + + Estimated total blocks + Нийт блокийн барагцаа + + + Last block time + Сүүлийн блокийн хугацаа + + + &Open + &Нээх + + + &Console + &Консол + + + &Network Traffic + + + + &Clear + + + + Totals + + + + In: + + + + Out: + + + + Build date + + + + Debug log file + + + + Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. + + + + Clear console + Консолыг цэвэрлэх + + + Welcome to the Bitcoin RPC console. + + + + Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. + + + + Type <b>help</b> for an overview of available commands. + + + + %1 B + + + + %1 KB + + + + %1 MB + + + + %1 GB + + + + %1 m + + + + %1 h + + + + %1 h %2 m + + + + + ReceiveCoinsDialog + + &Amount: + + + + &Label: + &Шошго: + + + &Message: + + + + Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. + + + + R&euse an existing receiving address (not recommended) + + + + An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. + + + + An optional label to associate with the new receiving address. + + + + Use this form to request payments. All fields are <b>optional</b>. + + + + An optional amount to request. Leave this empty or zero to not request a specific amount. + + + + Clear all fields of the form. + + + + Clear + + + + Requested payments history + + + + &Request payment + + + + Show the selected request (does the same as double clicking an entry) + + + + Show + Харуул + + + Remove the selected entries from the list + Сонгогдсон ѳгѳгдлүүдийг устгах + + + Remove + Устгах + + + Copy label + Шошгыг санах + + + Copy message + Зурвасыг санах + + + Copy amount + Хэмжээг санах + + + + ReceiveRequestDialog + + QR Code + + + + Copy &URI + + + + Copy &Address + + + + &Save Image... + + + + Request payment to %1 + + + + Payment information + + + + URI + + + + Address + Хаяг + + + Amount + Хэмжээ + + + Label + Шошго + + + Message + Зурвас + + + Resulting URI too long, try to reduce the text for label / message. + + + + Error encoding URI into QR Code. + + + + + RecentRequestsTableModel + + Date + Огноо + + + Label + Шошго + + + Message + Зурвас + + + Amount + Хэмжээ + + + (no label) + (шошго алга) + + + (no message) + (зурвас алга) + + + (no amount) + + + + + SendCoinsDialog + + Send Coins + Зоос явуулах + + + Coin Control Features + + + + Inputs... + + + + automatically selected + автоматаар сонгогдсон + + + Insufficient funds! + Таны дансны үлдэгдэл хүрэлцэхгүй байна! + + + Quantity: + + + + Bytes: + + + + Amount: + Хэмжээ: + + + Priority: + + + + Fee: + Тѳлбѳр: + + + Low Output: + + + + After Fee: + + + + Change: + + + + If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. + + + + Custom change address + + + + Send to multiple recipients at once + Нэгэн зэрэг олон хүлээн авагчруу явуулах + + + Add &Recipient + &Хүлээн авагчийг Нэмэх + + + Clear all fields of the form. + + + + Clear &All + &Бүгдийг Цэвэрлэ + + + Balance: + Баланс: + + + Confirm the send action + Явуулах үйлдлийг баталгаажуулна уу + + + S&end + Яв&уул + + + Confirm send coins + Зоос явуулахыг баталгаажуулна уу + + + %1 to %2 + + + + Copy quantity + + + + Copy amount + Хэмжээг санах + + + Copy fee + + + + Copy after fee + + + + Copy bytes + + + + Copy priority + + + + Copy low output + + + + Copy change + Ѳѳрчлѳлтийг санах + + + Total Amount %1 (= %2) + Нийт дүн %1 (= %2) + + + or + эсвэл + + + The recipient address is not valid, please recheck. + + + + The amount to pay must be larger than 0. + Тѳлѳх хэмжээ 0.-оос их байх ёстой + + + The amount exceeds your balance. + Энэ хэмжээ таны балансаас хэтэрсэн байна. + + + The total exceeds your balance when the %1 transaction fee is included. + Гүйлгээний тѳлбѳр %1-ийг тооцхоор нийт дүн нь таны балансаас хэтрээд байна. + + + Duplicate address found, can only send to each address once per send operation. + + + + Transaction creation failed! + + + + The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. + + + + Warning: Invalid Bitcoin address + Анхаар:Буруу Биткойны хаяг байна + + + (no label) + (шошгогүй) + + + Warning: Unknown change address + + + + Are you sure you want to send? + + + + added as transaction fee + + + + Payment request expired + + + + Invalid payment address %1 + + + + + SendCoinsEntry + + A&mount: + Дүн: + + + Pay &To: + Тѳлѳх &хаяг: + + + The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + + + + Enter a label for this address to add it to your address book + Энэ хаягийг ѳѳрийн бүртгэлдээ авахын тулд шошго оруул + + + &Label: + &Шошго: + + + Choose previously used address + + + + This is a normal payment. + + + + Alt+A + Alt+A + + + Paste address from clipboard + Копидсон хаягийг буулгах + + + Alt+P + Alt+P + + + Remove this entry + + + + Message: + Зурвас: + + + This is a verified payment request. + + + + Enter a label for this address to add it to the list of used addresses + + + + A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network. + + + + This is an unverified payment request. + + + + Pay To: + + + + Memo: + + + + + ShutdownWindow + + Bitcoin Core is shutting down... + Биткойны цѳм хаагдаж байна... + + + Do not shut down the computer until this window disappears. + Энэ цонхыг хаагдтал компьютерээ бүү унтраагаарай + + + + SignVerifyMessageDialog + + Signatures - Sign / Verify a Message + + + + &Sign Message + + + + You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. + + + + The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + + + + Choose previously used address + + + + Alt+A + Alt+A + + + Paste address from clipboard + Копидсон хаягийг буулгах + + + Alt+P + Alt+P + + + Enter the message you want to sign here + + + + Signature + + + + Copy the current signature to the system clipboard + + + + Sign the message to prove you own this Bitcoin address + + + + Sign &Message + + + + Reset all sign message fields + + + + Clear &All + &Бүгдийг Цэвэрлэ + + + &Verify Message + + + + Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. + + + + The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + + + + Verify the message to ensure it was signed with the specified Bitcoin address + + + + Verify &Message + + + + Reset all verify message fields + + + + Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + + + + Click "Sign Message" to generate signature + + + + The entered address is invalid. + + + + Please check the address and try again. + + + + The entered address does not refer to a key. + + + + Wallet unlock was cancelled. + + + + Private key for the entered address is not available. + + + + Message signing failed. + + + + Message signed. + + + + The signature could not be decoded. + + + + Please check the signature and try again. + + + + The signature did not match the message digest. + + + + Message verification failed. + + + + Message verified. + + + + + SplashScreen + + Bitcoin Core + + + + The Bitcoin Core developers + + + + [testnet] + + + + + TrafficGraphWidget + + KB/s + + + + + TransactionDesc + + Open until %1 + %1 хүртэл нээлттэй + + + conflicted + зѳрчилдлѳѳ + + + %1/offline + + + + %1/unconfirmed + %1/баталгаажаагүй + + + %1 confirmations + %1 баталгаажилтууд + + + Status + + + + , broadcast through %n node(s) + + + + Date + Огноо + + + Source + + + + Generated + + + + From + + + + To + + + + own address + + + + label + + + + Credit + + + + matures in %n more block(s) + + + + not accepted + + + + Debit + + + + Transaction fee + + + + Net amount + + + + Message + Зурвас + + + Comment + + + + Transaction ID + + + + Merchant + + + + Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. + + + + Debug information + + + + Transaction + + + + Inputs + + + + Amount + Хэмжээ + + + true + + + + false + + + + , has not been successfully broadcast yet + , хараахан амжилттай цацагдаагүй байна + + + Open for %n more block(s) + + + + unknown + үл мэдэгдэх + + + + TransactionDescDialog + + Transaction details + Гүйлгээний мэдээллэл + + + This pane shows a detailed description of the transaction + Гүйлгээний дэлгэрэнгүйг энэ бичил цонх харуулж байна + + + + TransactionTableModel + + Date + Огноо + + + Type + Тѳрѳл + + + Address + Хаяг + + + Amount + Хэмжээ + + + Immature (%1 confirmations, will be available after %2) + + + + Open for %n more block(s) + + + + Open until %1 + %1 хүртэл нээлттэй + + + Confirmed (%1 confirmations) + Баталгаажлаа (%1 баталгаажилт) + + + This block was not received by any other nodes and will probably not be accepted! + Энэ блокийг аль ч нод хүлээн авсангүй ба ер нь зѳвшѳѳрѳгдѳхгүй байж мэднэ! + + + Generated but not accepted + Үүсгэгдсэн гэхдээ хүлээн авагдаагүй + + + Offline + + + + Unconfirmed + Баталгаажаагүй + + + Confirming (%1 of %2 recommended confirmations) + + + + Conflicted + Зѳрчилдлѳѳ + + + Received with + Хүлээн авсан хаяг + + + Received from + Хүлээн авагдсан хаяг + + + Sent to + Явуулсан хаяг + + + Payment to yourself + Ѳѳрлүүгээ хийсэн тѳлбѳр + + + Mined + Олборлогдсон + + + (n/a) + (алга байна) + + + Transaction status. Hover over this field to show number of confirmations. + Гүйлгээний байдал. Энд хулганыг авчирч баталгаажуулалтын тоог харна уу. + + + Date and time that the transaction was received. + Гүйлгээг хүлээн авсан огноо ба цаг. + + + Type of transaction. + Гүйлгээний тѳрѳл + + + Destination address of transaction. + Гүйлгээг хүлээн авах хаяг + + + Amount removed from or added to balance. + Балансаас авагдсан болон нэмэгдсэн хэмжээ. + + + + TransactionView + + All + Бүгд + + + Today + Ѳнѳѳдѳр + + + This week + Энэ долоо хоног + + + This month + Энэ сар + + + Last month + Ѳнгѳрсѳн сар + + + This year + Энэ жил + + + Range... + + + + Received with + Хүлээн авсан хаяг + + + Sent to + Явуулсан хаяг + + + To yourself + Ѳѳрлүүгээ + + + Mined + Олборлогдсон + + + Other + Бусад + + + Enter address or label to search + Хайлт хийхийн тулд хаяг эсвэл шошгыг оруул + + + Min amount + Хамгийн бага хэмжээ + + + Copy address + Хаягийг санах + + + Copy label + Шошгыг санах + + + Copy amount + Хэмжээг санах + + + Copy transaction ID + + + + Edit label + Шошгыг ѳѳрчлѳх + + + Show transaction details + Гүйлгээний дэлгэрэнгүйг харуул + + + Export Transaction History + + + + Exporting Failed + + + + There was an error trying to save the transaction history to %1. + + + + Exporting Successful + + + + The transaction history was successfully saved to %1. + Гүйлгээнүй түүхийг %1-д амжилттай хадгаллаа. + + + Comma separated file (*.csv) + Таслалаар тусгаарлагдсан хүснэгтэн файл (.csv) + + + Confirmed + Баталгаажлаа + + + Date + Огноо + + + Type + Тѳрѳл + + + Label + Шошго + + + Address + Хаяг + + + Amount + Хэмжээ + + + ID + Тодорхойлолт + + + Range: + + + + to + -рүү/руу + + + + WalletFrame + + No wallet has been loaded. + Ямар ч түрүйвч ачааллагдсангүй. + + + + WalletModel + + Send Coins + Зоос явуулах + + + + WalletView + + &Export + + + + Export the data in the current tab to a file + + + + Backup Wallet + + + + Wallet Data (*.dat) + + + + Backup Failed + + + + There was an error trying to save the wallet data to %1. + + + + The wallet data was successfully saved to %1. + + + + Backup Successful + + + + + bitcoin-core + + Usage: + Хэрэглээ: + + + List commands + Үйлдлүүдийг жагсаах + + + Get help for a command + Үйлдэлд туслалцаа авах + + + Options: + Сонголтууд: + + + Specify configuration file (default: bitcoin.conf) + + + + Specify pid file (default: bitcoind.pid) + + + + Specify data directory + + + + Listen for connections on <port> (default: 8333 or testnet: 18333) + <port> дээрх холболтуудыг чагна (ѳгѳгдмѳл: 8333 эсвэл testnet: 18333) + + + Maintain at most <n> connections to peers (default: 125) + + + + Connect to a node to retrieve peer addresses, and disconnect + + + + Specify your own public address + + + + Threshold for disconnecting misbehaving peers (default: 100) + + + + Number of seconds to keep misbehaving peers from reconnecting (default: 86400) + + + + An error occurred while setting up the RPC port %u for listening on IPv4: %s + + + + Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332) + + + + Accept command line and JSON-RPC commands + + + + Bitcoin Core RPC client version + + + + Run in the background as a daemon and accept commands + + + + Use the test network + + + + Accept connections from outside (default: 1 if no -proxy or -connect) + + + + %s, you must set a rpcpassword in the configuration file: +%s +It is recommended you use the following random password: +rpcuser=bitcoinrpc +rpcpassword=%s +(you do not need to remember this password) +The username and password MUST NOT be the same. +If the file does not exist, create it with owner-readable-only file permissions. +It is also recommended to set alertnotify so you are notified of problems; +for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com + + + + + Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH) + + + + An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s + + + + Bind to given address and always listen on it. Use [host]:port notation for IPv6 + + + + Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15) + + + + Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development. + + + + Enter regression test mode, which uses a special chain in which blocks can be solved instantly. + + + + Error: Listening for incoming connections failed (listen returned error %d) + + + + Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. + + + + Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! + + + + Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) + + + + Fees smaller than this are considered zero fee (for transaction creation) (default: + + + + Flush database activity from memory pool to disk log every <n> megabytes (default: 100) + + + + How thorough the block verification of -checkblocks is (0-4, default: 3) + + + + In this mode -genproclimit controls how many blocks are generated immediately. + + + + Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) + + + + Set the processor limit for when generation is on (-1 = unlimited, default: -1) + + + + This is a pre-release test build - use at your own risk - do not use for mining or merchant applications + + + + Unable to bind to %s on this computer. Bitcoin Core is probably already running. + + + + Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy) + + + + Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. + + + + Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly. + + + + Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. + + + + Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. + + + + Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. + + + + Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. + + + + (default: 1) + + + + (default: wallet.dat) + + + + <category> can be: + + + + Attempt to recover private keys from a corrupt wallet.dat + + + + Bitcoin Core Daemon + + + + Block creation options: + + + + Clear list of wallet transactions (diagnostic tool; implies -rescan) + + + + Connect only to the specified node(s) + + + + Connect through SOCKS proxy + SOCKS проксигоор холбогдох + + + Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) + + + + Connection options: + + + + Corrupted block database detected + + + + Debugging/Testing options: + + + + Disable safemode, override a real safe mode event (default: 0) + + + + Discover own IP address (default: 1 when listening and no -externalip) + + + + Do not load the wallet and disable wallet RPC calls + + + + Do you want to rebuild the block database now? + + + + Error initializing block database + + + + Error initializing wallet database environment %s! + + + + Error loading block database + + + + Error opening block database + + + + Error: Disk space is low! + + + + Error: Wallet locked, unable to create transaction! + + + + Error: system error: + + + + Failed to listen on any port. Use -listen=0 if you want this. + + + + Failed to read block info + + + + Failed to read block + + + + Failed to sync block index + + + + Failed to write block index + + + + Failed to write block info + + + + Failed to write block + + + + Failed to write file info + + + + Failed to write to coin database + + + + Failed to write transaction index + + + + Failed to write undo data + + + + Fee per kB to add to transactions you send + + + + Fees smaller than this are considered zero fee (for relaying) (default: + + + + Find peers using DNS lookup (default: 1 unless -connect) + + + + Force safe mode (default: 0) + + + + Generate coins (default: 0) + + + + How many blocks to check at startup (default: 288, 0 = all) + + + + If <category> is not supplied, output all debugging information. + + + + Importing... + + + + Incorrect or no genesis block found. Wrong datadir for network? + + + + Invalid -onion address: '%s' + + + + Not enough file descriptors available. + + + + Prepend debug output with timestamp (default: 1) + + + + RPC client options: + + + + Rebuild block chain index from current blk000??.dat files + + + + Select SOCKS version for -proxy (4 or 5, default: 5) + + + + Set database cache size in megabytes (%d to %d, default: %d) + + + + Set maximum block size in bytes (default: %d) + + + + Set the number of threads to service RPC calls (default: 4) + + + + Specify wallet file (within data directory) + + + + Spend unconfirmed change when sending transactions (default: 1) + + + + This is intended for regression testing tools and app development. + + + + Usage (deprecated, use bitcoin-cli): + + + + Verifying blocks... + + + + Verifying wallet... + + + + Wait for RPC server to start + RPC серверийг эхэлтэл хүлээ + + + Wallet %s resides outside data directory %s + + + + Wallet options: + Түрүйвчийн сонголтууд: + + + Warning: Deprecated argument -debugnet ignored, use -debug=net + + + + You need to rebuild the database using -reindex to change -txindex + + + + Imports blocks from external blk000??.dat file + + + + Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. + + + + Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) + + + + Output debugging information (default: 0, supplying <category> is optional) + + + + Set maximum size of high-priority/low-fee transactions in bytes (default: %d) + + + + Information + + + + Invalid amount for -minrelaytxfee=<amount>: '%s' + + + + Invalid amount for -mintxfee=<amount>: '%s' + + + + Limit size of signature cache to <n> entries (default: 50000) + + + + Log transaction priority and fee per kB when mining blocks (default: 0) + + + + Maintain a full transaction index (default: 0) + + + + Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) + + + + Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) + + + + Only accept block chain matching built-in checkpoints (default: 1) + + + + Only connect to nodes in network <net> (IPv4, IPv6 or Tor) + + + + Print block on startup, if found in block index + + + + Print block tree on startup (default: 0) + + + + RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + RPC server options: + + + + Randomly drop 1 of every <n> network messages + + + + Randomly fuzz 1 of every <n> network messages + + + + Run a thread to flush wallet periodically (default: 1) + + + + SSL options: (see the Bitcoin Wiki for SSL setup instructions) + + + + Send command to Bitcoin Core + + + + Send trace/debug info to console instead of debug.log file + + + + Set minimum block size in bytes (default: 0) + + + + Sets the DB_PRIVATE flag in the wallet db environment (default: 1) + + + + Show all debugging options (usage: --help -help-debug) + + + + Show benchmark information (default: 0) + + + + Shrink debug.log file on client startup (default: 1 when no -debug) + + + + Signing transaction failed + + + + Specify connection timeout in milliseconds (default: 5000) + + + + Start Bitcoin Core Daemon + + + + System error: + + + + Transaction amount too small + + + + Transaction amounts must be positive + + + + Transaction too large + + + + Use UPnP to map the listening port (default: 0) + + + + Use UPnP to map the listening port (default: 1 when listening) + + + + Username for JSON-RPC connections + + + + Warning + + + + Warning: This version is obsolete, upgrade required! + + + + Zapping all transactions from wallet... + + + + on startup + + + + version + хувилбар + + + wallet.dat corrupt, salvage failed + + + + Password for JSON-RPC connections + + + + Allow JSON-RPC connections from specified IP address + + + + Send commands to node running on <ip> (default: 127.0.0.1) + + + + Execute command when the best block changes (%s in cmd is replaced by block hash) + + + + Upgrade wallet to latest format + Түрүйвчийг хамгийн сүүлийн үеийн форматруу шинэчлэх + + + Set key pool size to <n> (default: 100) + + + + Rescan the block chain for missing wallet transactions + + + + Use OpenSSL (https) for JSON-RPC connections + + + + Server certificate file (default: server.cert) + + + + Server private key (default: server.pem) + + + + This help message + + + + Unable to bind to %s on this computer (bind returned error %d, %s) + + + + Allow DNS lookups for -addnode, -seednode and -connect + + + + Loading addresses... + Хаягуудыг ачааллаж байна... + + + Error loading wallet.dat: Wallet corrupted + wallet.dat-ыг ачааллахад алдаа гарлаа: Түрүйвч эвдэрсэн байна + + + Error loading wallet.dat: Wallet requires newer version of Bitcoin + wallet.dat-ыг ачааллахад алдаа гарлаа: Түрүйвч Биткойны шинэ хувилбарыг шаардаж байна + + + Wallet needed to be rewritten: restart Bitcoin to complete + + + + Error loading wallet.dat + wallet.dat-ыг ачааллахад алдаа гарлаа + + + Invalid -proxy address: '%s' + Эдгээр прокси хаягнууд буруу байна: '%s' + + + Unknown network specified in -onlynet: '%s' + + + + Unknown -socks proxy version requested: %i + + + + Cannot resolve -bind address: '%s' + + + + Cannot resolve -externalip address: '%s' + + + + Invalid amount for -paytxfee=<amount>: '%s' + + + + Invalid amount + Буруу хэмжээ + + + Insufficient funds + Таны дансны үлдэгдэл хүрэлцэхгүй байна + + + Loading block index... + Блокийн индексүүдийг ачааллаж байна... + + + Add a node to connect to and attempt to keep the connection open + Холболт хийхийн тулд мѳн холболтой онгорхой хадгалхын тулд шинэ нод нэм + + + Loading wallet... + Түрүйвчийг ачааллаж байна... + + + Cannot downgrade wallet + + + + Cannot write default address + + + + Rescanning... + Ахин уншиж байна... + + + Done loading + Ачааллаж дууслаа + + + To use the %s option + %s сонголтыг ашиглахын тулд + + + Error + Алдаа + + + You must set rpcpassword=<password> in the configuration file: +%s +If the file does not exist, create it with owner-readable-only file permissions. + + + + \ No newline at end of file diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts index 9835a2e19f..0f92a6d49f 100644 --- a/src/qt/locale/bitcoin_ms_MY.ts +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 078bad7edc..09ef29d871 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adresse: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP-adressen til proxyen (f.eks. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: Aktive kommandolinjevalg som overstyrer valgene ovenfor: @@ -1349,8 +1357,8 @@ Adresse: %4 Feil: Ugyldig kombinasjon av -regtest og -testnet. - Bitcoin Core did't yet exit safely... - Bitcoin Core har annå ikke avsluttet på en sikker måte... + Bitcoin Core didn't yet exit safely... + Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index 0da46059b5..8cbbbdad7f 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adres: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP-adres van de proxy (bijv. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Derde partijen URL's (bijvoorbeeld block explorer) dat in de transacties tab verschijnen als contextmenu elementen. %s in de URL is vervangen door transactie hash. Verscheidene URL's zijn gescheiden door een verticale streep |. + + + Third party transaction URLs + Transactie-URLs van derde partijen + Active command-line options that override above options: Actieve commandoregelopties die bovenstaande opties overschrijven: @@ -1349,8 +1357,8 @@ Adres: %4 Fout: Ongeldige combinatie van -regtest en -testnet - Bitcoin Core did't yet exit safely... - + Bitcoin Core didn't yet exit safely... + Bitcoin Core is nog niet veilig uitgeschakeld... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2959,7 +2967,7 @@ bijvoorbeeld: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo Importing... - + Importeren... Incorrect or no genesis block found. Wrong datadir for network? diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts index 4a5e0363a8..22f1b7ccc3 100644 --- a/src/qt/locale/bitcoin_pam.ts +++ b/src/qt/locale/bitcoin_pam.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1045,6 +1045,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1347,7 +1355,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index 06845bfc3b..cbc08dd25d 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adres: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Adres IP serwera proxy (np. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1287,7 +1295,7 @@ Adres: %4 Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. - + Twoje aktywne proxy nie obsługuje SOCKS5, co jest wymagane dla żądania płatności przez proxy. Payment request fetch URL is invalid: %1 @@ -1349,8 +1357,8 @@ Adres: %4 Błąd: Niepoprawna kombinacja -regtest i -testnet. - Bitcoin Core did't yet exit safely... - + Bitcoin Core didn't yet exit safely... + Bitcoin Core jeszcze się nie wyłączył bezpiecznie… Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1555,7 +1563,7 @@ Adres: %4 Use this form to request payments. All fields are <b>optional</b>. - + Użyj tego formularza do zażądania płatności. Wszystkie pola są <b>opcjonalne</b>. An optional amount to request. Leave this empty or zero to not request a specific amount. @@ -2790,11 +2798,11 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo (default: 1) - + (domyślnie: 1) (default: wallet.dat) - + (domyślnie: wallet.dat) <category> can be: @@ -2934,7 +2942,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Fees smaller than this are considered zero fee (for relaying) (default: - + Opłaty mniejsze niż to są uznawane za nieistniejące (przy przekazywaniu) (domyślnie: Find peers using DNS lookup (default: 1 unless -connect) @@ -2958,7 +2966,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Importing... - + Importowanie… Incorrect or no genesis block found. Wrong datadir for network? @@ -3082,7 +3090,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Log transaction priority and fee per kB when mining blocks (default: 0) - + Loguj priorytety transakcji i opłaty na kB podczas kopania bloków (domyślnie: 0) Maintain a full transaction index (default: 0) @@ -3106,7 +3114,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Print block on startup, if found in block index - + Wyświetlaj blok podczas uruchamiania, jeżeli znaleziono indeks bloków Print block tree on startup (default: 0) @@ -3122,7 +3130,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Randomly drop 1 of every <n> network messages - + Losowo ignoruje 1 z każdych <n> wiadomości sieciowych. Randomly fuzz 1 of every <n> network messages @@ -3130,7 +3138,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Run a thread to flush wallet periodically (default: 1) - + Uruchom wątek do okresowego zapisywania portfela (domyślnie: 1) SSL options: (see the Bitcoin Wiki for SSL setup instructions) @@ -3138,7 +3146,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Send command to Bitcoin Core - + Wyślij komendę do Bitcoin Core Send trace/debug info to console instead of debug.log file @@ -3218,7 +3226,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo on startup - + podczas uruchamiania version diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index 94a87596ca..ee1c2a7381 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Endereço: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Endereço de IP do proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: Ativa as opções de linha de comando que sobrescreve as opções acima: @@ -1348,7 +1356,7 @@ Endereço: %4 Erro: Combinação inválida de-regtest e testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index d6dbbbf42a..7a9595a6dd 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1046,6 +1046,14 @@ Endereço: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Endereço IP do proxy (p.ex. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: Opções de linha de comandos ativas que se sobrepõem ás opções anteriores: @@ -1348,7 +1356,7 @@ Endereço: %4 Erro: Combinação inválida de -regtest e -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index 0a310db989..1d9d4cc936 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adresa: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Adresa: %4 Eroare: combinație nevalidă de -regtest și -testnet. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index d9840a9c5e..570c3a61e7 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) IP-адрес прокси (например IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Сторонние URL (например, block explorer), которые отображаются на вкладке транзакций как пункты контекстного меню. %s в URL заменяется хэшем транзакции. URL отделяются друг от друга вертикальной чертой |. + + + Third party transaction URLs + Сторонние URL транзакций. + Active command-line options that override above options: Активные опции командной строки, которые перекрывают вышеуказанные опции: @@ -1349,8 +1357,8 @@ Address: %4 Ошибка: неверная комбинация -regtest и -testnet. - Bitcoin Core did't yet exit safely... - Bitcoin Core еще не готов к безопасному завершению... + Bitcoin Core didn't yet exit safely... + Bitcoin Core ещё не завершился безопасно... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_sah.ts b/src/qt/locale/bitcoin_sah.ts index 5cdf9a93d7..3bc3e65c62 100644 --- a/src/qt/locale/bitcoin_sah.ts +++ b/src/qt/locale/bitcoin_sah.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index b12462dbb2..d96e9d9366 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -63,7 +63,7 @@ This product includes software developed by the OpenSSL Project for use in the O Delete the currently selected address from the list - + Vymaž vybranú adresu zo zoznamu Export the data in the current tab to a file @@ -79,11 +79,11 @@ This product includes software developed by the OpenSSL Project for use in the O Choose the address to send coins to - + Zvoľte adresu kam poslať coins Choose the address to receive coins with - + Zvoľte adresu na ktorú prijať coins C&hoose @@ -99,11 +99,11 @@ This product includes software developed by the OpenSSL Project for use in the O These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. - + Toto sú Vaše Bitcoin adresy pre posielanie platieb. Vždy skontrolujte množstvo a prijímaciu adresu pred poslaním coins. These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - + Toto sú vaše Bitcoin adresy pre prijímanie platieb. Odporúča sa použiť novú prijímaciu adresu pre každú transakciu. Copy &Label @@ -127,7 +127,7 @@ This product includes software developed by the OpenSSL Project for use in the O There was an error trying to save the address list to %1. - + Nastala chyba pri pokuse uložiť zoznam adries do %1. @@ -392,15 +392,15 @@ This product includes software developed by the OpenSSL Project for use in the O Encrypt the private keys that belong to your wallet - + Zašifruj súkromné kľúče ktoré patria do vašej peňaženky Sign messages with your Bitcoin addresses to prove you own them - + Podpísať správu s vašou adresou Bitcoin aby ste preukázali že ju vlastníte Verify messages to ensure they were signed with specified Bitcoin addresses - + Overiť či správa bola podpísaná uvedenou Bitcoin adresou &File @@ -428,7 +428,7 @@ This product includes software developed by the OpenSSL Project for use in the O Request payments (generates QR codes and bitcoin: URIs) - + Vyžiadať platbu (vygeneruje QR kód a bitcoin: URI) &About Bitcoin Core @@ -436,11 +436,11 @@ This product includes software developed by the OpenSSL Project for use in the O Show the list of used sending addresses and labels - + Zobraziť zoznam použitých adries odosielateľa a ich popisy Show the list of used receiving addresses and labels - + Zobraziť zoznam použitých prijímacích adries a ich popisov Open a bitcoin: URI or payment request @@ -448,7 +448,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Command-line options - Voľby príkazového riadku + Možnosti príkazového riadku Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options @@ -488,15 +488,15 @@ This product includes software developed by the OpenSSL Project for use in the O %1 and %2 - + %1 a %2 %n year(s) - + %%d)%n rokov %1 behind - %1 za + %1 pozadu Last received block was generated %1 ago. @@ -555,7 +555,7 @@ Adresa: %4 A fatal error occurred. Bitcoin can no longer continue safely and will quit. - + Vyskytla sa neblahá chyba. Bitcoin nemôže daľej bezpečne pokračovať a vypne sa. @@ -569,7 +569,7 @@ Adresa: %4 CoinControlDialog Coin Control Address Selection - + Coin Control výber adresy Quantity: @@ -593,11 +593,11 @@ Adresa: %4 Low Output: - + Malá hodnota na výstupe: After Fee: - + Po poplatku: Change: @@ -605,7 +605,7 @@ Adresa: %4 (un)select all - + (ne)vybrať všetko Tree mode @@ -657,11 +657,11 @@ Adresa: %4 Lock unspent - + Uzamknúť neminuté Unlock unspent - + Odomknúť neminuté Copy quantity @@ -729,7 +729,7 @@ Adresa: %4 (%1 locked) - + (%1 zamknutých) none @@ -777,7 +777,7 @@ Adresa: %4 Amounts below 0.546 times the minimum relay fee are shown as dust. - + Sumy pod 0.546 násobkom minimálneho poplatku pre prenos sú považované za prach. This label turns red, if the change is smaller than %1. @@ -808,11 +808,11 @@ Adresa: %4 The label associated with this address list entry - + Popis tejto položký v zozname adries je prázdny The address associated with this address list entry. This can only be modified for sending addresses. - + Adresa spojená s týmto záznamom v adresári. Možno upravovať len pre odosielajúce adresy. &Address @@ -863,7 +863,7 @@ Adresa: %4 Directory already exists. Add %1 if you intend to create a new directory here. - + Priečinok už existuje. Pridajte "%1" ak chcete vytvoriť nový priečinok tu. Path already exists, and is not a directory. @@ -878,7 +878,7 @@ Adresa: %4 HelpMessageDialog Bitcoin Core - Command-line options - + Jadro Bitcoin - možnosti príkazového riadku Bitcoin Core @@ -937,7 +937,7 @@ Adresa: %4 Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - + Jadro Bitcoin stiahne zo siete a uloží kópiu Bitcoin blockchain. Aspoň %1GB dát bude uložených v tomto priečinku a časom porastie. Peňaženka bude tiež uložená v tomto priečinku. Use the default data directory @@ -953,7 +953,7 @@ Adresa: %4 Error: Specified data directory "%1" can not be created. - + Chyba: Predpísaný priečinok pre dáta "%1" nemôže byt vytvorený. Error @@ -976,7 +976,7 @@ Adresa: %4 Open payment request from URI or file - + Otvoriť požiadavku na zaplatenie z URI alebo súboru URI: @@ -984,11 +984,11 @@ Adresa: %4 Select payment request file - + Vyberte súbor s výzvou k platbe Select payment request file to open - + Vyberte ktorý súbor s výzvou k platbe otvoriť @@ -1003,7 +1003,7 @@ Adresa: %4 Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. - + Voliteľný transakčný poplatok za kB ktorý pomôže rýchlemu spracovaniu transakcie. Väčšina transakcií má 1 kB. Poplatok 0.01 je odporúčaný. Pay transaction &fee @@ -1019,7 +1019,7 @@ Adresa: %4 Size of &database cache - + Veľkosť vyrovnávacej pamäti databázy MB @@ -1031,15 +1031,23 @@ Adresa: %4 Connect to the Bitcoin network through a SOCKS proxy. - + Pripojiť k Bitcoin sieti cez SOCKS proxy. &Connect through SOCKS proxy (default proxy): - + Pripojiť sa cez SOCKS proxy (predvolené proxy) IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) - + IP adresy proxy (napr. IPv4: 127.0.0.1 / IPv6: ::1) + + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + URL tretích strán (napr. prehliadač blockchain) ktoré sa zobrazujú v záložke transakcií ako položky kontextového menu. %s v URL je nahradené hash-om transakcie. Viaceré URL sú oddelené zvislou čiarou |. + + + Third party transaction URLs + URL transakcií s tretími stranami Active command-line options that override above options: @@ -1063,15 +1071,15 @@ Adresa: %4 W&allet - + Peňaženka Expert - + Expert Enable coin &control features - + Povoliť možnosti coin control If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. @@ -1139,7 +1147,7 @@ Adresa: %4 The user interface language can be set here. This setting will take effect after restarting Bitcoin. - + Tu sa dá nastaviť jazyk užívateľského rozhrania. Toto nastavenie bude účinné po reštartovaní Bitcoin. &Unit to show amounts in: @@ -1147,11 +1155,11 @@ Adresa: %4 Choose the default subdivision unit to show in the interface and when sending coins. - + Zvoľte ako deliť bitcoin pri zobrazovaní pri platbách a užívateľskom rozhraní. Whether to show Bitcoin addresses in the transaction list or not. - + Či ukazovať Bitcoin adresy v zozname transakcií alebo nie. &Display addresses in transaction list @@ -1159,7 +1167,7 @@ Adresa: %4 Whether to show coin control features or not. - + Či zobrazovať možnosti "Coin control" alebo nie. &OK @@ -1179,19 +1187,19 @@ Adresa: %4 Confirm options reset - + Potvrdiť obnovenie možností Client restart required to activate changes. - + Reštart klienta potrebný pre aktivovanie zmien. Client will be shutdown, do you want to proceed? - + Klient bude vypnutý, chcete pokračovať? This change would require a client restart. - + Táto zmena by vyžadovala reštart klienta. The supplied proxy address is invalid. @@ -1206,7 +1214,7 @@ Adresa: %4 The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. - + Zobrazené informácie môžu byť neaktuápne. Vaša peňaženka sa automaticky synchronizuje so sieťou Bitcoin po nadviazaní spojenia ale tento proces ešte nieje ukončený. Wallet @@ -1214,19 +1222,19 @@ Adresa: %4 Available: - + Disponibilné: Your current spendable balance - + Váš aktuálny disponibilný zostatok Pending: - + Čakajúce potvrdenie Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance - + Suma transakcií ktoré ešte neboli potvrdené a ešte sa nepočítajú do disponibilného zostatku Immature: @@ -1234,7 +1242,7 @@ Adresa: %4 Mined balance that has not yet matured - + Vytvorený zostatok ktorý ešte nedosiahol zrelosť Total: @@ -1261,15 +1269,15 @@ Adresa: %4 URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - + URI sa nedá rozložiť! To môže byť spôsobené neplatou Bitcoin adresou alebo zle upravenými vlastnosťami URI. Requested payment amount of %1 is too small (considered dust). - + Požadovaná platba sumy %1 je príliš malá (považovaná za prach). Payment request error - + Chyba pri vyžiadaní platby Cannot start bitcoin: click-to-pay handler @@ -1277,7 +1285,7 @@ Adresa: %4 Net manager warning - + Varovanie správcu siete Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. @@ -1297,15 +1305,15 @@ Adresa: %4 Unverified payment requests to custom payment scripts are unsupported. - + Program nepodporuje neoverené platobné výzvy na vlastná skripty. Refund from %1 - + Vrátenie z %1 Error communicating with %1: %2 - + Chyba komunikácie s %1: %2 Payment request can not be parsed or processed! @@ -1317,11 +1325,11 @@ Adresa: %4 Payment acknowledged - + Platba potvrdená Network request error - + Chyba požiadavky siete @@ -1332,7 +1340,7 @@ Adresa: %4 Error: Specified data directory "%1" does not exist. - + Chyba: Uvedený priečinok s dátami "%1" neexistuje. Error: Cannot parse configuration file: %1. Only use key=value syntax. @@ -1340,11 +1348,11 @@ Adresa: %4 Error: Invalid combination of -regtest and -testnet. - + Chyba: Nesprávna kombinácia -regtest a -testnet. - Bitcoin Core did't yet exit safely... - + Bitcoin Core didn't yet exit safely... + Jadro Bitcoin sa ešte úspešne nevyplo ... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1478,15 +1486,15 @@ Adresa: %4 Welcome to the Bitcoin RPC console. - + Vitajte v Bitcoin RPC konzole. Baník, pyčo! Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. - + Použi šipky hore a dolu pre navigáciu históriou a <b>Ctrl-L</b> pre vyčistenie obrazovky. Type <b>help</b> for an overview of available commands. - + Napíš <b>help</b> pre prehľad dostupných príkazov. %1 B @@ -1545,11 +1553,11 @@ Adresa: %4 An optional label to associate with the new receiving address. - + Voliteľný popis ktorý sa pridá k tejto novej prijímajúcej adrese. Use this form to request payments. All fields are <b>optional</b>. - + Použite tento formulár pre vyžiadanie platby. Všetky polia sú <b>voliteľné</b>. An optional amount to request. Leave this empty or zero to not request a specific amount. @@ -1573,7 +1581,7 @@ Adresa: %4 Show the selected request (does the same as double clicking an entry) - + Zobraz zvolenú požiadavku (urobí to isté ako dvoj-klik na záznam) Show @@ -1581,7 +1589,7 @@ Adresa: %4 Remove the selected entries from the list - + Odstrániť zvolené záznamy zo zoznamu Remove @@ -1694,7 +1702,7 @@ Adresa: %4 Coin Control Features - + Možnosti "Coin Control" Inputs... @@ -1730,11 +1738,11 @@ Adresa: %4 Low Output: - + Malá hodnota na výstupe: After Fee: - + Po poplatku: Change: @@ -1854,7 +1862,7 @@ Adresa: %4 Warning: Invalid Bitcoin address - + Varovanie: Nesprávna Bitcoin adresa (no label) @@ -1862,7 +1870,7 @@ Adresa: %4 Warning: Unknown change address - + Varovanie: Neznáma adresa pre výdavok Are you sure you want to send? @@ -1874,7 +1882,7 @@ Adresa: %4 Payment request expired - + Vypršala platnosť požiadavky na platbu Invalid payment address %1 @@ -1933,7 +1941,7 @@ Adresa: %4 This is a verified payment request. - + Toto je overená výzva k platbe. Enter a label for this address to add it to the list of used addresses @@ -1945,7 +1953,7 @@ Adresa: %4 This is an unverified payment request. - + Toto je neoverená výzva k platbe. Pay To: @@ -1953,7 +1961,7 @@ Adresa: %4 Memo: - + Poznámka: @@ -1964,14 +1972,14 @@ Adresa: %4 Do not shut down the computer until this window disappears. - + Nevypínajte počítač kým toto okno nezmizne. SignVerifyMessageDialog Signatures - Sign / Verify a Message - + Podpisy - Podpísať / Overiť správu &Sign Message @@ -2011,7 +2019,7 @@ Adresa: %4 Copy the current signature to the system clipboard - + Kopírovať práve zvolenú adresu do systémového klipbordu Sign the message to prove you own this Bitcoin address @@ -2023,7 +2031,7 @@ Adresa: %4 Reset all sign message fields - + Vynulovať všetky polia podpisu správy Clear &All @@ -2035,7 +2043,7 @@ Adresa: %4 Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. - + Vložte podpisovaciu adresu, správu (uistite sa, že kopírujete ukončenia riadkov, medzery, odrážky, atď. presne) a podpis pod to na overenie adresy. Buďte opatrní a nečítajte ako podpísané viac než je v samotnej podpísanej správe a môžete sa tak vyhnúť podvodu mitm útokom. The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2043,7 +2051,7 @@ Adresa: %4 Verify the message to ensure it was signed with the specified Bitcoin address - + Overím správy sa uistiť že bola podpísaná označenou Bitcoin adresou Verify &Message @@ -2051,7 +2059,7 @@ Adresa: %4 Reset all verify message fields - + Obnoviť všetky polia v overiť správu Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2071,7 +2079,7 @@ Adresa: %4 The entered address does not refer to a key. - + Vložená adresa nezodpovedá žiadnemu kľúcu. Wallet unlock was cancelled. @@ -2079,7 +2087,7 @@ Adresa: %4 Private key for the entered address is not available. - + Súkromný kľúč pre vložená adresu nieje k dispozícii. Message signing failed. @@ -2099,7 +2107,7 @@ Adresa: %4 The signature did not match the message digest. - + Podpis sa nezhoduje so zhrnutím správy Message verification failed. @@ -2140,7 +2148,7 @@ Adresa: %4 conflicted - + sporné %1/offline @@ -2160,7 +2168,7 @@ Adresa: %4 , broadcast through %n node(s) - + ,,, vysielať cez %n nód Date @@ -2196,7 +2204,7 @@ Adresa: %4 matures in %n more block(s) - + Dospeje o %n blokovDospeje o %n blokovdospeje o %n blokov not accepted @@ -2302,7 +2310,7 @@ Adresa: %4 Immature (%1 confirmations, will be available after %2) - + Nezrelé (%1 potvrdení, bude k dispozícii po %2) Open for %n more block(s) @@ -2326,19 +2334,19 @@ Adresa: %4 Offline - + Offline Unconfirmed - + Nepotvrdené Confirming (%1 of %2 recommended confirmations) - + Potvrdzuje sa ( %1 z %2 odporúčaných potvrdení) Conflicted - + V rozpore Received with @@ -2485,7 +2493,7 @@ Adresa: %4 The transaction history was successfully saved to %1. - + História transakciá bola úspešne uložená do %1. Comma separated file (*.csv) @@ -2566,11 +2574,11 @@ Adresa: %4 There was an error trying to save the wallet data to %1. - + Vyskytla sa chyba pri pokuse o uloženie dát peňaženky do %1. The wallet data was successfully saved to %1. - + Dáta peňaženky boli úspešne uložené do %1. Backup Successful @@ -2617,7 +2625,7 @@ Adresa: %4 Connect to a node to retrieve peer addresses, and disconnect - + Pripojiť sa k nóde, získať adresy ďaľších počítačov v sieti a odpojit sa. Specify your own public address @@ -2633,7 +2641,7 @@ Adresa: %4 An error occurred while setting up the RPC port %u for listening on IPv4: %s - + Vyskytla sa chyba pri nastavovaní RPC portu %u pre počúvanie na IPv4: %s Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332) @@ -2645,7 +2653,7 @@ Adresa: %4 Bitcoin Core RPC client version - + Verzia RPC klienta Jadra Bitcoin Run in the background as a daemon and accept commands @@ -2657,7 +2665,7 @@ Adresa: %4 Accept connections from outside (default: 1 if no -proxy or -connect) - + Prijať spojenia zvonku (predvolené: 1 ak žiadne -proxy alebo -connect) %s, you must set a rpcpassword in the configuration file: @@ -2679,11 +2687,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s - + Vyskytla sa chyba pri nastavovaní RPC portu %u pre počúvanie na IPv6, vraciam sa späť ku IPv4: %s Bind to given address and always listen on it. Use [host]:port notation for IPv6 - + Spojiť s danou adresou a vždy na nej počúvať. Použite zápis [host]:port pre IPv6 Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15) @@ -2691,7 +2699,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development. - + Vstúpiť do regresného testovacieho módu, ktorý používa špeciálnu reťaz v ktorej môžu byť bloky v okamihu vyriešené. Pre účely regresného testovania a vývoja aplikácie. Enter regression test mode, which uses a special chain in which blocks can be solved instantly. @@ -2711,7 +2719,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - + Vykonaj príkaz keď sa zmení transakcia peňaženky (%s v príkaze je nahradená TxID) Fees smaller than this are considered zero fee (for transaction creation) (default: @@ -2767,7 +2775,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - + Varovanie: chyba pri čítaní wallet.dad! Všetky kľúče sú čitateľné ale transakčné dáta alebo záznamy v adresári môžu byť nesprávne. Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. @@ -2775,11 +2783,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. (default: 1) - + (predvolené: 1) (default: wallet.dat) - + (predvolené: wallet.dat) <category> can be: @@ -2787,7 +2795,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Attempt to recover private keys from a corrupt wallet.dat - + Pokus zachrániť súkromné kľúče z poškodeného wallet.dat Bitcoin Core Daemon @@ -2807,7 +2815,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connect through SOCKS proxy - + Pripojiť cez SOCKS proxy Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) @@ -2815,7 +2823,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + Možnosti pripojenia: Corrupted block database detected @@ -2823,7 +2831,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Debugging/Testing options: - + Možnosti ladenia/testovania: Disable safemode, override a real safe mode event (default: 0) @@ -2831,7 +2839,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Discover own IP address (default: 1 when listening and no -externalip) - + Zisti vlastnú IP adresu (predvolené: 1 pri počúvaní/listening a žiadnej -externalip) Do not load the wallet and disable wallet RPC calls @@ -2847,7 +2855,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error initializing wallet database environment %s! - + Chyba spustenia databázového prostredia peňaženky %s! Error loading block database @@ -2871,7 +2879,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Failed to listen on any port. Use -listen=0 if you want this. - + Chyba počúvania na ktoromkoľvek porte. Použi -listen=0 ak toto chcete. Failed to read block info @@ -2883,11 +2891,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Failed to sync block index - + Zlyhalo synchronizovanie zoznamu blokov Failed to write block index - + Zlyhalo zapisovanie do zoznamu blokov Failed to write block info @@ -2907,11 +2915,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Failed to write transaction index - + Zlyhal zápis zoznamu transakcií Failed to write undo data - + Zlyhalo zapisovanie Fee per kB to add to transactions you send @@ -2923,7 +2931,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Find peers using DNS lookup (default: 1 unless -connect) - + Nájsť počítače v bitcoin sieti použitím DNS vyhľadávania (predvolené: 1 okrem -connect) Force safe mode (default: 0) @@ -2931,11 +2939,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Generate coins (default: 0) - + Vytvárať mince (predvolené: 0) How many blocks to check at startup (default: 288, 0 = all) - + Koľko blokov skontrolovať pri spustení (predvolené: 288, 0 = všetky) If <category> is not supplied, output all debugging information. @@ -2943,19 +2951,19 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Importing... - + Prebieha import ... Incorrect or no genesis block found. Wrong datadir for network? - + Nesprávny alebo žiadny genesis blok nájdený. Nesprávny dátový priečinok alebo sieť? Invalid -onion address: '%s' - + Neplatná -onion adresa: '%s' Not enough file descriptors available. - + Nedostatok kľúčových slov súboru. Prepend debug output with timestamp (default: 1) @@ -2963,15 +2971,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. RPC client options: - + Možnosti klienta RPC baník pyčo: Rebuild block chain index from current blk000??.dat files - + Znovu vytvoriť zoznam blokov zo súčasných blk000??.dat súborov Select SOCKS version for -proxy (4 or 5, default: 5) - + Zvoľte SOCKS verziu -proxy (4 alebo 5, predvolené 5) Set database cache size in megabytes (%d to %d, default: %d) @@ -2979,15 +2987,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set maximum block size in bytes (default: %d) - + Nastaviť najväčšiu veľkosť bloku v bytoch (predvolené: %d) Set the number of threads to service RPC calls (default: 4) - + Nastaviť množstvo vlákien na obsluhu RPC volaní (predvolené: 4) Specify wallet file (within data directory) - + Označ súbor peňaženky (v priečinku s dátami) Spend unconfirmed change when sending transactions (default: 1) @@ -2999,7 +3007,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Usage (deprecated, use bitcoin-cli): - + Použitie (neodporúča sa, použite bitcoin-cli): Verifying blocks... @@ -3011,11 +3019,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Wait for RPC server to start - + Čakanie na štart RPC servra Wallet %s resides outside data directory %s - + Peňaženka %s sa nachádza mimo dátového priečinka %s Wallet options: @@ -3027,7 +3035,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. You need to rebuild the database using -reindex to change -txindex - + Potrebujete prebudovať databázu použitím -reindex zmeniť -txindex Imports blocks from external blk000??.dat file @@ -3035,7 +3043,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - + Neviem uzamknúť data adresár %s. Jadro Bitcoin je pravdepodobne už spustené. Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) @@ -3055,11 +3063,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid amount for -minrelaytxfee=<amount>: '%s' - + Neplatná suma pre -minrelaytxfee=<amount>: '%s' Invalid amount for -mintxfee=<amount>: '%s' - + Neplatná suma pre -mintxfee=<amount>: '%s' Limit size of signature cache to <n> entries (default: 50000) @@ -3075,7 +3083,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) - + Maximálna veľkosť prijímacieho zásobníka pre jedno spojenie, <n>*1000 bytov (predvolené: 5000) Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) @@ -3087,7 +3095,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Only connect to nodes in network <net> (IPv4, IPv6 or Tor) - + Pripájať sa len k nódam v sieti <net> (IPv4, IPv6 alebo Tor) Print block on startup, if found in block index @@ -3103,11 +3111,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. RPC server options: - + Možnosti servra RPC: Randomly drop 1 of every <n> network messages - + Náhodne zahadzuj 1 z každých <n> sieťových správ Randomly fuzz 1 of every <n> network messages @@ -3115,7 +3123,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Run a thread to flush wallet periodically (default: 1) - + Mať spustené vlákno pravidelného čístenia peňaženky (predvolené: 1) SSL options: (see the Bitcoin Wiki for SSL setup instructions) @@ -3123,7 +3131,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Send command to Bitcoin Core - + Poslať príkaz Jadru Bitcoin Send trace/debug info to console instead of debug.log file @@ -3131,23 +3139,23 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set minimum block size in bytes (default: 0) - + Nastaviť minimálnu veľkosť bloku v bytoch (predvolené: 0) Sets the DB_PRIVATE flag in the wallet db environment (default: 1) - + Nastaví DB_PRIVATE možnosť v db prostredí peňaženky (prednastavené: 1) Show all debugging options (usage: --help -help-debug) - + Zobraziť všetky možnosti ladenia (použitie: --help --help-debug) Show benchmark information (default: 0) - + Zobraziť porovnávacie informácie (prednastavené: 0) Shrink debug.log file on client startup (default: 1 when no -debug) - + Zmenšiť debug.log pri spustení klienta (predvolené: 1 ak bez -debug) Signing transaction failed @@ -3159,7 +3167,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Start Bitcoin Core Daemon - + Štart služby Jadro Bitcoin System error: @@ -3171,7 +3179,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Transaction amounts must be positive - + Hodnoty transakcie musia byť väčšie ako nula (pozitívne) Transaction too large @@ -3203,7 +3211,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. on startup - + pri štarte version @@ -3259,7 +3267,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Unable to bind to %s on this computer (bind returned error %d, %s) - + Nepodarilo sa spojiť s %s na tomto počítači (bind vrátil chybu %d, %s) Allow DNS lookups for -addnode, -seednode and -connect @@ -3291,19 +3299,19 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Unknown network specified in -onlynet: '%s' - + Neznáma sieť upresnená v -onlynet: '%s' Unknown -socks proxy version requested: %i - + Neznáma verzia -socks proxy požadovaná: %i Cannot resolve -bind address: '%s' - + Nemožno rozriešiť -bind adress: '%s' Cannot resolve -externalip address: '%s' - + Nemožno rozriešiť -externalip address: '%s' Invalid amount for -paytxfee=<amount>: '%s' diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index b966842d85..1a46c6ae6c 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1042,6 +1042,14 @@ Naslov: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1344,7 +1352,7 @@ Naslov: %4 Napaka: Neveljavna kombinacija -regtest and -testnet - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts index 5d9e7b7168..65e37ff903 100644 --- a/src/qt/locale/bitcoin_sq.ts +++ b/src/qt/locale/bitcoin_sq.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts index 6549c53542..901eb59394 100644 --- a/src/qt/locale/bitcoin_sr.ts +++ b/src/qt/locale/bitcoin_sr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index 27a8c4d0e3..e98048e925 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1048,6 +1048,14 @@ Adress: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Proxyns IP-adress (t.ex. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Tredjeparts URL:er (t.ex. en block utforskare) som finns i transaktionstabben som ett menyval i sammanhanget. %s i URL:en ersätts med tansaktionshashen. Flera URL:er är separerade med vertikala streck |. + + + Third party transaction URLs + Tredjeparts transaktions-URL:er + Active command-line options that override above options: Aktiva kommandoradsalternativ som överrider alternativen ovan: @@ -1350,8 +1358,8 @@ Adress: %4 Fel: Felaktig kombination av -regtest och -testnet. - Bitcoin Core did't yet exit safely... - Bitcoin Core avslutades säkert... + Bitcoin Core didn't yet exit safely... + Bitcoin Core avslutades inte ännu säkert... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index a26a128d93..96c49b12d0 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index 07d6e68f17..15ec92f982 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Adres: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) Vekil sunucusunun IP adresi (mesela IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + Muameleler sekmesinde bağlam menüsü unsurları olarak görünen üçüncü taraf bağlantıları (mesela bir blok tarayıcısı). URL'deki %s, muamele hash değeri ile değiştirilecektir. Birden çok bağlantılar düşey çubuklar | ile ayrılacaktır. + + + Third party transaction URLs + Üçüncü taraf muamele URL'leri + Active command-line options that override above options: Yukarıdaki seçeneklerin yerine geçen faal komut satırı seçenekleri: @@ -1349,7 +1357,7 @@ Adres: %4 Hata: -regtest ve -testnet'in geçersiz kombinasyonu. - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... Bitcoin Çekirdeği henüz güvenli bir şekilde çıkış yapmamıştır... diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index d78775319f..1e739395a2 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1047,6 +1047,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1349,7 +1357,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts index 45b46e2689..d9634f63e3 100644 --- a/src/qt/locale/bitcoin_ur_PK.ts +++ b/src/qt/locale/bitcoin_ur_PK.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts index e4ce310e20..6ba4f6fa1b 100644 --- a/src/qt/locale/bitcoin_uz@Cyrl.ts +++ b/src/qt/locale/bitcoin_uz@Cyrl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts index 88e37b5ea2..0f9fc4f0f1 100644 --- a/src/qt/locale/bitcoin_vi.ts +++ b/src/qt/locale/bitcoin_vi.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts index 743e7119d1..2102729523 100644 --- a/src/qt/locale/bitcoin_vi_VN.ts +++ b/src/qt/locale/bitcoin_vi_VN.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index a8859892d6..ea98c4e4b1 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1048,6 +1048,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) 代理的 IP 地址 (例如 IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: 有效的命令行参数覆盖上述选项: @@ -1350,7 +1358,7 @@ Address: %4 错误:无效的 -regtest 与 -testnet 结合体。 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts index cf729a3f92..835d0134d6 100644 --- a/src/qt/locale/bitcoin_zh_HK.ts +++ b/src/qt/locale/bitcoin_zh_HK.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1038,6 +1038,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + + + + Third party transaction URLs + + Active command-line options that override above options: @@ -1340,7 +1348,7 @@ Address: %4 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index 4f7561ab9e..fccdf48abd 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -1049,6 +1049,14 @@ Address: %4 IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) 代理伺服器的網際網路位址(像是 IPv4 的 127.0.0.1 或 IPv6 的 ::1) + + Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. + 在交易頁籤的情境選單出現的第三方(比如說區塊探索網站)網址連結。網址中的 %s 會被取代為交易的雜湊值。可以用直線符號 | 來分隔多個連結。 + + + Third party transaction URLs + 交易的第三方網址連結 + Active command-line options that override above options: 從命令列取代掉以上設定的選項有: @@ -1351,7 +1359,7 @@ Address: %4 錯誤: -regtest 和 -testnet 的使用組合無效。 - Bitcoin Core did't yet exit safely... + Bitcoin Core didn't yet exit safely... 位元幣核心還沒有安全地結束... From deb3572ab160221124dfa3e9c5c4e493529f59e4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 17 Feb 2014 17:35:40 +0100 Subject: [PATCH 053/336] Add -rpcbind option to allow binding RPC port on a specific interface Add -rpcbind command option to specify binding RPC service on one or multiple specific interfaces. Functionality if -rpcbind is not specified remains the same as before: - If no -rpcallowip specified, bind on localhost - If no -rpcbind specified, bind on any interface Implements part of #3111. --- src/init.cpp | 3 +- src/rpcserver.cpp | 95 ++++++++++++++++++++++++++++++----------------- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 7007707855..7664988762 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -304,10 +304,11 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += "\n" + _("RPC server options:") + "\n"; strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; + strUsage += " -rpcbind= " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n"; strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 8332 or testnet: 18332)") + "\n"; - strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address") + "\n"; + strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address. This option can be specified multiple times") + "\n"; strUsage += " -rpcthreads= " + _("Set the number of threads to service RPC calls (default: 4)") + "\n"; strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d4a229b092..2534a9dcf4 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -508,6 +508,14 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptorimpl(), strCiphers.c_str()); } - // Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets - const bool loopback = !mapArgs.count("-rpcallowip"); - asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); - ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort())); - boost::system::error_code v6_only_error; + std::vector vEndpoints; + bool bBindAny = false; + int defaultPort = GetArg("-rpcport", Params().RPCPort()); + if (!mapArgs.count("-rpcallowip")) // Default to loopback if not allowing external IPs + { + vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v6::loopback(), defaultPort)); + vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v4::loopback(), defaultPort)); + if (mapArgs.count("-rpcbind")) + { + LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n"); + } + } else if (mapArgs.count("-rpcbind")) // Specific bind address + { + BOOST_FOREACH(const std::string &addr, mapMultiArgs["-rpcbind"]) + { + try { + vEndpoints.push_back(ParseEndpoint(addr, defaultPort)); + } + catch(boost::system::system_error &e) + { + uiInterface.ThreadSafeMessageBox( + strprintf(_("Could not parse -rpcbind value %s as network address"), addr), + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return; + } + } + } else { // No specific bind address specified, bind to any + vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v6::any(), defaultPort)); + vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v4::any(), defaultPort)); + // Prefer making the socket dual IPv6/IPv4 instead of binding + // to both addresses seperately. + bBindAny = true; + } bool fListening = false; std::string strerr; - try + BOOST_FOREACH(const ip::tcp::endpoint &endpoint, vEndpoints) { + asio::ip::address bindAddress = endpoint.address(); + LogPrintf("Binding RPC on address %s port %i (IPv4+IPv6 bind any: %i)\n", bindAddress.to_string(), endpoint.port(), bBindAny); + boost::system::error_code v6_only_error; boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); rpc_acceptors.push_back(acceptor); - acceptor->open(endpoint.protocol()); - acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - // Try making the socket dual IPv6/IPv4 (if listening on the "any" address) - acceptor->set_option(boost::asio::ip::v6_only(loopback), v6_only_error); - - acceptor->bind(endpoint); - acceptor->listen(socket_base::max_connections); - - RPCListen(acceptor, *rpc_ssl_context, fUseSSL); - - fListening = true; - } - catch(boost::system::system_error &e) - { - strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s"), endpoint.port(), e.what()); - } - try { - // If dual IPv6/IPv4 failed (or we're opening loopback interfaces only), open IPv4 separately - if (!fListening || loopback || v6_only_error) - { - bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any(); - endpoint.address(bindAddress); - - boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); - rpc_acceptors.push_back(acceptor); + try { acceptor->open(endpoint.protocol()); acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + + // Try making the socket dual IPv6/IPv4 when listening on the IPv6 "any" address + acceptor->set_option(boost::asio::ip::v6_only( + !bBindAny || bindAddress != asio::ip::address_v6::any()), v6_only_error); + acceptor->bind(endpoint); acceptor->listen(socket_base::max_connections); RPCListen(acceptor, *rpc_ssl_context, fUseSSL); fListening = true; + // If dual IPv6/IPv4 bind succesful, skip binding to IPv4 separately + if(bBindAny && bindAddress == asio::ip::address_v6::any() && !v6_only_error) + break; + } + catch(boost::system::system_error &e) + { + LogPrintf("ERROR: Binding RPC on address %s port %i failed: %s\n", bindAddress.to_string(), endpoint.port(), e.what()); + strerr = strprintf(_("An error occurred while setting up the RPC address %s port %u for listening: %s"), bindAddress.to_string(), endpoint.port(), e.what()); } - } - catch(boost::system::system_error &e) - { - strerr = strprintf(_("An error occurred while setting up the RPC port %u for listening on IPv4: %s"), endpoint.port(), e.what()); } if (!fListening) { From f923c077547ceb8492e11001d571ba27145242ef Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 7 Apr 2014 16:22:59 +0200 Subject: [PATCH 054/336] Support IPv6 lookup in bitcoin-cli even when IPv6 only bound on localhost First query in the current way (intelligently determining which network has a non-localhost interface). If this does not succeed, try plain lookup. Needed for testing. Fixes #1827 by always allowing IPv6 to be used. --- src/rpcprotocol.h | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index 8b3df19621..11bdd171d9 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -103,11 +103,27 @@ public: } bool connect(const std::string& server, const std::string& port) { - boost::asio::ip::tcp::resolver resolver(stream.get_io_service()); - boost::asio::ip::tcp::resolver::query query(server.c_str(), port.c_str()); - boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); - boost::asio::ip::tcp::resolver::iterator end; + using namespace boost::asio::ip; + tcp::resolver resolver(stream.get_io_service()); + tcp::resolver::iterator endpoint_iterator; +#if BOOST_VERSION >= 104300 + try { +#endif + // The default query (flags address_configured) tries IPv6 if + // non-localhost IPv6 configured, and IPv4 if non-localhost IPv4 + // configured. + tcp::resolver::query query(server.c_str(), port.c_str()); + endpoint_iterator = resolver.resolve(query); +#if BOOST_VERSION >= 104300 + } catch(boost::system::system_error &e) + { + // If we at first don't succeed, try blanket lookup (IPv4+IPv6 independent of configured interfaces) + tcp::resolver::query query(server.c_str(), port.c_str(), resolver_query_base::flags()); + endpoint_iterator = resolver.resolve(query); + } +#endif boost::system::error_code error = boost::asio::error::host_not_found; + tcp::resolver::iterator end; while (error && endpoint_iterator != end) { stream.lowest_layer().close(); From b5ad5e783d6f636d5ca5703919d05fd0119a34fc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 7 Apr 2014 17:29:36 +0200 Subject: [PATCH 055/336] Add Python test for -rpcbind and -rpcallowip Add a new test, `rpcbind_test.py`, that extensively tests the new `-rpcbind` functionality. --- qa/rpc-tests/netutil.py | 134 ++++++++++++++++++++++++++++++ qa/rpc-tests/rpcbind_test.py | 152 +++++++++++++++++++++++++++++++++++ qa/rpc-tests/util.py | 32 +++++++- 3 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 qa/rpc-tests/netutil.py create mode 100755 qa/rpc-tests/rpcbind_test.py diff --git a/qa/rpc-tests/netutil.py b/qa/rpc-tests/netutil.py new file mode 100644 index 0000000000..9bea2e355e --- /dev/null +++ b/qa/rpc-tests/netutil.py @@ -0,0 +1,134 @@ +# Linux network utilities +import sys +import socket +import fcntl +import struct +import array +import os +import binascii + +# Roughly based on http://voorloopnul.com/blog/a-python-netstat-in-less-than-100-lines-of-code/ by Ricardo Pascal +STATE_ESTABLISHED = '01' +STATE_SYN_SENT = '02' +STATE_SYN_RECV = '03' +STATE_FIN_WAIT1 = '04' +STATE_FIN_WAIT2 = '05' +STATE_TIME_WAIT = '06' +STATE_CLOSE = '07' +STATE_CLOSE_WAIT = '08' +STATE_LAST_ACK = '09' +STATE_LISTEN = '0A' +STATE_CLOSING = '0B' + +def get_socket_inodes(pid): + ''' + Get list of socket inodes for process pid. + ''' + base = '/proc/%i/fd' % pid + inodes = [] + for item in os.listdir(base): + target = os.readlink(os.path.join(base, item)) + if target.startswith('socket:'): + inodes.append(int(target[8:-1])) + return inodes + +def _remove_empty(array): + return [x for x in array if x !=''] + +def _convert_ip_port(array): + host,port = array.split(':') + # convert host from mangled-per-four-bytes form as used by kernel + host = binascii.unhexlify(host) + host_out = '' + for x in range(0, len(host)/4): + (val,) = struct.unpack('=I', host[x*4:(x+1)*4]) + host_out += '%08x' % val + + return host_out,int(port,16) + +def netstat(typ='tcp'): + ''' + Function to return a list with status of tcp connections at linux systems + To get pid of all network process running on system, you must run this script + as superuser + ''' + with open('/proc/net/'+typ,'r') as f: + content = f.readlines() + content.pop(0) + result = [] + for line in content: + line_array = _remove_empty(line.split(' ')) # Split lines and remove empty spaces. + tcp_id = line_array[0] + l_addr = _convert_ip_port(line_array[1]) + r_addr = _convert_ip_port(line_array[2]) + state = line_array[3] + inode = int(line_array[9]) # Need the inode to match with process pid. + nline = [tcp_id, l_addr, r_addr, state, inode] + result.append(nline) + return result + +def get_bind_addrs(pid): + ''' + Get bind addresses as (host,port) tuples for process pid. + ''' + inodes = get_socket_inodes(pid) + bind_addrs = [] + for conn in netstat('tcp') + netstat('tcp6'): + if conn[3] == STATE_LISTEN and conn[4] in inodes: + bind_addrs.append(conn[1]) + return bind_addrs + +# from: http://code.activestate.com/recipes/439093/ +def all_interfaces(): + ''' + Return all interfaces that are up + ''' + is_64bits = sys.maxsize > 2**32 + struct_size = 40 if is_64bits else 32 + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + max_possible = 8 # initial value + while True: + bytes = max_possible * struct_size + names = array.array('B', '\0' * bytes) + outbytes = struct.unpack('iL', fcntl.ioctl( + s.fileno(), + 0x8912, # SIOCGIFCONF + struct.pack('iL', bytes, names.buffer_info()[0]) + ))[0] + if outbytes == bytes: + max_possible *= 2 + else: + break + namestr = names.tostring() + return [(namestr[i:i+16].split('\0', 1)[0], + socket.inet_ntoa(namestr[i+20:i+24])) + for i in range(0, outbytes, struct_size)] + +def addr_to_hex(addr): + ''' + Convert string IPv4 or IPv6 address to binary address as returned by + get_bind_addrs. + Very naive implementation that certainly doesn't work for all IPv6 variants. + ''' + if '.' in addr: # IPv4 + addr = [int(x) for x in addr.split('.')] + elif ':' in addr: # IPv6 + sub = [[], []] # prefix, suffix + x = 0 + addr = addr.split(':') + for i,comp in enumerate(addr): + if comp == '': + if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end + continue + x += 1 # :: skips to suffix + assert(x < 2) + else: # two bytes per component + val = int(comp, 16) + sub[x].append(val >> 8) + sub[x].append(val & 0xff) + nullbytes = 16 - len(sub[0]) - len(sub[1]) + assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0)) + addr = sub[0] + ([0] * nullbytes) + sub[1] + else: + raise ValueError('Could not parse address %s' % addr) + return binascii.hexlify(bytearray(addr)) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py new file mode 100755 index 0000000000..a31f8d98ef --- /dev/null +++ b/qa/rpc-tests/rpcbind_test.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# Test for -rpcbind, as well as -rpcallowip and -rpcconnect + +# Add python-bitcoinrpc to module search path: +import os +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc")) + +import json +import shutil +import subprocess +import tempfile +import traceback + +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * +from netutil import * + +def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected): + ''' + Start a node with requested rpcallowip and rpcbind parameters, + then try to connect, and check if the set of bound addresses + matches the expected set. + ''' + expected = [(addr_to_hex(addr), port) for (addr, port) in expected] + base_args = ['-disablewallet', '-nolisten'] + if allow_ips: + base_args += ['-rpcallowip=' + x for x in allow_ips] + binds = ['-rpcbind='+addr for addr in addresses] + nodes = start_nodes(1, tmpdir, [base_args + binds], connect_to) + try: + pid = bitcoind_processes[0].pid + assert_equal(set(get_bind_addrs(pid)), set(expected)) + finally: + stop_nodes(nodes) + wait_bitcoinds() + +def run_allowip_test(tmpdir, allow_ips, rpchost): + ''' + Start a node with rpcwallow IP, and request getinfo + at a non-localhost IP. + ''' + base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] + nodes = start_nodes(1, tmpdir, [base_args]) + try: + # connect to node through non-loopback interface + url = "http://rt:rt@%s:%d" % (rpchost, START_RPC_PORT,) + node = AuthServiceProxy(url) + node.getinfo() + finally: + node = None # make sure connection will be garbage collected and closed + stop_nodes(nodes) + wait_bitcoinds() + + +def run_test(tmpdir): + assert(sys.platform == 'linux2') # due to OS-specific network stats queries, this test works only on Linux + # find the first non-loopback interface for testing + non_loopback_ip = None + for name,ip in all_interfaces(): + if ip != '127.0.0.1': + non_loopback_ip = ip + break + if non_loopback_ip is None: + assert(not 'This test requires at least one non-loopback IPv4 interface') + print("Using interface %s for testing" % non_loopback_ip) + + # check default without rpcallowip (IPv4 and IPv6 localhost) + run_bind_test(tmpdir, None, '127.0.0.1', [], + [('127.0.0.1', 11100), ('::1', 11100)]) + # check default with rpcallowip (IPv6 any) + run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [], + [('::0', 11100)]) + # check only IPv4 localhost (explicit) + run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], + [('127.0.0.1', START_RPC_PORT)]) + # check only IPv4 localhost (explicit) with alternative port + run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], + [('127.0.0.1', 32171)]) + # check only IPv4 localhost (explicit) with multiple alternative ports on same host + run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], + [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) + # check only IPv6 localhost (explicit) + run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'], + [('::1', 11100)]) + # check both IPv4 and IPv6 localhost (explicit) + run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], + [('127.0.0.1', START_RPC_PORT), ('::1', START_RPC_PORT)]) + # check only non-loopback interface + run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip], + [(non_loopback_ip, START_RPC_PORT)]) + + # Check that with invalid rpcallowip, we are denied + run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip) + try: + run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip) + assert(not 'Connection not denied by rpcallowip as expected') + except ValueError: + pass + +def main(): + import optparse + + parser = optparse.OptionParser(usage="%prog [options]") + parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", + help="Leave bitcoinds and test.* datadir on exit or error") + parser.add_option("--srcdir", dest="srcdir", default="../../src", + help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") + parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), + help="Root directory for datadirs") + (options, args) = parser.parse_args() + + os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] + + check_json_precision() + + success = False + nodes = [] + try: + print("Initializing test directory "+options.tmpdir) + if not os.path.isdir(options.tmpdir): + os.makedirs(options.tmpdir) + initialize_chain(options.tmpdir) + + run_test(options.tmpdir) + + success = True + + except AssertionError as e: + print("Assertion failed: "+e.message) + except Exception as e: + print("Unexpected exception caught during testing: "+str(e)) + traceback.print_tb(sys.exc_info()[2]) + + if not options.nocleanup: + print("Cleaning up") + wait_bitcoinds() + shutil.rmtree(options.tmpdir) + + if success: + print("Tests successful") + sys.exit(0) + else: + print("Failed") + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index 1d0896a3fb..40f4a1458f 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -15,6 +15,7 @@ import json import shutil import subprocess import time +import re from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException from util import * @@ -112,20 +113,43 @@ def initialize_chain(test_dir): to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) -def start_nodes(num_nodes, dir): +def _rpchost_to_args(rpchost): + '''Convert optional IP:port spec to rpcconnect/rpcport args''' + if rpchost is None: + return [] + + match = re.match('(\[[0-9a-fA-f:]+\]|[^:]+)(?::([0-9]+))?$', rpchost) + if not match: + raise ValueError('Invalid RPC host spec ' + rpchost) + + rpcconnect = match.group(1) + rpcport = match.group(2) + + if rpcconnect.startswith('['): # remove IPv6 [...] wrapping + rpcconnect = rpcconnect[1:-1] + + rv = ['-rpcconnect=' + rpcconnect] + if rpcport: + rv += ['-rpcport=' + rpcport] + return rv + +def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): # Start bitcoinds, and wait for RPC interface to be up and running: devnull = open("/dev/null", "w+") for i in range(num_nodes): datadir = os.path.join(dir, "node"+str(i)) args = [ "bitcoind", "-datadir="+datadir ] + if extra_args is not None: + args += extra_args[i] bitcoind_processes.append(subprocess.Popen(args)) - subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir, - "-rpcwait", "getblockcount"], stdout=devnull) + subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] + + _rpchost_to_args(rpchost) + + ["-rpcwait", "getblockcount"], stdout=devnull) devnull.close() # Create&return JSON-RPC connections rpc_connections = [] for i in range(num_nodes): - url = "http://rt:rt@127.0.0.1:%d"%(START_RPC_PORT+i,) + url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', START_RPC_PORT+i,) rpc_connections.append(AuthServiceProxy(url)) return rpc_connections From 4b61a6a47895309ffb059f986a31c4931b8fe0b4 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Mon, 5 May 2014 20:08:13 +0200 Subject: [PATCH 056/336] switch from boost int types to --- src/json/json_spirit_reader_template.h | 12 +++--- src/json/json_spirit_value.h | 31 ++++++++------- src/rpcblockchain.cpp | 14 +++---- src/rpcclient.cpp | 52 +++++++++++++------------- src/rpcmining.cpp | 6 +-- src/rpcmisc.cpp | 6 +-- src/rpcnet.cpp | 16 ++++---- src/rpcrawtransaction.cpp | 12 +++--- src/rpcwallet.cpp | 12 +++--- 9 files changed, 80 insertions(+), 81 deletions(-) diff --git a/src/json/json_spirit_reader_template.h b/src/json/json_spirit_reader_template.h index 4dec00e6c9..46f5892f62 100644 --- a/src/json/json_spirit_reader_template.h +++ b/src/json/json_spirit_reader_template.h @@ -33,8 +33,8 @@ namespace json_spirit { - const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); - const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); + const spirit_namespace::int_parser < int64_t > int64_p = spirit_namespace::int_parser < int64_t >(); + const spirit_namespace::uint_parser< uint64_t > uint64_p = spirit_namespace::uint_parser< uint64_t >(); template< class Iter_type > bool is_eq( Iter_type first, Iter_type last, const char* c_str ) @@ -270,12 +270,12 @@ namespace json_spirit add_to_current( Value_type() ); } - void new_int( boost::int64_t i ) + void new_int( int64_t i ) { add_to_current( i ); } - void new_uint64( boost::uint64_t ui ) + void new_uint64( uint64_t ui ) { add_to_current( ui ); } @@ -425,8 +425,8 @@ namespace json_spirit typedef boost::function< void( Char_type ) > Char_action; typedef boost::function< void( Iter_type, Iter_type ) > Str_action; typedef boost::function< void( double ) > Real_action; - typedef boost::function< void( boost::int64_t ) > Int_action; - typedef boost::function< void( boost::uint64_t ) > Uint64_action; + typedef boost::function< void( int64_t ) > Int_action; + typedef boost::function< void( uint64_t ) > Uint64_action; Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); diff --git a/src/json/json_spirit_value.h b/src/json/json_spirit_value.h index 7e83a2a7e3..88c0e1f736 100644 --- a/src/json/json_spirit_value.h +++ b/src/json/json_spirit_value.h @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -45,8 +44,8 @@ namespace json_spirit Value_impl( const Array& value ); Value_impl( bool value ); Value_impl( int value ); - Value_impl( boost::int64_t value ); - Value_impl( boost::uint64_t value ); + Value_impl( int64_t value ); + Value_impl( uint64_t value ); Value_impl( double value ); Value_impl( const Value_impl& other ); @@ -65,8 +64,8 @@ namespace json_spirit const Array& get_array() const; bool get_bool() const; int get_int() const; - boost::int64_t get_int64() const; - boost::uint64_t get_uint64() const; + int64_t get_int64() const; + uint64_t get_uint64() const; double get_real() const; Object& get_obj(); @@ -83,7 +82,7 @@ namespace json_spirit typedef boost::variant< String_type, boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, - bool, boost::int64_t, double > Variant; + bool, int64_t, double > Variant; Value_type type_; Variant v_; @@ -258,13 +257,13 @@ namespace json_spirit template< class Config > Value_impl< Config >::Value_impl( int value ) : type_( int_type ) - , v_( static_cast< boost::int64_t >( value ) ) + , v_( static_cast< int64_t >( value ) ) , is_uint64_( false ) { } template< class Config > - Value_impl< Config >::Value_impl( boost::int64_t value ) + Value_impl< Config >::Value_impl( int64_t value ) : type_( int_type ) , v_( value ) , is_uint64_( false ) @@ -272,9 +271,9 @@ namespace json_spirit } template< class Config > - Value_impl< Config >::Value_impl( boost::uint64_t value ) + Value_impl< Config >::Value_impl( uint64_t value ) : type_( int_type ) - , v_( static_cast< boost::int64_t >( value ) ) + , v_( static_cast< int64_t >( value ) ) , is_uint64_( true ) { } @@ -390,19 +389,19 @@ namespace json_spirit } template< class Config > - boost::int64_t Value_impl< Config >::get_int64() const + int64_t Value_impl< Config >::get_int64() const { check_type( int_type ); - return boost::get< boost::int64_t >( v_ ); + return boost::get< int64_t >( v_ ); } template< class Config > - boost::uint64_t Value_impl< Config >::get_uint64() const + uint64_t Value_impl< Config >::get_uint64() const { check_type( int_type ); - return static_cast< boost::uint64_t >( get_int64() ); + return static_cast< uint64_t >( get_int64() ); } template< class Config > @@ -481,13 +480,13 @@ namespace json_spirit } template< class Value > - boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > ) + int64_t get_value( const Value& value, Type_to_type< int64_t > ) { return value.get_int64(); } template< class Value > - boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > ) + uint64_t get_value( const Value& value, Type_to_type< uint64_t > ) { return value.get_uint64(); } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 1ed8a8e866..0a0fff41d7 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -64,8 +64,8 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) BOOST_FOREACH(const CTransaction&tx, block.vtx) txs.push_back(tx.GetHash().GetHex()); result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime())); - result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce)); + result.push_back(Pair("time", (int64_t)block.GetBlockTime())); + result.push_back(Pair("nonce", (uint64_t)block.nNonce)); result.push_back(Pair("bits", HexBits(block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); @@ -175,7 +175,7 @@ Value getrawmempool(const Array& params, bool fHelp) Object info; info.push_back(Pair("size", (int)e.GetTxSize())); info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", (boost::int64_t)e.GetTime())); + info.push_back(Pair("time", (int64_t)e.GetTime())); info.push_back(Pair("height", (int)e.GetHeight())); info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); @@ -315,11 +315,11 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) CCoinsStats stats; if (pcoinsTip->GetStats(stats)) { - ret.push_back(Pair("height", (boost::int64_t)stats.nHeight)); + ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); - ret.push_back(Pair("transactions", (boost::int64_t)stats.nTransactions)); - ret.push_back(Pair("txouts", (boost::int64_t)stats.nTransactionOutputs)); - ret.push_back(Pair("bytes_serialized", (boost::int64_t)stats.nSerializedSize)); + ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); + ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); + ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); } diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 8620a87297..4f3c39ce9b 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -128,53 +128,53 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo(params[0]); if (strMethod == "setgenerate" && n > 0) ConvertTo(params[0]); - if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); - if (strMethod == "getnetworkhashps" && n > 0) ConvertTo(params[0]); - if (strMethod == "getnetworkhashps" && n > 1) ConvertTo(params[1]); + if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); + if (strMethod == "getnetworkhashps" && n > 0) ConvertTo(params[0]); + if (strMethod == "getnetworkhashps" && n > 1) ConvertTo(params[1]); if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "settxfee" && n > 0) ConvertTo(params[0]); - if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo(params[0]); + if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); + if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo(params[0]); if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); + if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); - if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); + if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); if (strMethod == "move" && n > 2) ConvertTo(params[2]); - if (strMethod == "move" && n > 3) ConvertTo(params[3]); + if (strMethod == "move" && n > 3) ConvertTo(params[3]); if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); - if (strMethod == "sendfrom" && n > 3) ConvertTo(params[3]); - if (strMethod == "listtransactions" && n > 1) ConvertTo(params[1]); - if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); - if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); - if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); + if (strMethod == "sendfrom" && n > 3) ConvertTo(params[3]); + if (strMethod == "listtransactions" && n > 1) ConvertTo(params[1]); + if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); + if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); + if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); if (strMethod == "getblocktemplate" && n > 0) ConvertTo(params[0]); - if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); + if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); if (strMethod == "sendmany" && n > 1) ConvertTo(params[1]); - if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); - if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); + if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); + if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); if (strMethod == "addmultisigaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "createmultisig" && n > 0) ConvertTo(params[0]); + if (strMethod == "createmultisig" && n > 0) ConvertTo(params[0]); if (strMethod == "createmultisig" && n > 1) ConvertTo(params[1]); - if (strMethod == "listunspent" && n > 0) ConvertTo(params[0]); - if (strMethod == "listunspent" && n > 1) ConvertTo(params[1]); + if (strMethod == "listunspent" && n > 0) ConvertTo(params[0]); + if (strMethod == "listunspent" && n > 1) ConvertTo(params[1]); if (strMethod == "listunspent" && n > 2) ConvertTo(params[2]); if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); - if (strMethod == "getrawtransaction" && n > 1) ConvertTo(params[1]); + if (strMethod == "getrawtransaction" && n > 1) ConvertTo(params[1]); if (strMethod == "createrawtransaction" && n > 0) ConvertTo(params[0]); if (strMethod == "createrawtransaction" && n > 1) ConvertTo(params[1]); if (strMethod == "signrawtransaction" && n > 1) ConvertTo(params[1], true); if (strMethod == "signrawtransaction" && n > 2) ConvertTo(params[2], true); if (strMethod == "sendrawtransaction" && n > 1) ConvertTo(params[1], true); - if (strMethod == "gettxout" && n > 1) ConvertTo(params[1]); + if (strMethod == "gettxout" && n > 1) ConvertTo(params[1]); if (strMethod == "gettxout" && n > 2) ConvertTo(params[2]); if (strMethod == "lockunspent" && n > 0) ConvertTo(params[0]); if (strMethod == "lockunspent" && n > 1) ConvertTo(params[1]); if (strMethod == "importprivkey" && n > 2) ConvertTo(params[2]); - if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); - if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); - if (strMethod == "keypoolrefill" && n > 0) ConvertTo(params[0]); + if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); + if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); + if (strMethod == "keypoolrefill" && n > 0) ConvertTo(params[0]); if (strMethod == "getrawmempool" && n > 0) ConvertTo(params[0]); return params; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index cb903b585a..23876c603d 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -88,7 +88,7 @@ Value GetNetworkHashPS(int lookup, int height) { uint256 workDiff = pb->nChainWork - pb0->nChainWork; int64_t timeDiff = maxTime - minTime; - return (boost::int64_t)(workDiff.getdouble() / timeDiff); + return (int64_t)(workDiff.getdouble() / timeDiff); } Value getnetworkhashps(const Array& params, bool fHelp) @@ -226,8 +226,8 @@ Value gethashespersec(const Array& params, bool fHelp) ); if (GetTimeMillis() - nHPSTimerStart > 8000) - return (boost::int64_t)0; - return (boost::int64_t)dHashesPerSec; + return (int64_t)0; + return (int64_t)dHashesPerSec; } #endif diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 2564a3f1a6..0dd98fd765 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -69,18 +69,18 @@ Value getinfo(const Array& params, bool fHelp) } #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); + obj.push_back(Pair("timeoffset", (int64_t)GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("testnet", TestNet())); #ifdef ENABLE_WALLET if (pwalletMain) { - obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); } if (pwalletMain && pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); #endif obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 573d6cd3f6..1dc70840ca 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -116,11 +116,11 @@ Value getpeerinfo(const Array& params, bool fHelp) if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%08x", stats.nServices))); - obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); - obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); - obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes)); - obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes)); - obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected)); + obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); + obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); + obj.push_back(Pair("bytessent", (int64_t)stats.nSendBytes)); + obj.push_back(Pair("bytesrecv", (int64_t)stats.nRecvBytes)); + obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); obj.push_back(Pair("pingtime", stats.dPingTime)); if (stats.dPingWait > 0.0) obj.push_back(Pair("pingwait", stats.dPingWait)); @@ -328,9 +328,9 @@ Value getnettotals(const Array& params, bool fHelp) ); Object obj; - obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv()))); - obj.push_back(Pair("totalbytessent", static_cast(CNode::GetTotalBytesSent()))); - obj.push_back(Pair("timemillis", static_cast(GetTimeMillis()))); + obj.push_back(Pair("totalbytesrecv", static_cast< uint64_t>(CNode::GetTotalBytesRecv()))); + obj.push_back(Pair("totalbytessent", static_cast(CNode::GetTotalBytesSent()))); + obj.push_back(Pair("timemillis", static_cast(GetTimeMillis()))); return obj; } diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 50734a5c11..dee7daeb2a 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -55,7 +55,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) { entry.push_back(Pair("txid", tx.GetHash().GetHex())); entry.push_back(Pair("version", tx.nVersion)); - entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime)); + entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); Array vin; BOOST_FOREACH(const CTxIn& txin, tx.vin) { @@ -65,13 +65,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) else { in.push_back(Pair("txid", txin.prevout.hash.GetHex())); - in.push_back(Pair("vout", (boost::int64_t)txin.prevout.n)); + in.push_back(Pair("vout", (int64_t)txin.prevout.n)); Object o; o.push_back(Pair("asm", txin.scriptSig.ToString())); o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); in.push_back(Pair("scriptSig", o)); } - in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence)); + in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); } entry.push_back(Pair("vin", vin)); @@ -81,7 +81,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) const CTxOut& txout = tx.vout[i]; Object out; out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - out.push_back(Pair("n", (boost::int64_t)i)); + out.push_back(Pair("n", (int64_t)i)); Object o; ScriptPubKeyToJSON(txout.scriptPubKey, o, true); out.push_back(Pair("scriptPubKey", o)); @@ -99,8 +99,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) if (chainActive.Contains(pindex)) { entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); - entry.push_back(Pair("time", (boost::int64_t)pindex->nTime)); - entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime)); + entry.push_back(Pair("time", (int64_t)pindex->nTime)); + entry.push_back(Pair("blocktime", (int64_t)pindex->nTime)); } else entry.push_back(Pair("confirmations", 0)); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 2479a1f87e..c61035ab35 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -49,7 +49,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); - entry.push_back(Pair("blocktime", (boost::int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); + entry.push_back(Pair("blocktime", (int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); } uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); @@ -57,8 +57,8 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); entry.push_back(Pair("walletconflicts", conflicts)); - entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime())); - entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived)); + entry.push_back(Pair("time", (int64_t)wtx.GetTxTime())); + entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) entry.push_back(Pair(item.first, item.second)); } @@ -1167,7 +1167,7 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Object entry; entry.push_back(Pair("account", acentry.strAccount)); entry.push_back(Pair("category", "move")); - entry.push_back(Pair("time", (boost::int64_t)acentry.nTime)); + entry.push_back(Pair("time", (int64_t)acentry.nTime)); entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit))); entry.push_back(Pair("otheraccount", acentry.strOtherAccount)); entry.push_back(Pair("comment", acentry.strComment)); @@ -1912,9 +1912,9 @@ Value getwalletinfo(const Array& params, bool fHelp) obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size())); - obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); if (pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime)); return obj; } From 3e74ac22d5298f3259115848db5ac96e00d74e4a Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Mon, 5 May 2014 21:15:33 +0200 Subject: [PATCH 057/336] json_spirit: #include --- src/json/json_spirit_value.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/json/json_spirit_value.h b/src/json/json_spirit_value.h index 88c0e1f736..13cc89210c 100644 --- a/src/json/json_spirit_value.h +++ b/src/json/json_spirit_value.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include From d56e30ca898469cf5988b0fc9847ec79b43be49c Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 6 May 2014 14:58:43 +0200 Subject: [PATCH 058/336] removed a few unnecessary casts --- src/rpcblockchain.cpp | 4 ++-- src/rpcmisc.cpp | 6 +++--- src/rpcnet.cpp | 18 +++++++++--------- src/rpcwallet.cpp | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 0a0fff41d7..a303b5d3ef 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -64,7 +64,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) BOOST_FOREACH(const CTransaction&tx, block.vtx) txs.push_back(tx.GetHash().GetHex()); result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", (int64_t)block.GetBlockTime())); + result.push_back(Pair("time", block.GetBlockTime())); result.push_back(Pair("nonce", (uint64_t)block.nNonce)); result.push_back(Pair("bits", HexBits(block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); @@ -175,7 +175,7 @@ Value getrawmempool(const Array& params, bool fHelp) Object info; info.push_back(Pair("size", (int)e.GetTxSize())); info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", (int64_t)e.GetTime())); + info.push_back(Pair("time", e.GetTime())); info.push_back(Pair("height", (int)e.GetHeight())); info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 0dd98fd765..27d6d61a36 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -69,18 +69,18 @@ Value getinfo(const Array& params, bool fHelp) } #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("timeoffset", (int64_t)GetTimeOffset())); + obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("testnet", TestNet())); #ifdef ENABLE_WALLET if (pwalletMain) { - obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); } if (pwalletMain && pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); #endif obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 1dc70840ca..024f6a09de 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -116,11 +116,11 @@ Value getpeerinfo(const Array& params, bool fHelp) if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%08x", stats.nServices))); - obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); - obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); - obj.push_back(Pair("bytessent", (int64_t)stats.nSendBytes)); - obj.push_back(Pair("bytesrecv", (int64_t)stats.nRecvBytes)); - obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); + obj.push_back(Pair("lastsend", stats.nLastSend)); + obj.push_back(Pair("lastrecv", stats.nLastRecv)); + obj.push_back(Pair("bytessent", stats.nSendBytes)); + obj.push_back(Pair("bytesrecv", stats.nRecvBytes)); + obj.push_back(Pair("conntime", stats.nTimeConnected)); obj.push_back(Pair("pingtime", stats.dPingTime)); if (stats.dPingWait > 0.0) obj.push_back(Pair("pingwait", stats.dPingWait)); @@ -328,9 +328,9 @@ Value getnettotals(const Array& params, bool fHelp) ); Object obj; - obj.push_back(Pair("totalbytesrecv", static_cast< uint64_t>(CNode::GetTotalBytesRecv()))); - obj.push_back(Pair("totalbytessent", static_cast(CNode::GetTotalBytesSent()))); - obj.push_back(Pair("timemillis", static_cast(GetTimeMillis()))); + obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("timemillis", GetTimeMillis())); return obj; } @@ -365,7 +365,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); - obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); + obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index c61035ab35..a8f267d7fc 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -57,7 +57,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); entry.push_back(Pair("walletconflicts", conflicts)); - entry.push_back(Pair("time", (int64_t)wtx.GetTxTime())); + entry.push_back(Pair("time", wtx.GetTxTime())); entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) entry.push_back(Pair(item.first, item.second)); @@ -1167,7 +1167,7 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Object entry; entry.push_back(Pair("account", acentry.strAccount)); entry.push_back(Pair("category", "move")); - entry.push_back(Pair("time", (int64_t)acentry.nTime)); + entry.push_back(Pair("time", acentry.nTime)); entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit))); entry.push_back(Pair("otheraccount", acentry.strOtherAccount)); entry.push_back(Pair("comment", acentry.strComment)); @@ -1912,9 +1912,9 @@ Value getwalletinfo(const Array& params, bool fHelp) obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("txcount", (int)pwalletMain->mapWallet.size())); - obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); if (pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime)); + obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); return obj; } From be54b87f22f10bf84bc25d9e29bf1eed596dc764 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 11:11:02 +0200 Subject: [PATCH 059/336] remove ParseString(...) which is never used --- src/util.cpp | 20 -------------------- src/util.h | 1 - 2 files changed, 21 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 00e29446d5..205af738d5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -303,26 +303,6 @@ int LogPrintStr(const std::string &str) return ret; } -void ParseString(const string& str, char c, vector& v) -{ - if (str.empty()) - return; - string::size_type i1 = 0; - string::size_type i2; - while (true) - { - i2 = str.find(c, i1); - if (i2 == str.npos) - { - v.push_back(str.substr(i1)); - return; - } - v.push_back(str.substr(i1, i2-i1)); - i1 = i2+1; - } -} - - string FormatMoney(int64_t n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want diff --git a/src/util.h b/src/util.h index 27a08716dd..52ca6e579b 100644 --- a/src/util.h +++ b/src/util.h @@ -153,7 +153,6 @@ static inline bool error(const char* format) void LogException(std::exception* pex, const char* pszThread); void PrintExceptionContinue(std::exception* pex, const char* pszThread); -void ParseString(const std::string& str, char c, std::vector& v); std::string FormatMoney(int64_t n, bool fPlus=false); bool ParseMoney(const std::string& str, int64_t& nRet); bool ParseMoney(const char* pszIn, int64_t& nRet); From 5248ff40997c64cc0fde7aaa67cf94dd38b14899 Mon Sep 17 00:00:00 2001 From: Stuart Cardall Date: Tue, 13 May 2014 10:15:00 +0000 Subject: [PATCH 060/336] SetupEnvironment() - clean commit --- src/bitcoin-cli.cpp | 2 ++ src/bitcoind.cpp | 2 ++ src/qt/bitcoin.cpp | 2 ++ src/util.cpp | 16 ++++++++++++++++ src/util.h | 1 + 5 files changed, 23 insertions(+) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index ca6950a162..ce9e7a4027 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -58,6 +58,8 @@ static bool AppInitRPC(int argc, char* argv[]) int main(int argc, char* argv[]) { + SetupEnvironment(); + try { if(!AppInitRPC(argc, argv)) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 17aa0c9d4b..78c8b2ba0e 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -172,6 +172,8 @@ bool AppInit(int argc, char* argv[]) int main(int argc, char* argv[]) { + SetupEnvironment(); + bool fRet = false; // Connect bitcoind signal handlers diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 31716ab825..45d7a52889 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -459,6 +459,8 @@ WId BitcoinApplication::getMainWinId() const #ifndef BITCOIN_QT_TEST int main(int argc, char *argv[]) { + SetupEnvironment(); + /// 1. Parse command-line options. These take precedence over anything else. // Command-line options take precedence: ParseParameters(argc, argv); diff --git a/src/util.cpp b/src/util.cpp index 00e29446d5..2e8500eeae 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1404,3 +1404,19 @@ bool ParseInt32(const std::string& str, int32_t *out) n <= std::numeric_limits::max(); } +void SetupEnvironment() +{ + #ifndef WIN32 + try + { + #if BOOST_FILESYSTEM_VERSION == 3 + boost::filesystem::path::codecvt(); // Raises runtime error if current locale is invalid + #else // boost filesystem v2 + std::locale(); // Raises runtime error if current locale is invalid + #endif + } catch(std::runtime_error &e) + { + setenv("LC_ALL", "C", 1); // Force C locale + } + #endif +} diff --git a/src/util.h b/src/util.h index 27a08716dd..b252295e76 100644 --- a/src/util.h +++ b/src/util.h @@ -106,6 +106,7 @@ extern volatile bool fReopenDebugLog; void RandAddSeed(); void RandAddSeedPerfmon(); +void SetupEnvironment(); /* Return true if log accepts specified category */ bool LogAcceptCategory(const char* category); From 122549f6dee5f4d4daf7091d6302c38ba13ffb01 Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 13 May 2014 16:38:36 -0400 Subject: [PATCH 061/336] Fix incorrect checkpoint data for testnet3 --- src/checkpoints.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 9ab8b68443..926949e06a 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -66,8 +66,8 @@ namespace Checkpoints ; static const CCheckpointData dataTestnet = { &mapCheckpointsTestnet, - 1338180505, - 16341, + 1337966069, + 1488, 300 }; From c6e36b0492dc870c49dafbfb7aa76e28202f8ef0 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 15 May 2014 03:27:35 -0300 Subject: [PATCH 062/336] Fix NameError in macdeploy script --- contrib/macdeploy/macdeployqtplus | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 5c310df1fc..599713fbbb 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -580,7 +580,7 @@ try: except RuntimeError as e: if verbose >= 1: sys.stderr.write("Error: %s\n" % str(e)) - sys.exit(ret) + sys.exit(1) # ------------------------------------------------ @@ -593,7 +593,7 @@ if config.plugins: except RuntimeError as e: if verbose >= 1: sys.stderr.write("Error: %s\n" % str(e)) - sys.exit(ret) + sys.exit(1) # ------------------------------------------------ From 0b78ba8ad69d55817f2b62c631a71b5ac32549f1 Mon Sep 17 00:00:00 2001 From: Huang Le <4tarhl@gmail.com> Date: Tue, 20 May 2014 01:22:33 +0800 Subject: [PATCH 063/336] Remove fDaemon flag checking on return from main(), which is useless and looks really strange. --- src/bitcoind.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 78c8b2ba0e..9b535c2e6b 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -174,15 +174,8 @@ int main(int argc, char* argv[]) { SetupEnvironment(); - bool fRet = false; - // Connect bitcoind signal handlers noui_connect(); - fRet = AppInit(argc, argv); - - if (fRet && fDaemon) - return 0; - - return (fRet ? 0 : 1); + return (AppInit(argc, argv) ? 0 : 1); } From 0a59723ff6218d545438e8e0f3083fc1d1b98bd4 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Tue, 20 May 2014 12:15:56 +0800 Subject: [PATCH 064/336] Remove extraneous c_str --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f7c53052e1..7bb3bdb70c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4445,7 +4445,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) uint256 hash = state.vBlocksToDownload.front(); vGetData.push_back(CInv(MSG_BLOCK, hash)); MarkBlockAsInFlight(pto->GetId(), hash); - LogPrint("net", "Requesting block %s from %s\n", hash.ToString().c_str(), state.name.c_str()); + LogPrint("net", "Requesting block %s from %s\n", hash.ToString(), state.name); if (vGetData.size() >= 1000) { pto->PushMessage("getdata", vGetData); From 0e31e5631c279353564f6407b8950b1224cf5b9f Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 20:48:34 +0200 Subject: [PATCH 065/336] remove CWallet::AddReserveKey which is never used --- src/wallet.cpp | 15 --------------- src/wallet.h | 1 - 2 files changed, 16 deletions(-) diff --git a/src/wallet.cpp b/src/wallet.cpp index fa7aecddb6..89604f96ac 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1671,21 +1671,6 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool) } } -int64_t CWallet::AddReserveKey(const CKeyPool& keypool) -{ - { - LOCK2(cs_main, cs_wallet); - CWalletDB walletdb(strWalletFile); - - int64_t nIndex = 1 + *(--setKeyPool.end()); - if (!walletdb.WritePool(nIndex, keypool)) - throw runtime_error("AddReserveKey() : writing added key failed"); - setKeyPool.insert(nIndex); - return nIndex; - } - return -1; -} - void CWallet::KeepKey(int64_t nIndex) { // Remove from key pool diff --git a/src/wallet.h b/src/wallet.h index b2c06d3f61..5e9af191cc 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -263,7 +263,6 @@ public: bool NewKeyPool(); bool TopUpKeyPool(unsigned int kpSize = 0); - int64_t AddReserveKey(const CKeyPool& keypool); void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool); void KeepKey(int64_t nIndex); void ReturnKey(int64_t nIndex); From f4057cb749f4c0d04bf936805ff8aa5678b9c6f2 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 20:58:25 +0200 Subject: [PATCH 066/336] remove CTransaction::IsNewerThan which is never used --- src/core.cpp | 29 ----------------------------- src/core.h | 1 - 2 files changed, 30 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 7651ce9957..aadcb44b98 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -77,35 +77,6 @@ uint256 CTransaction::GetHash() const return SerializeHash(*this); } -bool CTransaction::IsNewerThan(const CTransaction& old) const -{ - if (vin.size() != old.vin.size()) - return false; - for (unsigned int i = 0; i < vin.size(); i++) - if (vin[i].prevout != old.vin[i].prevout) - return false; - - bool fNewer = false; - unsigned int nLowest = std::numeric_limits::max(); - for (unsigned int i = 0; i < vin.size(); i++) - { - if (vin[i].nSequence != old.vin[i].nSequence) - { - if (vin[i].nSequence <= nLowest) - { - fNewer = false; - nLowest = vin[i].nSequence; - } - if (old.vin[i].nSequence < nLowest) - { - fNewer = true; - nLowest = old.vin[i].nSequence; - } - } - } - return fNewer; -} - int64_t CTransaction::GetValueOut() const { int64_t nValueOut = 0; diff --git a/src/core.h b/src/core.h index 5eb953610d..ba7f691119 100644 --- a/src/core.h +++ b/src/core.h @@ -219,7 +219,6 @@ public: } uint256 GetHash() const; - bool IsNewerThan(const CTransaction& old) const; // Return sum of txouts. int64_t GetValueOut() const; From 595f691d0acd871ecaba323d888a3632805c1828 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 21:00:16 +0200 Subject: [PATCH 067/336] remove LogException( ) which is never used --- src/util.cpp | 6 ------ src/util.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index aa3adf89ec..d99e6a7bfb 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -885,12 +885,6 @@ static std::string FormatException(std::exception* pex, const char* pszThread) "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); } -void LogException(std::exception* pex, const char* pszThread) -{ - std::string message = FormatException(pex, pszThread); - LogPrintf("\n%s", message); -} - void PrintExceptionContinue(std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); diff --git a/src/util.h b/src/util.h index 97185073e0..dc0c3a8cae 100644 --- a/src/util.h +++ b/src/util.h @@ -151,8 +151,6 @@ static inline bool error(const char* format) return false; } - -void LogException(std::exception* pex, const char* pszThread); void PrintExceptionContinue(std::exception* pex, const char* pszThread); std::string FormatMoney(int64_t n, bool fPlus=false); bool ParseMoney(const std::string& str, int64_t& nRet); From 5bd4adca716738a4de35aed2ccad874d3301fefc Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 21:02:17 +0200 Subject: [PATCH 068/336] remove LookupHostNumeric( ) which is never used --- src/netbase.cpp | 5 ----- src/netbase.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 82a681281d..c72d777e3d 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -123,11 +123,6 @@ bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nM return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup); } -bool LookupHostNumeric(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions) -{ - return LookupHost(pszName, vIP, nMaxSolutions, false); -} - bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions) { if (pszName[0] == 0) diff --git a/src/netbase.h b/src/netbase.h index 118f866d6c..35547b2660 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -173,7 +173,6 @@ bool IsProxy(const CNetAddr &addr); bool SetNameProxy(CService addrProxy, int nSocksVersion = 5); bool HaveNameProxy(); bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); -bool LookupHostNumeric(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); From 28b6c1def57360ca5a05745faafaec53910f5e88 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 21:37:47 +0200 Subject: [PATCH 069/336] remove GetMedianTime( ) which is never used --- src/main.cpp | 13 ------------- src/main.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c54fa65233..126b4ada51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2575,19 +2575,6 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns return (nFound >= nRequired); } -int64_t CBlockIndex::GetMedianTime() const -{ - AssertLockHeld(cs_main); - const CBlockIndex* pindex = this; - for (int i = 0; i < nMedianTimeSpan/2; i++) - { - if (!chainActive.Next(pindex)) - return GetBlockTime(); - pindex = chainActive.Next(pindex); - } - return pindex->GetMedianTimePast(); -} - void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd) { AssertLockHeld(cs_main); diff --git a/src/main.h b/src/main.h index f47c9ee825..25f70e7ad4 100644 --- a/src/main.h +++ b/src/main.h @@ -849,8 +849,6 @@ public: return pbegin[(pend - pbegin)/2]; } - int64_t GetMedianTime() const; - /** * Returns true if there are nRequired or more blocks of minVersion or above * in the last nToCheck blocks, starting at pstart and going backwards. From f40dbeedde3a6a73c13b0241258cf23248db1de1 Mon Sep 17 00:00:00 2001 From: Kamil Domanski Date: Tue, 13 May 2014 21:41:51 +0200 Subject: [PATCH 070/336] remove CPubKey::VerifyCompact( ) which is never used --- src/key.cpp | 15 --------------- src/key.h | 4 ---- 2 files changed, 19 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 2199996cf3..aa24f0a622 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -485,21 +485,6 @@ bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector& vchSig) const { - if (!IsValid()) - return false; - if (vchSig.size() != 65) - return false; - CECKey key; - if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4)) - return false; - CPubKey pubkeyRec; - key.GetPubKey(pubkeyRec, IsCompressed()); - if (*this != pubkeyRec) - return false; - return true; -} - bool CPubKey::IsFullyValid() const { if (!IsValid()) return false; diff --git a/src/key.h b/src/key.h index 37a06810b4..983775fd23 100644 --- a/src/key.h +++ b/src/key.h @@ -156,10 +156,6 @@ public: // If this public key is not fully valid, the return value will be false. bool Verify(const uint256 &hash, const std::vector& vchSig) const; - // Verify a compact signature (~65 bytes). - // See CKey::SignCompact. - bool VerifyCompact(const uint256 &hash, const std::vector& vchSig) const; - // Recover a public key from a compact signature. bool RecoverCompact(const uint256 &hash, const std::vector& vchSig); From d16f6f87e1c15bd686e0e74ddb671da95a916c6d Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 15 May 2014 03:22:42 -0300 Subject: [PATCH 071/336] Remove unused imports in macdeploy script --- contrib/macdeploy/README.md | 4 ---- contrib/macdeploy/macdeployqtplus | 11 ----------- 2 files changed, 15 deletions(-) diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md index 5f0611f20c..0aa57b4777 100644 --- a/contrib/macdeploy/README.md +++ b/contrib/macdeploy/README.md @@ -1,9 +1,5 @@ ### MacDeploy ### -You will need the appscript package for the fancy disk image creation to work: - - sudo easy_install appscript - For Snow Leopard (which uses [Python 2.6](http://www.python.org/download/releases/2.6/)), you will need the param_parser package: sudo easy_install argparse diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 5c310df1fc..4bfaadffd7 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -19,7 +19,6 @@ import subprocess, sys, re, os, shutil, stat, os.path from string import Template -from time import sleep from argparse import ArgumentParser # This is ported from the original macdeployqt with modifications @@ -488,16 +487,6 @@ if len(config.fancy) == 1: sys.stderr.write("Error: Could not import plistlib which is required for fancy disk images.\n") sys.exit(1) - if verbose >= 3: - print "Fancy: Importing appscript..." - try: - import appscript - except ImportError: - if verbose >= 1: - sys.stderr.write("Error: Could not import appscript which is required for fancy disk images.\n") - sys.stderr.write("Please install it e.g. with \"sudo easy_install appscript\".\n") - sys.exit(1) - p = config.fancy[0] if verbose >= 3: print "Fancy: Loading \"%s\"..." % p From d4e1c61212c3f28f80c7184aca81f5d118fad460 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 5 May 2014 21:06:14 +0200 Subject: [PATCH 072/336] add DEFAULT_UPNP constant in net - as this is a shared Core/GUI setting, this makes it easier to keep them in sync (also no new includes are needed) --- src/net.cpp | 4 +--- src/net.h | 6 ++++++ src/qt/optionsmodel.cpp | 6 +----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 6bde1e7999..7cabfef099 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1736,10 +1736,8 @@ void StartNode(boost::thread_group& threadGroup) else threadGroup.create_thread(boost::bind(&TraceThread, "dnsseed", &ThreadDNSAddressSeed)); -#ifdef USE_UPNP // Map ports with UPnP - MapPort(GetBoolArg("-upnp", USE_UPNP)); -#endif + MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); // Send and receive from sockets, accept connections threadGroup.create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); diff --git a/src/net.h b/src/net.h index 729b1bcd57..21b8dd242f 100644 --- a/src/net.h +++ b/src/net.h @@ -38,6 +38,12 @@ namespace boost { /** The maximum number of entries in an 'inv' protocol message */ static const unsigned int MAX_INV_SZ = 50000; +/** -upnp default */ +#ifdef USE_UPNP +static const bool DEFAULT_UPNP = USE_UPNP; +#else +static const bool DEFAULT_UPNP = false; +#endif inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index e87a1d97e7..051098315d 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -106,11 +106,7 @@ void OptionsModel::Init() // Network if (!settings.contains("fUseUPnP")) -#ifdef USE_UPNP - settings.setValue("fUseUPnP", true); -#else - settings.setValue("fUseUPnP", false); -#endif + settings.setValue("fUseUPnP", DEFAULT_UPNP); if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) addOverriddenOption("-upnp"); From 305ccaa27551efa33fcaf637e76310654738f428 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 20 May 2014 21:45:12 +0200 Subject: [PATCH 073/336] Add missing LOCK(cs_main) --- src/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index c54fa65233..a1fe6c07bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3488,7 +3488,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return true; } - State(pfrom->GetId())->nLastBlockProcess = GetTimeMicros(); + { + LOCK(cs_main); + State(pfrom->GetId())->nLastBlockProcess = GetTimeMicros(); + } From f701da8f707726e4097e17234cdd7b55255c1077 Mon Sep 17 00:00:00 2001 From: Kosta Zertsekel Date: Mon, 19 May 2014 13:42:57 +0300 Subject: [PATCH 074/336] Doc: Always use absolute paths --- doc/build-unix.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/build-unix.md b/doc/build-unix.md index ab5fbad521..1d75c206e5 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -2,6 +2,16 @@ UNIX BUILD NOTES ==================== Some notes on how to build Bitcoin in Unix. +Note +--------------------- +Always use absolute paths to configure and compile bitcoin and the dependencies, +for example, when specifying the the path of the dependency: + + ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX + +Here BDB_PREFIX must absolute path - it is defined using $(pwd) which ensures +the usage of the absolute path. + To Build --------------------- From 1a97b22b9c8ca6f1c3c7e3285e1b98893691d421 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 13 May 2014 19:23:22 -0400 Subject: [PATCH 075/336] gitian: Add OSX build descriptors Github-Pull: #4185 Rebased-By: Wladimir J. van der Laan Rebased-From: bb5da27, 2288206, 7fe8fe6, f76db78, ebcf375, fa1ed7c, 397e9b8 --- .../gitian-descriptors/gitian-osx-bitcoin.yml | 65 ++++++ .../gitian-descriptors/gitian-osx-depends.yml | 160 +++++++++++++++ .../gitian-descriptors/gitian-osx-native.yml | 179 ++++++++++++++++ contrib/gitian-descriptors/gitian-osx-qt.yml | 192 ++++++++++++++++++ doc/README_osx.txt | 71 +++++++ doc/release-process.md | 49 +++-- 6 files changed, 699 insertions(+), 17 deletions(-) create mode 100644 contrib/gitian-descriptors/gitian-osx-bitcoin.yml create mode 100644 contrib/gitian-descriptors/gitian-osx-depends.yml create mode 100644 contrib/gitian-descriptors/gitian-osx-native.yml create mode 100644 contrib/gitian-descriptors/gitian-osx-qt.yml create mode 100644 doc/README_osx.txt diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml new file mode 100644 index 0000000000..aea4b93a1f --- /dev/null +++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml @@ -0,0 +1,65 @@ +--- +name: "bitcoin" +suites: +- "precise" +architectures: +- "i386" +packages: +- "git-core" +- "automake" +- "faketime" +- "bsdmainutils" +- "pkg-config" +- "p7zip-full" + +reference_datetime: "2013-06-01 00:00:00" +remotes: +- "url": "https://github.com/bitcoin/bitcoin.git" + "dir": "bitcoin" +files: +- "osx-native-depends-r2.tar.gz" +- "osx-depends-r2.tar.gz" +- "osx-depends-qt-5.2.1-r2.tar.gz" +- "MacOSX10.6.pkg" + +script: | + + echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c + + HOST=x86_64-apple-darwin11 + PREFIX=`pwd`/osx-cross-depends/prefix + SDK=`pwd`/osx-cross-depends/SDKs/MacOSX10.6.sdk + NATIVEPREFIX=`pwd`/osx-cross-depends/native-prefix + export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + + export SOURCES_PATH=`pwd` + + mkdir osx-cross-depends + + cd osx-cross-depends + mkdir -p SDKs + 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + cd .. + + tar -C osx-cross-depends -xf osx-native-depends-r2.tar.gz + tar -C osx-cross-depends -xf osx-depends-r2.tar.gz + tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r2.tar.gz + export PATH=`pwd`/osx-cross-depends/native-prefix/bin:$PATH + + cd bitcoin + + export ZERO_AR_DATE=1 + export QT_RCC_TEST=1 + ./autogen.sh + ./configure --host=${HOST} --with-boost=${PREFIX} CC=clang CXX=clang++ OBJC=clang OBJCXX=clang++ CFLAGS="-target ${HOST} -mmacosx-version-min=10.6 --sysroot ${SDK} -msse2 -Qunused-arguments" CXXFLAGS="-target ${HOST} -mmacosx-version-min=10.6 --sysroot ${SDK} -msse2 -Qunused-arguments" LDFLAGS="-B${NATIVEPREFIX}/bin -L${PREFIX}/lib -L${SDK}/usr/lib/i686-apple-darwin10/4.2.1" CPPFLAGS="-I${NATIVEPREFIX}/lib/clang/3.2/include -I${PREFIX}/include" SSL_LIBS="-lz -lssl -lcrypto" --disable-tests -with-gui=qt5 PKG_CONFIG_LIBDIR="${PREFIX}/lib/pkgconfig" --disable-dependency-tracking --disable-maintainer-mode + make dist + mkdir -p distsrc + cd distsrc + tar --strip-components=1 -xf ../bitcoin-*.tar* + ./configure --host=${HOST} --with-boost=${PREFIX} CC=clang CXX=clang++ OBJC=clang OBJCXX=clang++ CFLAGS="-target ${HOST} -mmacosx-version-min=10.6 --sysroot ${SDK} -msse2 -Qunused-arguments" CXXFLAGS="-target ${HOST} -mmacosx-version-min=10.6 --sysroot ${SDK} -msse2 -Qunused-arguments" LDFLAGS="-B${NATIVEPREFIX}/bin -L${PREFIX}/lib -L${SDK}/usr/lib/i686-apple-darwin10/4.2.1" CPPFLAGS="-I${NATIVEPREFIX}/lib/clang/3.2/include -I${PREFIX}/include" SSL_LIBS="-lz -lssl -lcrypto" --disable-tests -with-gui=qt5 PKG_CONFIG_LIBDIR="${PREFIX}/lib/pkgconfig" --disable-dependency-tracking --disable-maintainer-mode + make $MAKEOPTS + export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + make deploy + dmg dmg Bitcoin-Qt.dmg $OUTDIR/Bitcoin-Qt.dmg diff --git a/contrib/gitian-descriptors/gitian-osx-depends.yml b/contrib/gitian-descriptors/gitian-osx-depends.yml new file mode 100644 index 0000000000..8e91a30ded --- /dev/null +++ b/contrib/gitian-descriptors/gitian-osx-depends.yml @@ -0,0 +1,160 @@ +--- +name: "osx-depends" +suites: +- "precise" +architectures: +- "i386" +packages: +- "git-core" +- "automake" +- "p7zip-full" + +reference_datetime: "2013-06-01 00:00:00" +remotes: [] +files: +- "boost_1_55_0.tar.bz2" +- "db-4.8.30.NC.tar.gz" +- "miniupnpc-1.9.tar.gz" +- "openssl-1.0.1g.tar.gz" +- "protobuf-2.5.0.tar.bz2" +- "qrencode-3.4.3.tar.bz2" +- "MacOSX10.6.pkg" +- "osx-native-depends-r2.tar.gz" + +script: | + + echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | sha256sum -c + echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c + echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c + echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c + echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c + echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c + echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c + + REVISION=r2 + export SOURCES_PATH=`pwd` + export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export PATH=$HOME:$PATH + export SOURCES_PATH=`pwd` + export ZERO_AR_DATE=1 + + mkdir -p osx-cross-depends/build + cd osx-cross-depends + + PREFIX=`pwd`/prefix + NATIVEPREFIX=`pwd`/native-prefix + BUILD_BASE=`pwd`/build + SDK=`pwd`/SDKs/MacOSX10.6.sdk + HOST=x86_64-apple-darwin11 + MIN_VERSION=10.6 + + INT_CFLAGS="-target ${HOST} -mmacosx-version-min=${MIN_VERSION} --sysroot ${SDK} -msse2 -Qunused-arguments" + INT_CXXFLAGS="${INT_CFLAGS}" + INT_LDFLAGS="-L${PREFIX}/lib -L${SDK}/usr/lib/i686-apple-darwin10/4.2.1" + INT_LDFLAGS_CLANG="-B${NATIVEPREFIX}/bin" + INT_CPPFLAGS="-I${PREFIX}/include" + INT_CC=clang + INT_CXX=clang++ + INT_OBJC=clang + INT_OBJCXX=clang++ + INT_AR=${HOST}-ar + INT_RANLIB=${HOST}-ranlib + INT_LIBTOOL=${HOST}-libtool + INT_INSTALL_NAME_TOOL=${HOST}-install_name_tool + + export PATH=${NATIVEPREFIX}/bin:${PATH} + + mkdir -p ${NATIVEPREFIX}/bin + mkdir -p ${NATIVEPREFIX}/lib + mkdir -p ${PREFIX}/bin + mkdir -p ${PREFIX}/lib + mkdir -p ${BUILD_BASE} + + mkdir -p ${SDK} + 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + + tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz + + # bdb + SOURCE_FILE=${SOURCES_PATH}/db-4.8.30.NC.tar.gz + BUILD_DIR=${BUILD_BASE}/db-4.8.30.NC + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + sed -i 's/__atomic_compare_exchange/__atomic_compare_exchange_db/g' ${BUILD_DIR}/dbinc/atomic.h + pushd ${BUILD_DIR} + cd build_unix; + ../dist/configure --host=${HOST} --prefix="${PREFIX}" --disable-shared --enable-cxx CC="${INT_CC}" CXX="${INT_CXX}" AR="${INT_AR}" RANLIB="${INT_RANLIB}" OBJC="${INT_OBJC}" OBJCXX="${INT_OBJCXX}" CFLAGS="${INT_CFLAGS}" CXXFLAGS="${INT_CXXFLAGS}" LDFLAGS="${INT_CLANG_LDFLAGS} ${INT_LDFLAGS}" CPPFLAGS="${INT_CPPFLAGS}" + make $MAKEOPTS libdb.a libdb_cxx.a + make install_lib install_include + popd + + # openssl + SOURCE_FILE=${SOURCES_PATH}/openssl-1.0.1g.tar.gz + BUILD_DIR=${BUILD_BASE}/openssl-1.0.1g + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + pushd ${BUILD_DIR} + sed -ie "s|cc:|${INT_CC}:|" ${BUILD_DIR}/Configure + sed -ie "s|\(-arch [_a-zA-Z0-9]*\)|\1 --sysroot ${SDK} -target ${HOST} -msse2|" ${BUILD_DIR}/Configure + AR="${INT_AR}" RANLIB="${INT_RANLIB}" ./Configure --prefix=${PREFIX} --openssldir=${PREFIX}/etc/openssl zlib shared no-krb5 darwin64-x86_64-cc ${INT_LDFLAGS} ${INT_CLANG_LDFLAGS} ${INT_CPPFLAGS} + sed -i "s|engines apps test|engines|" ${BUILD_DIR}/Makefile + sed -i "/define DATE/d" ${BUILD_DIR}/crypto/Makefile + make -j1 build_libs libcrypto.pc libssl.pc openssl.pc + make -j1 install_sw + popd + + #libminiupnpc + SOURCE_FILE=${SOURCES_PATH}/miniupnpc-1.9.tar.gz + BUILD_DIR=${BUILD_BASE}/miniupnpc-1.9 + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + pushd ${BUILD_DIR} + CFLAGS="${INT_CFLAGS} ${INT_CPPFLAGS}" make $MAKEOPTS OS=Darwin CC="${INT_CC}" AR="${INT_AR}" libminiupnpc.a + install -d ${PREFIX}/include/miniupnpc + install *.h ${PREFIX}/include/miniupnpc + install libminiupnpc.a ${PREFIX}/lib + popd + + # qrencode + SOURCE_FILE=${SOURCES_PATH}/qrencode-3.4.3.tar.bz2 + BUILD_DIR=${BUILD_BASE}/qrencode-3.4.3 + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + pushd ${BUILD_DIR} + + # m4 folder is not included in the stable release, which can confuse aclocal + # if its timestamp ends up being earlier than configure.ac when extracted + touch aclocal.m4 + ./configure --host=${HOST} --prefix="${PREFIX}" --disable-shared CC="${INT_CC}" CXX="${INT_CXX}" AR="${INT_AR}" RANLIB="${INT_RANLIB}" OBJC="${INT_OBJC}" OBJCXX="${INT_OBJCXX}" CFLAGS="${INT_CFLAGS}" CXXFLAGS="${INT_CXXFLAGS}" LDFLAGS="${INT_CLANG_LDFLAGS} ${INT_LDFLAGS}" CPPFLAGS="${INT_CPPFLAGS}" --disable-shared -without-tools --disable-sdltest --disable-dependency-tracking + make $MAKEOPTS + make install + popd + + # libprotobuf + SOURCE_FILE=${SOURCES_PATH}/protobuf-2.5.0.tar.bz2 + BUILD_DIR=${BUILD_BASE}/protobuf-2.5.0 + + tar -C ${BUILD_BASE} -xjf ${SOURCE_FILE} + pushd ${BUILD_DIR} + ./configure --host=${HOST} --prefix="${PREFIX}" --disable-shared --enable-cxx CC="${INT_CC}" CXX="${INT_CXX}" AR="${INT_AR}" RANLIB="${INT_RANLIB}" OBJC="${INT_OBJC}" OBJCXX="${INT_OBJCXX}" CFLAGS="${INT_CFLAGS}" CXXFLAGS="${INT_CXXFLAGS}" LDFLAGS="${INT_CLANG_LDFLAGS} ${INT_LDFLAGS}" CPPFLAGS="${INT_CPPFLAGS}" --enable-shared=no --disable-dependency-tracking --with-protoc=${NATIVEPREFIX}/bin/protoc + cd src + make $MAKEOPTS libprotobuf.la + make install-libLTLIBRARIES install-nobase_includeHEADERS + cd .. + make install-pkgconfigDATA + popd + + # boost + SOURCE_FILE=${SOURCES_PATH}/boost_1_55_0.tar.bz2 + BUILD_DIR=${BUILD_BASE}/boost_1_55_0 + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + pushd ${BUILD_DIR} + ./bootstrap.sh --with-libraries=chrono,filesystem,program_options,system,thread,test + echo "using darwin : : ${INT_CXX} : \"${INT_CFLAGS} ${INT_CPPFLAGS}\" \"${INT_LDFLAGS} ${INT_CLANG_LDFLAGS}\" \"${INT_LIBTOOL}\" \"${INT_STRIP}\" : ;" > "user-config.jam" + ./b2 -d2 --layout=tagged --build-type=complete --prefix="${PREFIX}" --toolset=darwin-4.2.1 --user-config=user-config.jam variant=release threading=multi link=static install + popd + + export GZIP="-9n" + find prefix | sort | tar --no-recursion -czf osx-depends-${REVISION}.tar.gz -T - + + mv osx-depends-${REVISION}.tar.gz $OUTDIR diff --git a/contrib/gitian-descriptors/gitian-osx-native.yml b/contrib/gitian-descriptors/gitian-osx-native.yml new file mode 100644 index 0000000000..6040e5ac5b --- /dev/null +++ b/contrib/gitian-descriptors/gitian-osx-native.yml @@ -0,0 +1,179 @@ +--- +name: "osx-native" +suites: +- "precise" +architectures: +- "i386" +packages: +- "git-core" +- "automake" +- "faketime" +- "libssl-dev" +- "libbz2-dev" +- "libz-dev" +- "cmake" +- "libcap-dev" +- "p7zip-full" +- "uuid-dev" + +reference_datetime: "2013-06-01 00:00:00" +remotes: [] +files: +- "10cc648683617cca8bcbeae507888099b41b530c.tar.gz" +- "cctools-809.tar.gz" +- "dyld-195.5.tar.gz" +- "ld64-127.2.tar.gz" +- "protobuf-2.5.0.tar.bz2" +- "MacOSX10.6.pkg" +- "cdrkit-1.1.11.tar.gz" +- "libdmg-hfsplus-v0.1.tar.gz" +- "clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz" +- "cdrkit-deterministic.patch" + + +script: | + + echo "18406961fd4a1ec5c7ea35c91d6a80a2f8bb797a2bd243a610bd75e13eff9aca 10cc648683617cca8bcbeae507888099b41b530c.tar.gz" | sha256sum -c + echo "03ba62749b843b131c7304a044a98c6ffacd65b1399b921d69add0375f79d8ad cctools-809.tar.gz" | sha256sum -c + echo "2cf0484c87cf79b606b351a7055a247dae84093ae92c747a74e0cde2c8c8f83c dyld-195.5.tar.gz" | sha256sum -c + echo "97b75547b2bd761306ab3e15ae297f01e7ab9760b922bc657f4ef72e4e052142 ld64-127.2.tar.gz" | sha256sum -c + echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c + echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c + echo "d1c030756ecc182defee9fe885638c1785d35a2c2a297b4604c0e0dcc78e47da cdrkit-1.1.11.tar.gz" | sha256sum -c + echo "6569a02eb31c2827080d7d59001869ea14484c281efab0ae7f2b86af5c3120b3 libdmg-hfsplus-v0.1.tar.gz" | sha256sum -c + echo "b9d57a88f9514fa1f327a1a703756d0c1c960f4c58494a5bd80313245d13ffff clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz" | sha256sum -c + echo "cc12bdbd7a09f71cb2a6a3e6ec3e0abe885ca7111c2b47857f5095e5980caf4f cdrkit-deterministic.patch" | sha256sum -c + + + REVISION=r2 + export REFERENCE_DATETIME + export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export FAKETIME=$REFERENCE_DATETIME + export TZ=UTC + + REAL_AR=`which ar` + REAL_RANLIB=`which ranlib` + REAL_DATE=`which date` + + echo '#!/bin/bash' > $HOME/ar + echo 'export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1' >> $HOME/ar + echo "$REAL_AR \"\$@\"" >> $HOME/ar + + echo '#!/bin/bash' > $HOME/ranlib + echo 'export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1' >> $HOME/ranlib + echo "$REAL_RANLIB \"\$@\"" >> $HOME/ranlib + + echo '#!/bin/bash' > $HOME/date + echo 'export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1' >> $HOME/date + echo "$REAL_DATE \"\$@\"" >> $HOME/date + + chmod +x $HOME/ar $HOME/ranlib $HOME/date + + + export PATH=$HOME:$PATH + export SOURCES_PATH=`pwd` + + mkdir -p osx-cross-depends/build + cd osx-cross-depends + + NATIVEPREFIX=`pwd`/native-prefix + BUILD_BASE=`pwd`/build + SDK=`pwd`/SDKs/MacOSX10.6.sdk + HOST=x86_64-apple-darwin11 + MIN_VERSION=10.6 + + CFLAGS="" + CXXFLAGS="${CFLAGS}" + LDFLAGS="-L${NATIVEPREFIX}/lib" + + export PATH=${NATIVEPREFIX}/bin:${PATH} + + mkdir -p ${NATIVEPREFIX}/bin + mkdir -p ${NATIVEPREFIX}/lib + + mkdir -p ${SDK} + 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + + # Clang + SOURCE_FILE=${SOURCES_PATH}/clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz + BUILD_DIR=${BUILD_BASE}/clang+llvm-3.2-x86-linux-ubuntu-12.04 + + mkdir -p ${NATIVEPREFIX}/lib/clang/3.2/include + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + cp ${BUILD_DIR}/bin/clang ${NATIVEPREFIX}/bin/ + cp ${BUILD_DIR}/bin/clang++ ${NATIVEPREFIX}/bin/ + cp ${BUILD_DIR}/lib/libLTO.so ${NATIVEPREFIX}/lib/ + cp ${BUILD_DIR}/lib/clang/3.2/include/* ${NATIVEPREFIX}/lib/clang/3.2/include + + # cctools + SOURCE_FILE=${SOURCES_PATH}/10cc648683617cca8bcbeae507888099b41b530c.tar.gz + BUILD_DIR=${BUILD_BASE}/toolchain4-10cc648683617cca8bcbeae507888099b41b530c + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + mkdir -p ${BUILD_DIR}/sdks + pushd ${BUILD_DIR}/sdks; + ln -sf ${SDK} MacOSX10.6.sdk + ln -sf ${SOURCES_PATH}/cctools-809.tar.gz ${BUILD_DIR}/cctools2odcctools/cctools-809.tar.gz + ln -sf ${SOURCES_PATH}/ld64-127.2.tar.gz ${BUILD_DIR}/cctools2odcctools/ld64-127.2.tar.gz + ln -sf ${SOURCES_PATH}/dyld-195.5.tar.gz ${BUILD_DIR}/cctools2odcctools/dyld-195.5.tar.gz + + tar -C ${BUILD_DIR} -xf ${SOURCES_PATH}/clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz + # Hack in the use of our llvm headers rather than grabbing the old llvm-gcc. + sed -i "s|GCC_DIR|LLVM_CLANG_DIR|g" ${BUILD_DIR}/cctools2odcctools/extract.sh + sed -i "s|llvmgcc42-2336.1|clang+llvm-3.2-x86-linux-ubuntu-12.04|g" ${BUILD_DIR}/cctools2odcctools/extract.sh + sed -i "s|\${LLVM_CLANG_DIR}/llvmCore/include/llvm-c|\${LLVM_CLANG_DIR}/include/llvm-c \${LLVM_CLANG_DIR}/include/llvm |" ${BUILD_DIR}/cctools2odcctools/extract.sh + + sed -i "s|fAC_INIT|AC_INIT|" ${BUILD_DIR}/cctools2odcctools/files/configure.ac + sed -i 's/\# Dynamically linked LTO/\t ;\&\n\t linux*)\n# Dynamically linked LTO/' ${BUILD_DIR}/cctools2odcctools/files/configure.ac + + cd ${BUILD_DIR}/cctools2odcctools + ./extract.sh --osxver 10.6 + cd odcctools-809 + ./configure --prefix=${NATIVEPREFIX} --target=${HOST} CFLAGS="${CFLAGS} -I${NATIVEPREFIX}/include -D__DARWIN_UNIX03 -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" LDFLAGS="${LDFLAGS} -Wl,-rpath=\\\$\$ORIGIN/../lib" --with-sysroot=${SDK} + + # The 'PC' define in sparc/reg.h conflicts but doesn't get used anyway. Just rename it. + sed -i "s|define\tPC|define\tPC_|" ${BUILD_DIR}/cctools2odcctools/odcctools-809/include/architecture/sparc/reg.h + make $MAKEOPTS + make install + popd + + # protoc + SOURCE_FILE=${SOURCES_PATH}/protobuf-2.5.0.tar.bz2 + BUILD_DIR=${BUILD_BASE}/protobuf-2.5.0 + + tar -C ${BUILD_BASE} -xjf ${SOURCE_FILE} + pushd ${BUILD_DIR}; + ./configure --enable-shared=no --disable-dependency-tracking --prefix=${NATIVEPREFIX} + make $MAKEOPTS + cp ${BUILD_DIR}/src/protoc ${NATIVEPREFIX}/bin/ + popd + + # cdrkit + SOURCE_FILE=${SOURCES_PATH}/cdrkit-1.1.11.tar.gz + BUILD_DIR=${BUILD_BASE}/cdrkit-1.1.11 + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + pushd ${BUILD_DIR} + patch -p1 < ${SOURCES_PATH}/cdrkit-deterministic.patch + cmake -DCMAKE_INSTALL_PREFIX=${NATIVEPREFIX} + make $MAKEOPTS genisoimage + make -C genisoimage install + popd + + # libdmg-hfsplus + SOURCE_FILE=${SOURCES_PATH}/libdmg-hfsplus-v0.1.tar.gz + BUILD_DIR=${BUILD_BASE}/libdmg-hfsplus-libdmg-hfsplus-v0.1 + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + mkdir -p ${BUILD_DIR}/build + pushd ${BUILD_DIR}/build + cmake -DCMAKE_INSTALL_PREFIX:PATH=${NATIVEPREFIX}/bin .. + make $MAKEOPTS + make install + popd + + rm -rf native-prefix/docs + + export GZIP="-9n" + find native-prefix | sort | tar --no-recursion -czf osx-native-depends-$REVISION.tar.gz -T - + mv osx-native-depends-$REVISION.tar.gz $OUTDIR diff --git a/contrib/gitian-descriptors/gitian-osx-qt.yml b/contrib/gitian-descriptors/gitian-osx-qt.yml new file mode 100644 index 0000000000..d0be016e68 --- /dev/null +++ b/contrib/gitian-descriptors/gitian-osx-qt.yml @@ -0,0 +1,192 @@ +--- +name: "osx-qt" +suites: +- "precise" +architectures: +- "i386" +packages: +- "git-core" +- "automake" +- "p7zip-full" + +reference_datetime: "2013-06-01 00:00:00" +remotes: [] +files: +- "qt-everywhere-opensource-src-5.2.1.tar.gz" +- "osx-native-depends-r2.tar.gz" +- "osx-depends-r2.tar.gz" +- "MacOSX10.6.pkg" + +script: | + + echo "84e924181d4ad6db00239d87250cc89868484a14841f77fb85ab1f1dbdcd7da1 qt-everywhere-opensource-src-5.2.1.tar.gz" | sha256sum -c + echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c + + REVISION=r2 + export SOURCES_PATH=`pwd` + export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export ZERO_AR_DATE=1 + + export TZ=UTC + + REAL_DATE=`which date` + echo '#!/bin/bash' > $HOME/date + echo "$REAL_DATE -d \"${REFERENCE_DATETIME}\" \"\$@\"" >> $HOME/date + + chmod +x $HOME/date + export PATH=$HOME:$PATH + + mkdir -p osx-cross-depends/build + cd osx-cross-depends + + PREFIX=`pwd`/prefix + NATIVEPREFIX=`pwd`/native-prefix + BUILD_BASE=`pwd`/build + SDK=`pwd`/SDKs/MacOSX10.6.sdk + HOST=x86_64-apple-darwin11 + MIN_VERSION=10.6 + + INT_CFLAGS="-target ${HOST} -mmacosx-version-min=${MIN_VERSION} --sysroot ${SDK} -msse2 -Qunused-arguments" + INT_CXXFLAGS="${INT_CFLAGS}" + INT_LDFLAGS="-L${PREFIX}/lib -L${SDK}/usr/lib/i686-apple-darwin10/4.2.1" + INT_LDFLAGS_CLANG="-B${NATIVEPREFIX}/bin" + INT_CPPFLAGS="-I${PREFIX}/include" + INT_CC=clang + INT_CXX=clang++ + INT_OBJC=clang + INT_OBJCXX=clang++ + INT_AR=${HOST}-ar + INT_RANLIB=${HOST}-ranlib + INT_LIBTOOL=${HOST}-libtool + INT_INSTALL_NAME_TOOL=${HOST}-install_name_tool + + export PATH=${NATIVEPREFIX}/bin:${PATH} + + mkdir -p ${NATIVEPREFIX}/bin + mkdir -p ${NATIVEPREFIX}/lib + mkdir -p ${PREFIX}/bin + mkdir -p ${PREFIX}/lib + mkdir -p ${BUILD_BASE} + + mkdir -p ${SDK} + 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + + tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz + + + mkdir -p SDKs + 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + + tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz + export PATH=`pwd`/native-prefix/bin:$PATH + tar xf /home/ubuntu/build/osx-depends-r2.tar.gz + + SOURCE_FILE=${SOURCES_PATH}/qt-everywhere-opensource-src-5.2.1.tar.gz + BUILD_DIR=${BUILD_BASE}/qt-everywhere-opensource-src-5.2.1 + + + tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} + + # Install our mkspec. All files are pulled from the macx-clang spec, except for + # our custom qmake.conf + SPECFILE=${BUILD_DIR}/qtbase/mkspecs/macx-clang-linux/qmake.conf + + mkdir -p ${BUILD_DIR}/qtbase/mkspecs/macx-clang-linux + cp -f ${BUILD_DIR}/qtbase/mkspecs/macx-clang/Info.plist.lib ${BUILD_DIR}/qtbase/mkspecs/macx-clang-linux/ + cp -f ${BUILD_DIR}/qtbase/mkspecs/macx-clang/Info.plist.app ${BUILD_DIR}/qtbase/mkspecs/macx-clang-linux/ + cp -f ${BUILD_DIR}/qtbase/mkspecs/macx-clang/qplatformdefs.h ${BUILD_DIR}/qtbase/mkspecs/macx-clang-linux/ + + cat > ${SPECFILE} < Date: Wed, 21 May 2014 12:27:37 +0200 Subject: [PATCH 076/336] qt: Periodic language update --- src/qt/locale/bitcoin_af_ZA.ts | 2 +- src/qt/locale/bitcoin_ar.ts | 443 +++++++++++++++++---------------- src/qt/locale/bitcoin_cs.ts | 18 +- src/qt/locale/bitcoin_da.ts | 88 +++---- src/qt/locale/bitcoin_es.ts | 9 +- src/qt/locale/bitcoin_fi.ts | 2 +- src/qt/locale/bitcoin_ja.ts | 8 +- src/qt/locale/bitcoin_ko_KR.ts | 68 ++--- src/qt/locale/bitcoin_lt.ts | 6 +- src/qt/locale/bitcoin_lv_LV.ts | 289 ++++++++++----------- src/qt/locale/bitcoin_nb.ts | 6 +- src/qt/locale/bitcoin_pl.ts | 8 +- src/qt/locale/bitcoin_sk.ts | 207 ++++++++------- 13 files changed, 588 insertions(+), 566 deletions(-) diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index 80e4de010f..6e8395e589 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -1898,7 +1898,7 @@ Address: %4 The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Die adres waarheen die betaling gestuur moet word (b.v. 1H7wyVL5HCNoVFyyBJSDojwyxcCChU7TPA) + Die adres waarheen die betaling gestuur moet word (b.v. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Enter a label for this address to add it to your address book diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index 32b0d4b0fc..5877cc35d9 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -20,7 +20,7 @@ This product includes software developed by the OpenSSL Project for use in the O Copyright - + الحقوق محفوظة The Bitcoin Core developers @@ -35,7 +35,7 @@ This product includes software developed by the OpenSSL Project for use in the O AddressBookPage Double-click to edit address or label - أنقر على الماوس مرتين لتعديل العنوان + أنقر بالماوس مرتين لتعديل العنوان او الوصف Create a new address @@ -43,7 +43,7 @@ This product includes software developed by the OpenSSL Project for use in the O &New - + &جديد Copy the currently selected address to the system clipboard @@ -51,11 +51,11 @@ This product includes software developed by the OpenSSL Project for use in the O &Copy - + &نسخ C&lose - + &اغلاق &Copy Address @@ -63,7 +63,7 @@ This product includes software developed by the OpenSSL Project for use in the O Delete the currently selected address from the list - + حذف العنوان المحدد من القائمة Export the data in the current tab to a file @@ -71,7 +71,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Export - + &تصدير &Delete @@ -79,23 +79,23 @@ This product includes software developed by the OpenSSL Project for use in the O Choose the address to send coins to - + اختر العنوان الذي سترسل له العملات Choose the address to receive coins with - + اختر العنوان الذي تستقبل عليه العملات C&hoose - + &اختر Sending addresses - + ارسال العناوين Receiving addresses - + استقبال العناوين These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. @@ -107,7 +107,7 @@ This product includes software developed by the OpenSSL Project for use in the O Copy &Label - + نسخ &الوصف &Edit @@ -115,7 +115,7 @@ This product includes software developed by the OpenSSL Project for use in the O Export Address List - + تصدير قائمة العناوين Comma separated file (*.csv) @@ -123,7 +123,7 @@ This product includes software developed by the OpenSSL Project for use in the O Exporting Failed - + فشل التصدير There was an error trying to save the address list to %1. @@ -157,15 +157,15 @@ This product includes software developed by the OpenSSL Project for use in the O New passphrase - عبارة مرور جديدة + كلمة مرور جديدة Repeat new passphrase - ادخل الجملة السرية مرة أخرى + ادخل كلمة المرور الجديدة مرة أخرى Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. - أدخل عبارة مرور جديدة إلى المحفظة. الرجاء استخدام عبارة مرور تتكون من10 حروف عشوائية على الاقل, أو أكثر من 7 كلمات + أدخل كلمة مرور جديدة للمحفظة. <br/>الرجاء استخدام كلمة مرور تتكون <b>من 10 حروف عشوائية على الاقل</b>, أو <b>أكثر من 7 كلمات</b>. Encrypt wallet @@ -173,7 +173,7 @@ This product includes software developed by the OpenSSL Project for use in the O This operation needs your wallet passphrase to unlock the wallet. - هذه العملية تحتاج عبارة المرور محفظتك لفتحها + هذه العملية تحتاج كلمة مرور محفظتك لفتحها Unlock wallet @@ -181,7 +181,7 @@ This product includes software developed by the OpenSSL Project for use in the O This operation needs your wallet passphrase to decrypt the wallet. - هذه العملية تحتاج عبارة المرور محفظتك فك تشفيرها + هذه العملية تحتاج كلمة مرور محفظتك لفك تشفيرها Decrypt wallet @@ -189,15 +189,15 @@ This product includes software developed by the OpenSSL Project for use in the O Change passphrase - تغيير عبارة المرور + تغيير كلمة المرور Enter the old and new passphrase to the wallet. - أدخل عبارة المرور القديمة والجديدة إلى المحفظة. + أدخل كلمة المرور القديمة والجديدة للمحفظة. Confirm wallet encryption - تأكيد التشفير المحفظة + تأكيد تشفير المحفظة Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! @@ -213,7 +213,7 @@ This product includes software developed by the OpenSSL Project for use in the O Warning: The Caps Lock key is on! - + تحذير: مفتاح الحروف الكبيرة مفعل Wallet encrypted @@ -229,12 +229,11 @@ This product includes software developed by the OpenSSL Project for use in the O Wallet encryption failed due to an internal error. Your wallet was not encrypted. - شل تشفير المحفظة بسبب خطأ داخلي. لم يتم تشفير محفظتك. + فشل تشفير المحفظة بسبب خطأ داخلي. لم يتم تشفير محفظتك. The supplied passphrases do not match. - عبارتي المرور ليستا متطابقتان - + كلمتي المرور ليستا متطابقتان Wallet unlock failed @@ -242,8 +241,7 @@ This product includes software developed by the OpenSSL Project for use in the O The passphrase entered for the wallet decryption was incorrect. - عبارة المرور التي تم إدخالها لفك شفرة المحفظة غير صحيحة. - + كلمة المرور التي تم إدخالها لفك تشفير المحفظة غير صحيحة. Wallet decryption failed @@ -262,11 +260,11 @@ This product includes software developed by the OpenSSL Project for use in the O Synchronizing with network... - مزامنة مع شبكة ... + مزامنة مع الشبكة ... &Overview - نظرة عامة + &نظرة عامة Node @@ -278,11 +276,11 @@ This product includes software developed by the OpenSSL Project for use in the O &Transactions - المعاملات + &المعاملات Browse transaction history - تصفح التاريخ المعاملات + تصفح سجل المعاملات E&xit @@ -294,7 +292,7 @@ This product includes software developed by the OpenSSL Project for use in the O Show information about Bitcoin - إظهار المزيد معلومات حول Bitcoin + إظهار معلومات حول بت كوين About &Qt @@ -306,19 +304,19 @@ This product includes software developed by the OpenSSL Project for use in the O &Options... - خيارات ... + &خيارات ... &Encrypt Wallet... - + &تشفير المحفظة &Backup Wallet... - + &نسخ احتياط للمحفظة &Change Passphrase... - + &تغيير كلمة المرور &Sending addresses... @@ -330,7 +328,7 @@ This product includes software developed by the OpenSSL Project for use in the O Open &URI... - + افتح &URI... Importing blocks from disk... @@ -354,11 +352,11 @@ This product includes software developed by the OpenSSL Project for use in the O Change the passphrase used for wallet encryption - تغيير عبارة المرور المستخدمة لتشفير المحفظة + تغيير كلمة المرور المستخدمة لتشفير المحفظة &Debug window - + &نافذة المعالجة Open debugging and diagnostic console @@ -366,7 +364,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Verify message... - + &التحقق من الرسالة... Bitcoin @@ -378,19 +376,19 @@ This product includes software developed by the OpenSSL Project for use in the O &Send - + %ارسل &Receive - + &استقبل &Show / Hide - + &عرض / اخفاء Show or hide the main Window - + عرض او اخفاء النافذة الرئيسية Encrypt the private keys that belong to your wallet @@ -406,15 +404,15 @@ This product includes software developed by the OpenSSL Project for use in the O &File - ملف + &ملف &Settings - الاعدادات + &الاعدادات &Help - مساعدة + &مساعدة Tabs toolbar @@ -458,7 +456,7 @@ This product includes software developed by the OpenSSL Project for use in the O Bitcoin client - عميل بتكوين + عميل بت كوين %n active connection(s) to Bitcoin network @@ -478,15 +476,15 @@ This product includes software developed by the OpenSSL Project for use in the O %n hour(s) - + %n ساعة%n ساعة%n ساعة%n ساعات%n ساعات%n ساعات %n day(s) - + %n يوم%n يوم%n يوم%n أيام%n أيام%n ايام %n week(s) - + %n اسبوع%n اسبوع%n اسبوع%n اسابيع%n اسابيع%n اسابيع %1 and %2 @@ -514,15 +512,15 @@ This product includes software developed by the OpenSSL Project for use in the O Warning - + تحذير Information - + معلومات Up to date - محين + محدث Catching up... @@ -534,7 +532,7 @@ This product includes software developed by the OpenSSL Project for use in the O Incoming transaction - المعاملات واردة + المعاملات الواردة Date: %1 @@ -542,15 +540,19 @@ Amount: %2 Type: %3 Address: %4 - + التاريخ : 1% +القيمة: 2% +النوع: 3% +العنوان: 4% + Wallet is <b>encrypted</b> and currently <b>unlocked</b> - المحفظة مشفرة و مفتوحة حاليا + المحفظة <b>مشفرة</b> و <b>مفتوحة</b> حاليا Wallet is <b>encrypted</b> and currently <b>locked</b> - المحفظة مشفرة و مقفلة حاليا + المحفظة <b>مشفرة</b> و <b>مقفلة</b> حاليا A fatal error occurred. Bitcoin can no longer continue safely and will quit. @@ -561,7 +563,7 @@ Address: %4 ClientModel Network Alert - + تنبيه من الشبكة @@ -572,7 +574,7 @@ Address: %4 Quantity: - + الكمية: Bytes: @@ -580,7 +582,7 @@ Address: %4 Amount: - + القيمة Priority: @@ -588,7 +590,7 @@ Address: %4 Fee: - + رسوم : Low Output: @@ -628,7 +630,7 @@ Address: %4 Confirmations - + تأكيد Confirmed @@ -636,11 +638,11 @@ Address: %4 Priority - + أفضلية Copy address - انسخ عنوان + انسخ العنوان Copy label @@ -648,11 +650,11 @@ Address: %4 Copy amount - نسخ الكمية + نسخ القيمة Copy transaction ID - + نسخ رقم المعاملة Lock unspent @@ -664,15 +666,15 @@ Address: %4 Copy quantity - + نسخ الكمية Copy fee - + نسخ الرسوم Copy after fee - + نسخ بعد الرسوم Copy bytes @@ -680,7 +682,7 @@ Address: %4 Copy priority - + نسخ الافضلية Copy low output @@ -688,19 +690,19 @@ Address: %4 Copy change - + نسخ التغييرات highest - + الاعلى higher - + اعلى high - + عالي medium-high @@ -716,7 +718,7 @@ Address: %4 low - + منخفض lower @@ -732,7 +734,7 @@ Address: %4 none - + لا شيء Dust @@ -803,7 +805,7 @@ Address: %4 &Label - + &وصف The label associated with this address list entry @@ -815,11 +817,11 @@ Address: %4 &Address - العنوان + &العنوان New receiving address - عنوان تلقي جديد + عنوان أستلام جديد New sending address @@ -827,8 +829,7 @@ Address: %4 Edit receiving address - تعديل عنوان التلقي - + تعديل عنوان الأستلام Edit sending address @@ -855,11 +856,11 @@ Address: %4 FreespaceChecker A new data directory will be created. - + سيتم انشاء دليل بيانات جديد name - + الاسم Directory already exists. Add %1 if you intend to create a new directory here. @@ -871,7 +872,7 @@ Address: %4 Cannot create data directory here. - + لا يمكن انشاء دليل بيانات هنا . @@ -925,7 +926,7 @@ Address: %4 Intro Welcome - + أهلا Welcome to Bitcoin Core. @@ -941,11 +942,11 @@ Address: %4 Use the default data directory - + استخدام دليل البانات الافتراضي Use a custom data directory: - + استخدام دليل بيانات مخصص: Bitcoin @@ -961,11 +962,11 @@ Address: %4 GB of free space available - + قيقا بايت مساحة متاحة (of %1GB needed) - + ( بحاجة الى 1%قيقا بايت ) @@ -984,11 +985,11 @@ Address: %4 Select payment request file - + حدد ملف طلب الدفع Select payment request file to open - + حدد ملف طلب الدفع لفتحه @@ -999,7 +1000,7 @@ Address: %4 &Main - الرئيسي + &الرئيسي Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. @@ -1007,7 +1008,7 @@ Address: %4 Pay transaction &fee - + ادفع &رسوم المعاملة Automatically start Bitcoin after logging in to the system. @@ -1023,7 +1024,7 @@ Address: %4 MB - + م ب Number of script &verification threads @@ -1047,7 +1048,7 @@ Address: %4 Third party transaction URLs - + عنوان النطاق للطرف الثالث Active command-line options that override above options: @@ -1059,11 +1060,11 @@ Address: %4 &Reset Options - + &استعادة الخيارات &Network - + &الشبكة (0 = auto, <0 = leave that many cores free) @@ -1071,11 +1072,11 @@ Address: %4 W&allet - + &محفظة Expert - + تصدير Enable coin &control features @@ -1099,15 +1100,15 @@ Address: %4 Proxy &IP: - + بروكسي &اي بي: &Port: - + &المنفذ: Port of the proxy (e.g. 9050) - + منفذ البروكسي (مثلا 9050) SOCKS &Version: @@ -1139,11 +1140,11 @@ Address: %4 &Display - + &عرض User Interface &language: - + واجهة المستخدم &اللغة: The user interface language can be set here. This setting will take effect after restarting Bitcoin. @@ -1183,11 +1184,11 @@ Address: %4 none - + لا شيء Confirm options reset - + تأكيد استعادة الخيارات Client restart required to activate changes. @@ -1230,7 +1231,7 @@ Address: %4 Pending: - + معلق: Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance @@ -1246,11 +1247,11 @@ Address: %4 Total: - + المجموع: Your current total balance - + رصيدك الكلي الحالي <b>Recent transactions</b> @@ -1321,7 +1322,7 @@ Address: %4 Bad response from server %1 - + استجابة سيئة من الملقم٪ 1 Payment acknowledged @@ -1363,15 +1364,15 @@ Address: %4 QRImageWidget &Save Image... - + &حفظ الصورة &Copy Image - + &نسخ الصورة Save QR Code - + حفظ رمز الاستجابة السريعة QR PNG Image (*.png) @@ -1402,7 +1403,7 @@ Address: %4 General - + عام Using OpenSSL version @@ -1410,7 +1411,7 @@ Address: %4 Startup time - + وقت البدء Network @@ -1450,23 +1451,23 @@ Address: %4 &Network Traffic - + &حركة مرور الشبكة &Clear - + &مسح Totals - + المجاميع In: - + داخل: Out: - + خارج: Build date @@ -1490,7 +1491,7 @@ Address: %4 Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. - + استخدم اسهم الاعلى و الاسفل للتنقل بين السجلات و <b>Ctrl-L</b> لمسح الشاشة Type <b>help</b> for an overview of available commands. @@ -1498,46 +1499,46 @@ Address: %4 %1 B - + 1% بايت %1 KB - + 1% كيلو بايت %1 MB - + 1% ميقا بايت %1 GB - + 1% قيقا بايت %1 m - + 1% دقيقة %1 h - + 1% ساعة %1 h %2 m - + 1% ساعة 2% دقيقة ReceiveCoinsDialog &Amount: - + &القيمة &Label: - + &الوصف: &Message: - + &رسالة: Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. @@ -1565,15 +1566,15 @@ Address: %4 Clear all fields of the form. - + مسح كل حقول النموذج المطلوبة Clear - + مسح Requested payments history - + سجل طلبات الدفع &Request payment @@ -1585,7 +1586,7 @@ Address: %4 Show - + عرض Remove the selected entries from the list @@ -1593,7 +1594,7 @@ Address: %4 Remove - + ازل Copy label @@ -1605,26 +1606,26 @@ Address: %4 Copy amount - نسخ الكمية + نسخ القيمة ReceiveRequestDialog QR Code - + رمز كيو ار Copy &URI - + نسخ &URI Copy &Address - + نسخ &العنوان &Save Image... - + &حفظ الصورة Request payment to %1 @@ -1636,7 +1637,7 @@ Address: %4 URI - + URI Address @@ -1652,7 +1653,7 @@ Address: %4 Message - + رسالة Resulting URI too long, try to reduce the text for label / message. @@ -1675,7 +1676,7 @@ Address: %4 Message - + رسالة Amount @@ -1687,7 +1688,7 @@ Address: %4 (no message) - + ( لا رسائل ) (no amount) @@ -1710,7 +1711,7 @@ Address: %4 automatically selected - + اختيار تلقائيا Insufficient funds! @@ -1718,7 +1719,7 @@ Address: %4 Quantity: - + الكمية : Bytes: @@ -1726,15 +1727,15 @@ Address: %4 Amount: - + القيمة : Priority: - + افضلية : Fee: - + رسوم : Low Output: @@ -1742,11 +1743,11 @@ Address: %4 After Fee: - + بعد الرسوم : Change: - + تعديل : If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. @@ -1762,7 +1763,7 @@ Address: %4 Add &Recipient - + أضافة &مستلم Clear all fields of the form. @@ -1782,7 +1783,7 @@ Address: %4 S&end - + &ارسال Confirm send coins @@ -1790,23 +1791,23 @@ Address: %4 %1 to %2 - + 1% الى 2% Copy quantity - + نسخ الكمية Copy amount - نسخ الكمية + نسخ القيمة Copy fee - + نسخ الرسوم Copy after fee - + نسخ بعد الرسوم Copy bytes @@ -1814,7 +1815,7 @@ Address: %4 Copy priority - + نسخ الافضلية Copy low output @@ -1822,15 +1823,15 @@ Address: %4 Copy change - + نسخ التعديل Total Amount %1 (= %2) - + مجموع المبلغ %1 (= %2) or - + أو The recipient address is not valid, please recheck. @@ -1842,11 +1843,11 @@ Address: %4 The amount exceeds your balance. - + القيمة تتجاوز رصيدك The total exceeds your balance when the %1 transaction fee is included. - + المجموع يتجاوز رصيدك عندما يتم اضافة 1% رسوم العملية Duplicate address found, can only send to each address once per send operation. @@ -1897,7 +1898,7 @@ Address: %4 Pay &To: - ادفع الى + ادفع &الى : The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1909,7 +1910,7 @@ Address: %4 &Label: - + &وصف : Choose previously used address @@ -1925,7 +1926,7 @@ Address: %4 Paste address from clipboard - انسخ العنوان من لوحة المفاتيح + الصق العنوان من لوحة المفاتيح Alt+P @@ -1972,7 +1973,7 @@ Address: %4 Do not shut down the computer until this window disappears. - + لا توقف عمل الكمبيوتر حتى تختفي هذه النافذة @@ -1983,7 +1984,7 @@ Address: %4 &Sign Message - + &توقيع الرسالة You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to. @@ -2011,11 +2012,11 @@ Address: %4 Enter the message you want to sign here - + ادخل الرسالة التي تريد توقيعها هنا Signature - + التوقيع Copy the current signature to the system clipboard @@ -2023,11 +2024,11 @@ Address: %4 Sign the message to prove you own this Bitcoin address - + وقع الرسالة لتثبت انك تمتلك عنوان البت كوين هذا Sign &Message - + توقيع $الرسالة Reset all sign message fields @@ -2039,7 +2040,7 @@ Address: %4 &Verify Message - + &تحقق رسالة Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. @@ -2055,7 +2056,7 @@ Address: %4 Verify &Message - + تحقق &الرسالة Reset all verify message fields @@ -2067,7 +2068,7 @@ Address: %4 Click "Sign Message" to generate signature - + اضغط "توقيع الرسالة" لتوليد التوقيع The entered address is invalid. @@ -2083,7 +2084,7 @@ Address: %4 Wallet unlock was cancelled. - + تم الغاء عملية فتح المحفظة Private key for the entered address is not available. @@ -2103,7 +2104,7 @@ Address: %4 Please check the signature and try again. - + فضلا تاكد من التوقيع وحاول مرة اخرى The signature did not match the message digest. @@ -2148,7 +2149,7 @@ Address: %4 conflicted - + يتعارض %1/offline @@ -2196,7 +2197,7 @@ Address: %4 label - + علامة Credit @@ -2216,7 +2217,7 @@ Address: %4 Transaction fee - رسوم التحويل + رسوم المعاملة Net amount @@ -2224,7 +2225,7 @@ Address: %4 Message - + رسالة Comment @@ -2236,7 +2237,7 @@ Address: %4 Merchant - + تاجر Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. @@ -2268,7 +2269,7 @@ Address: %4 , has not been successfully broadcast yet - لم يتم حتى الآن البث بنجاح + , لم يتم حتى الآن البث بنجاح Open for %n more block(s) @@ -2421,7 +2422,7 @@ Address: %4 Range... - v + المدى... Received with @@ -2449,7 +2450,7 @@ Address: %4 Min amount - + الحد الأدنى Copy address @@ -2465,7 +2466,7 @@ Address: %4 Copy transaction ID - + نسخ رقم العملية Edit label @@ -2473,7 +2474,7 @@ Address: %4 Show transaction details - + عرض تفاصيل المعاملة Export Transaction History @@ -2481,7 +2482,7 @@ Address: %4 Exporting Failed - + فشل التصدير There was an error trying to save the transaction history to %1. @@ -2489,7 +2490,7 @@ Address: %4 Exporting Successful - نجح الاستخراج + نجح التصدير The transaction history was successfully saved to %1. @@ -2529,7 +2530,7 @@ Address: %4 Range: - + المدى: to @@ -2554,7 +2555,7 @@ Address: %4 WalletView &Export - + &تصدير Export the data in the current tab to a file @@ -2562,7 +2563,7 @@ Address: %4 Backup Wallet - + نسخ احتياط للمحفظة Wallet Data (*.dat) @@ -2570,7 +2571,7 @@ Address: %4 Backup Failed - + فشل النسخ الاحتياطي There was an error trying to save the wallet data to %1. @@ -2582,7 +2583,7 @@ Address: %4 Backup Successful - + نجاح النسخ الاحتياطي @@ -2613,7 +2614,7 @@ Address: %4 Specify data directory - حدد موقع مجلد المعلومات او data directory + حدد مجلد المعلومات Listen for connections on <port> (default: 8333 or testnet: 18333) @@ -2867,15 +2868,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error: Disk space is low! - + تحذير: مساحة القرص منخفضة Error: Wallet locked, unable to create transaction! - + تحذير: المحفظة مغلقة , لا تستطيع تنفيذ المعاملة Error: system error: - + خطأ: خطأ في النظام: Failed to listen on any port. Use -listen=0 if you want this. @@ -2959,7 +2960,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid -onion address: '%s' - + عنوان اونيون غير صحيح : '%s' Not enough file descriptors available. @@ -3015,7 +3016,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Verifying wallet... - + التحقق من المحفظة ... Wait for RPC server to start @@ -3027,7 +3028,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Wallet options: - + خيارات المحفظة : Warning: Deprecated argument -debugnet ignored, use -debug=net @@ -3059,7 +3060,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Information - + معلومات Invalid amount for -minrelaytxfee=<amount>: '%s' @@ -3159,7 +3160,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Signing transaction failed - + فشل توقيع المعاملة Specify connection timeout in milliseconds (default: 5000) @@ -3171,19 +3172,19 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. System error: - + خطأ في النظام : Transaction amount too small - + قيمة العملية صغيره جدا Transaction amounts must be positive - + يجب ان يكون قيمة العملية بالموجب Transaction too large - + المعاملة طويلة جدا Use UPnP to map the listening port (default: 0) @@ -3199,11 +3200,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning - + تحذير Warning: This version is obsolete, upgrade required! - + تحذير : هذا الاصدار قديم , يتطلب التحديث Zapping all transactions from wallet... @@ -3239,7 +3240,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Upgrade wallet to latest format - + تحديث المحفظة للنسخة الاخيرة Set key pool size to <n> (default: 100) @@ -3259,7 +3260,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Server private key (default: server.pem) - + المفتاح الخاص بالسيرفر (default: server.pem) This help message @@ -3295,7 +3296,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid -proxy address: '%s' - + عنوان البروكسي غير صحيح : '%s' Unknown network specified in -onlynet: '%s' @@ -3319,11 +3320,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid amount - + قيمة غير صحيحة Insufficient funds - + اموال غير كافية Loading block index... @@ -3343,7 +3344,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Cannot write default address - + لايمكن كتابة العنوان الافتراضي Rescanning... @@ -3355,7 +3356,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. To use the %s option - + لاستخدام %s الخيار Error diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index ba4d2def35..6cc783b59e 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -1571,7 +1571,7 @@ Adresa: %4 Clear all fields of the form. - + Smaže všechny pole formuláře. Clear @@ -1599,7 +1599,7 @@ Adresa: %4 Remove - + Odstranit Copy label @@ -1712,11 +1712,11 @@ Adresa: %4 Inputs... - + Vstupy... automatically selected - + automaticky vybrané Insufficient funds! @@ -1772,7 +1772,7 @@ Adresa: %4 Clear all fields of the form. - + Smaže všechny pole formuláře. Clear &All @@ -1880,7 +1880,7 @@ Adresa: %4 Are you sure you want to send? - + Opravdu chcete odeslat %1? added as transaction fee @@ -1947,7 +1947,7 @@ Adresa: %4 This is a verified payment request. - + Toto je ověřený požadavek k platbě. Enter a label for this address to add it to the list of used addresses @@ -1959,7 +1959,7 @@ Adresa: %4 This is an unverified payment request. - + Toto je neověřený požadavek k platbě. Pay To: @@ -3127,7 +3127,7 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. RPC server options: - + Možnosti RPC serveru: Randomly drop 1 of every <n> network messages diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 442a86b7c0..5795701497 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -52,7 +52,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Copy the currently selected address to the system clipboard - Kopier den valgte adresse til systemets udklipsholder + Kopiér den valgte adresse til systemets udklipsholder &Copy @@ -64,7 +64,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Copy Address - Kopier adresse + Kopiér adresse Delete the currently selected address from the list @@ -112,11 +112,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Copy &Label - Kopier mærkat + Kopiér mærkat &Edit - Rediger + Redigér Export Address List @@ -174,7 +174,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Encrypt wallet - Krypter tegnebog + Kryptér tegnebog This operation needs your wallet passphrase to unlock the wallet. @@ -190,7 +190,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Decrypt wallet - Dekrypter tegnebog + Dekryptér tegnebog Change passphrase @@ -261,11 +261,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open BitcoinGUI Sign &message... - Underskriv besked... + Underskriv besked … Synchronizing with network... - Synkroniserer med netværk... + Synkroniserer med netværk … &Overview @@ -309,19 +309,19 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Options... - Indstillinger... + Indstillinger … &Encrypt Wallet... - Krypter tegnebog... + Kryptér tegnebog … &Backup Wallet... - Sikkerhedskopier tegnebog... + Sikkerhedskopiér tegnebog … &Change Passphrase... - Skift adgangskode... + Skift adgangskode … &Sending addresses... @@ -349,7 +349,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Modify configuration options for Bitcoin - Rediger konfigurationsindstillinger af Bitcoin + Redigér konfigurationsindstillinger for Bitcoin Backup wallet to another location @@ -369,7 +369,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Verify message... - Verificér besked... + Verificér besked … Bitcoin @@ -413,7 +413,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Settings - Indstillinger + Opsætning &Help @@ -465,7 +465,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open %n active connection(s) to Bitcoin network - %n aktiv(e) forbindelse(r) til Bitcoin-netværket%n aktiv(e) forbindelse(r) til Bitcoin-netværket + %n aktiv forbindelse til Bitcoin-netværket%n aktive forbindelser til Bitcoin-netværket No block source available... @@ -529,7 +529,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Catching up... - Indhenter... + Indhenter … Sent transaction @@ -806,7 +806,7 @@ Adresse: %4 EditAddressDialog Edit Address - Rediger adresse + Redigér adresse &Label @@ -834,11 +834,11 @@ Adresse: %4 Edit receiving address - Rediger modtagelsesadresse + Redigér modtagelsesadresse Edit sending address - Rediger afsendelsesadresse + Redigér afsendelsesadresse The entered address "%1" is already in the address book. @@ -1017,11 +1017,11 @@ Adresse: %4 Automatically start Bitcoin after logging in to the system. - Start Bitcoin automatisk, når der logges ind på systemet + Start Bitcoin automatisk, når der logges ind på systemet. &Start Bitcoin on system login - Start Bitcoin, når systemet startes + Start Bitcoin ved systemlogin Size of &database cache @@ -1097,11 +1097,11 @@ Adresse: %4 Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. - Åbn Bitcoin-klientens port på routeren automatisk. Dette virker kun, når din router understøtter UPnP og UPnP er aktiveret. + Åbn automatisk Bitcoin-klientens port på routeren. Dette virker kun, når din router understøtter UPnP, og UPnP er aktiveret. Map port using &UPnP - Konfigurer port vha. UPnP + Konfigurér port vha. UPnP Proxy &IP: @@ -1113,7 +1113,7 @@ Adresse: %4 Port of the proxy (e.g. 9050) - Porten på proxyen (f.eks. 9050) + Port for proxyen (fx 9050) SOCKS &Version: @@ -1121,7 +1121,7 @@ Adresse: %4 SOCKS version of the proxy (e.g. 5) - SOCKS-version af proxyen (f.eks. 5) + SOCKS-version for proxyen (fx 5) &Window @@ -1416,7 +1416,7 @@ Adresse: %4 Startup time - Opstartstid + Opstartstidspunkt Network @@ -1492,11 +1492,11 @@ Adresse: %4 Welcome to the Bitcoin RPC console. - Velkommen til Bitcoin RPC-konsollen + Velkommen til Bitcoin RPC-konsollen. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. - Brug op og ned-piletasterne til at navigere historikken og <b>Ctrl-L</b> til at rydde skærmen. + Brug op- og ned-piletasterne til at navigere i historikken og <b>Ctrl-L</b> til at rydde skærmen. Type <b>help</b> for an overview of available commands. @@ -1852,11 +1852,11 @@ Adresse: %4 The total exceeds your balance when the %1 transaction fee is included. - Totalen overstiger din saldo, når %1 transaktionsgebyr er inkluderet. + Totalen overstiger din saldo, når transaktionsgebyret på %1 er inkluderet. Duplicate address found, can only send to each address once per send operation. - Duplikeret adresse fundet. Du kan kun sende til hver adresse en gang pr. afsendelse. + Duplikeret adresse fundet. Du kan kun sende til hver adresse én gang pr. afsendelse. Transaction creation failed! @@ -2396,7 +2396,7 @@ Adresse: %4 Amount removed from or added to balance. - Beløb fjernet eller tilføjet balance. + Beløb trukket fra eller tilføjet balance. @@ -2427,7 +2427,7 @@ Adresse: %4 Range... - Interval... + Interval … Received with @@ -2459,15 +2459,15 @@ Adresse: %4 Copy address - Kopier adresse + Kopiér adresse Copy label - Kopier mærkat + Kopiér mærkat Copy amount - Kopier beløb + Kopiér beløb Copy transaction ID @@ -2475,7 +2475,7 @@ Adresse: %4 Edit label - Rediger mærkat + Redigér mærkat Show transaction details @@ -2631,7 +2631,7 @@ Adresse: %4 Connect to a node to retrieve peer addresses, and disconnect - Forbind til en knude for at modtage adresse, og afbryd + Forbind til en knude for at modtage adresser på andre knuder, og afbryd derefter Specify your own public address @@ -2655,7 +2655,7 @@ Adresse: %4 Accept command line and JSON-RPC commands - Accepter kommandolinje- og JSON-RPC-kommandoer + Acceptér kommandolinje- og JSON-RPC-kommandoer Bitcoin Core RPC client version @@ -2663,7 +2663,7 @@ Adresse: %4 Run in the background as a daemon and accept commands - Kør i baggrunden som en service, og accepter kommandoer + Kør i baggrunden som en service, og acceptér kommandoer Use the test network @@ -3291,7 +3291,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Loading addresses... - Indlæser adresser... + Indlæser adresser … Error loading wallet.dat: Wallet corrupted @@ -3343,7 +3343,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Loading block index... - Indlæser blokindeks... + Indlæser blokindeks … Add a node to connect to and attempt to keep the connection open @@ -3351,7 +3351,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Loading wallet... - Indlæser tegnebog... + Indlæser tegnebog … Cannot downgrade wallet @@ -3363,7 +3363,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Rescanning... - Genindlæser... + Genindlæser … Done loading diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 8ca8360ef6..1ed40a77c2 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -320,7 +320,7 @@ Eric Young (eay@cryptsoft.com) y el software UPnP escrito por Thomas Bernard. &Backup Wallet... - %Guardar copia del monedero... + &Guardar copia del monedero... &Change Passphrase... @@ -1052,11 +1052,11 @@ Dirección: %4 Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. - + URLs de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como items del menú contextual. El %s en la URL es reemplazado por el hash de la transacción. Se pueden separar múltiples URLs por una barra vertical |. Third party transaction URLs - + URLs de transacciones de terceros Active command-line options that override above options: @@ -1977,8 +1977,7 @@ Dirección: %4 ShutdownWindow Bitcoin Core is shutting down... - Bitcoin Core se está cerrando... - + Bitcoin Core se está cerrando... Do not shut down the computer until this window disappears. diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index ece70f6075..dc72359590 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -1053,7 +1053,7 @@ Osoite: %4 Third party transaction URLs - + Kolmannen osapuolen rahansiirto URL:t Active command-line options that override above options: diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index 5edfc0746a..d3a6cece87 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -611,7 +611,7 @@ Address: %4 (un)select all - + すべて選択/選択解除 Tree mode @@ -739,7 +739,7 @@ Address: %4 none - + なし Dust @@ -1189,7 +1189,7 @@ Address: %4 none - + なし Confirm options reset @@ -1425,7 +1425,7 @@ Address: %4 Name - + 名前 Number of connections diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index f5d2dddbe4..fb013f4c1d 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -48,7 +48,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http &New - + 새 항목(N) Copy the currently selected address to the system clipboard @@ -60,7 +60,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http C&lose - + 닫기 (L) &Copy Address @@ -76,7 +76,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http &Export - + &내보내기 &Delete @@ -92,7 +92,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http C&hoose - + 선택하기 (H) Sending addresses @@ -108,7 +108,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - + 비트코인을 받을 수 있는 계좌 주소입니다. 매 거래마다 새로운 주소 사용을 권장합니다. Copy &Label @@ -401,11 +401,11 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http Sign messages with your Bitcoin addresses to prove you own them - + 지갑 주소가 자신 소유의 것인지 증명하기 위해 비트코인 주소에 서명할 수 있습니다. Verify messages to ensure they were signed with specified Bitcoin addresses - + 비트코인 주소의 전자 서명 확인을 위해 첨부된 메시지가 있을 경우 이를 검증할 수 있습니다. &File @@ -441,11 +441,11 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http Show the list of used sending addresses and labels - + 한번 이상 사용된 보내는 주소와 주소 제목의 목록을 보여줍니다. Show the list of used receiving addresses and labels - + 한번 이상 사용된 받는 주소와 주소 제목의 목록을 보여줍니다. Open a bitcoin: URI or payment request @@ -814,7 +814,7 @@ Address: %4 The label associated with this address list entry - + 현재 선택된 주소 필드의 제목입니다. The address associated with this address list entry. This can only be modified for sending addresses. @@ -869,7 +869,7 @@ Address: %4 Directory already exists. Add %1 if you intend to create a new directory here. - + 폴더가 이미 존재합니다. 새로운 폴더 생성을 원한다면 %1 명령어를 추가하세요. Path already exists, and is not a directory. @@ -1275,7 +1275,7 @@ Address: %4 URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. - + URI의 파싱에 문제가 발생했습니다. 잘못된 비트코인 주소나 URI 파라미터 구성에 오류가 존재할 수 있습니다. Requested payment amount of %1 is too small (considered dust). @@ -1358,7 +1358,7 @@ Address: %4 Bitcoin Core didn't yet exit safely... - + 비트코인 코어가 아직 안전하게 종료되지 않았습니다. Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1563,7 +1563,7 @@ Address: %4 Use this form to request payments. All fields are <b>optional</b>. - + 지급을 요청하기 위해 아래 형식을 사용하세요. 입력값은 <b>선택 사항</b> 입니다. An optional amount to request. Leave this empty or zero to not request a specific amount. @@ -1907,7 +1907,7 @@ Address: %4 The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - + 비트코인을 송금할 지갑 주소 입력하기 (예 : 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Enter a label for this address to add it to your address book @@ -2049,7 +2049,7 @@ Address: %4 Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. - + 메시지를 검증하기 위해 아래 칸에 각각 지갑 주소와 메시지, 전자서명을 입력하세요. (메시지 원본의 띄어쓰기, 들여쓰기, 행 나눔 등이 정확하게 입력되어야 하므로 원본을 복사해서 입력하세요) 이 기능은 메시지 검증이 주 목적이며, 네트워크 침입자에 의해 변조되지 않도록 전자서명 해독에 불필요한 시간을 소모하지 마세요. The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2174,7 +2174,7 @@ Address: %4 , broadcast through %n node(s) - + %n 노드를 거쳐 전파합니다. Date @@ -2278,7 +2278,7 @@ Address: %4 Open for %n more block(s) - + %n 개의 추가 블럭을 읽습니다. unknown @@ -2320,7 +2320,7 @@ Address: %4 Open for %n more block(s) - + %n 개의 추가 블럭을 읽습니다. Open until %1 @@ -2560,7 +2560,7 @@ Address: %4 WalletView &Export - + &내보내기 Export the data in the current tab to a file @@ -2721,7 +2721,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! - + 오류 : 해당 거래는 송금액, 다중 거래, 최근 수령한 금액의 사용 등의 이유로 최소 %s 이상의 송금 수수료가 필요합니다. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) @@ -2753,7 +2753,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. This is a pre-release test build - use at your own risk - do not use for mining or merchant applications - + 이 빌드 버전은 정식 출시 전 테스트의 목적이며, 예기치 않은 위험과 오류가 발생할 수 있습니다. 채굴과 상점용 소프트웨어로 사용하는 것을 권하지 않습니다. Unable to bind to %s on this computer. Bitcoin Core is probably already running. @@ -2773,7 +2773,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - + 경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. @@ -2781,11 +2781,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. - + 경고 : wallet.dat 파일을 읽는 중 에러가 발생했습니다. 주소 키는 모두 정확하게 로딩되었으나 거래 데이터와 주소록 필드에서 누락이나 오류가 존재할 수 있습니다. Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - + 경고 : wallet.dat가 손상되어 데이터가 복구되었습니다. 원래의 wallet.dat 파일은 %s 후에 wallet.{timestamp}.bak 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다. (default: 1) @@ -2957,7 +2957,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Importing... - + 들여오기 중... Incorrect or no genesis block found. Wrong datadir for network? @@ -2969,7 +2969,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Not enough file descriptors available. - + 사용 가능한 파일 디스크립터-File Descriptor-가 부족합니다. Prepend debug output with timestamp (default: 1) @@ -2981,7 +2981,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Rebuild block chain index from current blk000??.dat files - + 현재의 blk000??.dat 파일들로부터 블록체인 색인을 재구성합니다. Select SOCKS version for -proxy (4 or 5, default: 5) @@ -2997,7 +2997,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set the number of threads to service RPC calls (default: 4) - + 원격 프로시져 호출 서비스를 위한 쓰레드 개수를 설정합니다 (기본값 : 4) Specify wallet file (within data directory) @@ -3041,11 +3041,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. You need to rebuild the database using -reindex to change -txindex - + -txindex를 바꾸기 위해서는 -reindex를 사용해서 데이터베이스를 재구성해야 합니다. Imports blocks from external blk000??.dat file - 외부 blk000??.dat 파일에서 블록 가져오기 + 외부 blk000??.dat 파일에서 블록을 가져옵니다. Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. @@ -3069,11 +3069,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid amount for -minrelaytxfee=<amount>: '%s' - + 노드로 전달하기 위한 최저 거래 수수료가 부족합니다. - minrelaytxfee=<amount>: '%s' - Invalid amount for -mintxfee=<amount>: '%s' - + 최저 거래 수수료가 부족합니다. -mintxfee=<amount>: '%s' Limit size of signature cache to <n> entries (default: 50000) @@ -3173,7 +3173,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Start Bitcoin Core Daemon - + 비트코인 코어의 데몬 프로그램을 실행합니다. System error: diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index a9898adb2b..c74fd8ab3b 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -1490,7 +1490,7 @@ Adresas: %4 Welcome to the Bitcoin RPC console. - + Sveiki atvykę į Bitcoin RPC konsolę. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. @@ -2633,7 +2633,7 @@ Adresas: %4 Specify your own public address - + Nurodykite savo nuosavą viešą adresą Threshold for disconnecting misbehaving peers (default: 100) @@ -3347,7 +3347,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Cannot write default address - + Negalima parašyti įprasto adreso Rescanning... diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index c17f65e125..299e4d55e0 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -16,7 +16,12 @@ This is experimental software. Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. - + +Šī ir eksperimentālā programmatūra. + +Izplatīta saskaņā ar MIT/X11 programmatūras licenci, skatīt pievienoto datni COPYING vai http://www.opensource.org/licenses/mit-license.php. + +Šis produkts ietver programmatūru, ko izstrādājis OpenSSL Project izmantošanai OpenSSL Toolkit (http://www.openssl.org/) un šifrēšanas programmatūru no Eric Young (eay@cryptsoft.com) un UPnP programmatūru no Thomas Bernard. Copyright @@ -28,7 +33,7 @@ This product includes software developed by the OpenSSL Project for use in the O (%1-bit) - + (%1-biti) @@ -63,7 +68,7 @@ This product includes software developed by the OpenSSL Project for use in the O Delete the currently selected address from the list - + Izdzēst iezīmētās adreses no saraksta Export the data in the current tab to a file @@ -79,11 +84,11 @@ This product includes software developed by the OpenSSL Project for use in the O Choose the address to send coins to - + Izvēlies adresi uz kuru sūtīt bitcoins Choose the address to receive coins with - + Izvēlies adresi ar kuru saņemt bitcoins C&hoose @@ -201,11 +206,11 @@ This product includes software developed by the OpenSSL Project for use in the O Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! - + Brīdinājums: Ja tu nošifrē savu maciņu un pazaudē paroli, tu <b>PAZAUDĒSI VISAS SAVAS BITCOINS</b>! Are you sure you wish to encrypt your wallet? - + Vai tu tiešām vēlies šifrēt savu maciņu? IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. @@ -249,7 +254,7 @@ This product includes software developed by the OpenSSL Project for use in the O Wallet passphrase was successfully changed. - + Maciņa parole tika veiksmīgi nomainīta. @@ -268,7 +273,7 @@ This product includes software developed by the OpenSSL Project for use in the O Node - + Node Show general overview of wallet @@ -304,31 +309,31 @@ This product includes software developed by the OpenSSL Project for use in the O &Options... - &Iespējas + &Iespējas... &Encrypt Wallet... - Š&ifrēt maciņu... + Šifrēt &maciņu... &Backup Wallet... - &Izveidot maciņa rezerves kopiju + &Maciņa Rezerves Kopija... &Change Passphrase... - &Mainīt paroli + Mainīt &Paroli... &Sending addresses... - &Adrešu sūtīšana... + &Sūtīšanas adreses... &Receiving addresses... - Adrešu &saņemšana... + Saņemšanas &adreses... Open &URI... - Atvērt &URI + Atvērt &URI... Importing blocks from disk... @@ -356,7 +361,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Debug window - &Debug logs + &Atkļūdošanas logs Open debugging and diagnostic console @@ -388,7 +393,7 @@ This product includes software developed by the OpenSSL Project for use in the O Show or hide the main Window - + Parādīt vai paslēpt galveno Logu Encrypt the private keys that belong to your wallet @@ -428,7 +433,7 @@ This product includes software developed by the OpenSSL Project for use in the O Request payments (generates QR codes and bitcoin: URIs) - + Pieprasīt maksājumus (izveido QR kodu un bitcoin: URIs) &About Bitcoin Core @@ -496,7 +501,7 @@ This product includes software developed by the OpenSSL Project for use in the O %1 behind - + %1 aizmugurē Last received block was generated %1 ago. @@ -556,7 +561,7 @@ Adrese: %4 A fatal error occurred. Bitcoin can no longer continue safely and will quit. - + Radās fatāla kļūda. Bitcoin Core nevar vairs droši turpināt un tiks izslēgta. @@ -594,7 +599,7 @@ Adrese: %4 Low Output: - + Zema Izeja: After Fee: @@ -606,7 +611,7 @@ Adrese: %4 (un)select all - + iezīmēt visus Tree mode @@ -658,11 +663,11 @@ Adrese: %4 Lock unspent - + Aizslēgt neiztērēto Unlock unspent - + Atslēgt neiztērēto Copy quantity @@ -686,7 +691,7 @@ Adrese: %4 Copy low output - + Kopēt zemo izeju Copy change @@ -730,7 +735,7 @@ Adrese: %4 (%1 locked) - + (%1 aizslēgts) none @@ -738,7 +743,7 @@ Adrese: %4 Dust - + Putekļi yes @@ -856,7 +861,7 @@ Adrese: %4 FreespaceChecker A new data directory will be created. - + Tiks izveidota jauna datu mape. name @@ -868,11 +873,11 @@ Adrese: %4 Path already exists, and is not a directory. - + Šāds ceļš jau pastāv un tā nav mape. Cannot create data directory here. - + Šeit nevar izveidot datu mapi. @@ -942,11 +947,11 @@ Adrese: %4 Use the default data directory - + Izmantot noklusēto datu mapi Use a custom data directory: - + Izmantot pielāgotu datu mapi: Bitcoin @@ -1020,7 +1025,7 @@ Adrese: %4 Size of &database cache - + &Datubāzes kešatmiņas izmērs MB @@ -1028,19 +1033,19 @@ Adrese: %4 Number of script &verification threads - + Skriptu &pārbaudes pavedienu skaits Connect to the Bitcoin network through a SOCKS proxy. - + Savienoties ar Bitcoin tīklu caur SOCKS starpniekserveri. &Connect through SOCKS proxy (default proxy): - + &Savienoties caur SOCKS starpniekserveri (noklusējuma starpniekserveris) IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) - + Starpniekservera IP adrese (piem. IPv4: 127.0.0.1 / IPv6: ::1) Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. @@ -1048,19 +1053,19 @@ Adrese: %4 Third party transaction URLs - + Trešo personu transakciju URLs Active command-line options that override above options: - + Aktīvās komandrindas opcijas, kuras pārspēko šos iestatījumus: Reset all client options to default. - + Atiestatīt visus klienta iestatījumus uz noklusējumu. &Reset Options - + &Atiestatīt Iestatījumus. &Network @@ -1100,7 +1105,7 @@ Adrese: %4 Proxy &IP: - Proxy &IP: + Starpniekservera &IP: &Port: @@ -1108,7 +1113,7 @@ Adrese: %4 Port of the proxy (e.g. 9050) - Proxy ports (piem. 9050) + Starpniekservera ports (piem. 9050) SOCKS &Version: @@ -1116,7 +1121,7 @@ Adrese: %4 SOCKS version of the proxy (e.g. 5) - proxy SOCKS versija (piem. 5) + Starpniekservera SOCKS versija (piem. 5) &Window @@ -1172,7 +1177,7 @@ Adrese: %4 &OK - &OK + &Labi &Cancel @@ -1184,11 +1189,11 @@ Adrese: %4 none - neviens + neviena Confirm options reset - + Apstiprināt iestatījumu atiestatīšanu Client restart required to activate changes. @@ -1196,7 +1201,7 @@ Adrese: %4 Client will be shutdown, do you want to proceed? - + Klients tiks izslēgts, vai vēlaties turpināt? This change would require a client restart. @@ -1204,7 +1209,7 @@ Adrese: %4 The supplied proxy address is invalid. - Norādītā proxy adrese nav derīga. + Norādītā starpniekservera adrese nav derīga. @@ -1231,11 +1236,11 @@ Adrese: %4 Pending: - + Neizšķirts: Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance - + Kopējā apstiprināmo transakciju vērtība, vēl nav ieskaitīta tērējamajā bilancē Immature: @@ -1247,7 +1252,7 @@ Adrese: %4 Total: - Kopā: + Kopsumma: Your current total balance @@ -1266,7 +1271,7 @@ Adrese: %4 PaymentServer URI handling - + URI apstrāde URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters. @@ -1278,11 +1283,11 @@ Adrese: %4 Payment request error - + Maksājumu pieprasījuma kļūda Cannot start bitcoin: click-to-pay handler - + Nevar palaist Bitcoin: nospied-lai-maksātu apstrādātāju Net manager warning @@ -1310,7 +1315,7 @@ Adrese: %4 Refund from %1 - + Atmaksa no %1 Error communicating with %1: %2 @@ -1326,11 +1331,11 @@ Adrese: %4 Payment acknowledged - + Maksājums atzīts Network request error - + Tīkla pieprasījuma kļūda @@ -1353,7 +1358,7 @@ Adrese: %4 Bitcoin Core didn't yet exit safely... - + Bitcoin Core vel neizgāja droši... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1399,11 +1404,11 @@ Adrese: %4 Debug window - + Atkļūdošanas logs General - + Vispārējs Using OpenSSL version @@ -1463,11 +1468,11 @@ Adrese: %4 In: - + Ie.: Out: - + Iz.: Build date @@ -1475,7 +1480,7 @@ Adrese: %4 Debug log file - + Atkļūdošanas žurnāla datne Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. @@ -1546,7 +1551,7 @@ Adrese: %4 R&euse an existing receiving address (not recommended) - + &Atkārtoti izmantot esošo saņemšanas adresi (nav ieteicams) An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. @@ -1582,7 +1587,7 @@ Adrese: %4 Show the selected request (does the same as double clicking an entry) - + Parādīt atlasītos pieprasījumus (tas pats, kas dubultklikšķis uz ieraksta) Show @@ -1590,7 +1595,7 @@ Adrese: %4 Remove the selected entries from the list - + Noņemt atlasītos ierakstus no saraksta. Remove @@ -1625,7 +1630,7 @@ Adrese: %4 &Save Image... - &Saglabāt Attēlu + &Saglabāt Attēlu... Request payment to %1 @@ -1707,15 +1712,15 @@ Adrese: %4 Inputs... - + Ieejas... automatically selected - + automātiski atlasīts Insufficient funds! - + Nepietiekami līdzekļi! Quantity: @@ -1739,7 +1744,7 @@ Adrese: %4 Low Output: - + Zema Izeja: After Fee: @@ -1819,7 +1824,7 @@ Adrese: %4 Copy low output - + Kopēt zemās izejas Copy change @@ -1835,7 +1840,7 @@ Adrese: %4 The recipient address is not valid, please recheck. - + Saņēmēja adrese ir nepareiza, lūdzu pārbaudi. The amount to pay must be larger than 0. @@ -1863,7 +1868,7 @@ Adrese: %4 Warning: Invalid Bitcoin address - + Brīdinājums: Nederīga Bitcoin adrese (no label) @@ -1871,7 +1876,7 @@ Adrese: %4 Warning: Unknown change address - + Brīdinājums: Nezināma atlikuma adrese Are you sure you want to send? @@ -1887,7 +1892,7 @@ Adrese: %4 Invalid payment address %1 - + Nederīga maksājuma adrese %1 @@ -1914,7 +1919,7 @@ Adrese: %4 Choose previously used address - + Izvēlies iepriekš izmantoto adresi This is a normal payment. @@ -1962,7 +1967,7 @@ Adrese: %4 Memo: - + Memo: @@ -1973,7 +1978,7 @@ Adrese: %4 Do not shut down the computer until this window disappears. - + Neizslēdziet datoru kamēr šis logs nepazūd. @@ -1992,11 +1997,11 @@ Adrese: %4 The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - + Adrese ar kuru parakstīt ziņojumu (piem. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Choose previously used address - + Izvēlies iepriekš izmantoto adresi Alt+A @@ -2012,7 +2017,7 @@ Adrese: %4 Enter the message you want to sign here - + Šeit ievadi ziņojumu kuru vēlies parakstīt Signature @@ -2020,11 +2025,11 @@ Adrese: %4 Copy the current signature to the system clipboard - + Kopēt parakstu uz sistēmas starpliktuvi Sign the message to prove you own this Bitcoin address - + Parakstīt ziņojumu lai pierādītu, ka esi šīs Bitcoin adreses īpašnieks. Sign &Message @@ -2032,7 +2037,7 @@ Adrese: %4 Reset all sign message fields - + Atiestatīt visus laukus Clear &All @@ -2048,7 +2053,7 @@ Adrese: %4 The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - + Adrese ar kādu ziņojums tika parakstīts (piem. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Verify the message to ensure it was signed with the specified Bitcoin address @@ -2060,7 +2065,7 @@ Adrese: %4 Reset all verify message fields - + Atiestatīt visus laukus Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2072,23 +2077,23 @@ Adrese: %4 The entered address is invalid. - + Ievadītā adrese ir nederīga. Please check the address and try again. - + Lūdzu pārbaudi adresi un mēģini vēlreiz. The entered address does not refer to a key. - + Ievadītā adrese neattiecas uz atslēgu. Wallet unlock was cancelled. - + Maciņa atslēgšana tika atcelta. Private key for the entered address is not available. - + Privātā atslēga priekš ievadītās adreses nav pieejama. Message signing failed. @@ -2104,11 +2109,11 @@ Adrese: %4 Please check the signature and try again. - + Lūdzu pārbaudi parakstu un mēģini vēlreiz. The signature did not match the message digest. - + Paraksts neatbilda ziņojuma apkopojumam. Message verification failed. @@ -2149,7 +2154,7 @@ Adrese: %4 conflicted - + pretrunā %1/offline @@ -2181,7 +2186,7 @@ Adrese: %4 Generated - + Ģenerēts From @@ -2193,15 +2198,15 @@ Adrese: %4 own address - + paša adrese label - + etiķete Credit - + Kredīts matures in %n more block(s) @@ -2209,11 +2214,11 @@ Adrese: %4 not accepted - + nav pieņemts Debit - + Debets Transaction fee @@ -2237,7 +2242,7 @@ Adrese: %4 Merchant - + Tirgotājs Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. @@ -2245,7 +2250,7 @@ Adrese: %4 Debug information - + Atkļūdošanas informācija Transaction @@ -2253,7 +2258,7 @@ Adrese: %4 Inputs - + Ieejas Amount @@ -2273,7 +2278,7 @@ Adrese: %4 Open for %n more block(s) - + Atvērts vel %n blokusAtvērts vel %n blokuAtvērts vel %n blokus unknown @@ -2315,7 +2320,7 @@ Adrese: %4 Open for %n more block(s) - + Atvērts vel %n blokusAtvērts vel %n blokuAtvērts vel %n blokus Open until %1 @@ -2347,7 +2352,7 @@ Adrese: %4 Conflicted - + Pretrunā Received with @@ -2494,7 +2499,7 @@ Adrese: %4 The transaction history was successfully saved to %1. - + Transakciju vēsture tika veiksmīgi saglabāta uz %1. Comma separated file (*.csv) @@ -2555,7 +2560,7 @@ Adrese: %4 WalletView &Export - &Eksportēt... + &Eksportēt Export the data in the current tab to a file @@ -2654,7 +2659,7 @@ Adrese: %4 Bitcoin Core RPC client version - + Bitcoin Core RPC klienta versija Run in the background as a daemon and accept commands @@ -2764,7 +2769,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly. - + Brīdinājums: Lūdzu pārbaudi vai tava datora datums un laiks ir pareizs! Ja pulkstenis ir nepareizs, Bitcoin Core nestrādās pareizi. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. @@ -2784,11 +2789,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. (default: 1) - + (noklusējums: 1) (default: wallet.dat) - + (noklusējums: wallet.dat) <category> can be: @@ -2796,7 +2801,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Attempt to recover private keys from a corrupt wallet.dat - + Mēģināt atgūt privātās atslēgas no bojāta wallet.dat Bitcoin Core Daemon @@ -2812,11 +2817,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connect only to the specified node(s) - + Savienoties tikai ar norādītajām nodēm. Connect through SOCKS proxy - + Savienoties caur SOCKS starpniekserveri Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) @@ -2824,7 +2829,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + Savienojuma iestatījumi: Corrupted block database detected @@ -2832,7 +2837,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Debugging/Testing options: - + Atkļūdošanas/Testēšanas iestatījumi: Disable safemode, override a real safe mode event (default: 0) @@ -2860,7 +2865,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error loading block database - + Kļūda ielādējot bloku datubāzi Error opening block database @@ -2868,15 +2873,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error: Disk space is low! - + Kļūda: Zema diska vieta! Error: Wallet locked, unable to create transaction! - + Kļūda: Maciņš ir aizslēgts, nevar izveidot transakciju! Error: system error: - + Kļūda: sistēmas kļūda: Failed to listen on any port. Use -listen=0 if you want this. @@ -2932,11 +2937,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Find peers using DNS lookup (default: 1 unless -connect) - + Atrast pīrus izmantojot DNS uzmeklēšanu (noklusējums: 1 ja nav -connect) Force safe mode (default: 0) - + Piespiest drošo režīmu (noklusējums: 0) Generate coins (default: 0) @@ -2952,7 +2957,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Importing... - + Importē... Incorrect or no genesis block found. Wrong datadir for network? @@ -3000,7 +3005,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Spend unconfirmed change when sending transactions (default: 1) - + Tērēt neapstiprinātu atlikumu kad sūta transakcijas (noklusējums: 1) This is intended for regression testing tools and app development. @@ -3020,7 +3025,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Wait for RPC server to start - + Uzgaidi līdz RPC serveris palaižas Wallet %s resides outside data directory %s @@ -3040,7 +3045,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Imports blocks from external blk000??.dat file - + Importēt blokus no ārējās blk000??.dat datnes Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. @@ -3112,7 +3117,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. RPC server options: - + RPC servera iestatījumi: Randomly drop 1 of every <n> network messages @@ -3132,7 +3137,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Send command to Bitcoin Core - + Sūtīt komandu uz Bitcoin Core Send trace/debug info to console instead of debug.log file @@ -3152,7 +3157,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Show benchmark information (default: 0) - + Rādīt etalonuzdevuma informāciju (noklusējums: 0) Shrink debug.log file on client startup (default: 1 when no -debug) @@ -3160,7 +3165,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Signing transaction failed - + Transakcijas parakstīšana neizdevās Specify connection timeout in milliseconds (default: 5000) @@ -3168,19 +3173,19 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Start Bitcoin Core Daemon - + Sākt Bitcoin Core Procesu System error: - + Sistēmas kļūda: Transaction amount too small - + Transakcijas summa ir pārāk maza Transaction amounts must be positive - + Transakcijas summai ir jābūt pozitīvai Transaction too large @@ -3204,7 +3209,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: This version is obsolete, upgrade required! - + Brīdinājums: Šī versija ir novecojusi, nepieciešams atjauninājums! Zapping all transactions from wallet... @@ -3212,7 +3217,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. on startup - + startēšanas laikā version @@ -3220,7 +3225,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. wallet.dat corrupt, salvage failed - + wallet.dat ir bojāts, glābšana neizdevās Password for JSON-RPC connections @@ -3304,7 +3309,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Unknown -socks proxy version requested: %i - Pieprasīta nezināma -socks proxy versija: %i + Pieprasīta nezināma -socks starpniekservera versija: %i Cannot resolve -bind address: '%s' diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 09ef29d871..1267ad65b9 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -1049,11 +1049,11 @@ Adresse: %4 Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. - + Tredjepart URLer (f. eks. en blokkutforsker) som dukker opp i transaksjonsfanen som kontekst meny elementer. %s i URLen er erstattet med transaksjonen sin hash. Flere URLer er separert av en vertikal linje |. Third party transaction URLs - + Tredjepart transaksjon URLer Active command-line options that override above options: @@ -1358,7 +1358,7 @@ Adresse: %4 Bitcoin Core didn't yet exit safely... - + Bitcoin Core har ennå ikke avsluttet på en sikker måte... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index cbc08dd25d..6bc177076b 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -739,7 +739,7 @@ Adres: %4 none - + żaden Dust @@ -1189,7 +1189,7 @@ Adres: %4 none - + żaden Confirm options reset @@ -2340,7 +2340,7 @@ Adres: %4 Offline - + Offline Unconfirmed @@ -3182,7 +3182,7 @@ na przykład: alertnotify=echo %%s | mail -s "Alarm Bitcoin" admin@foo Start Bitcoin Core Daemon - + Uruchom serwer Bitcoin Core System error: diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index d96e9d9366..bce535fad7 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -16,7 +16,12 @@ This is experimental software. Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. - + +Toto je experimentálny softvér. + +Distribuovaný pod MIT/X11 softvérovou licenciou, viď sprevádzajúci súbor COPYING alebo http://www.opensource.org/licenses/mit-license.php. + +Tento výrobok obsahuje sofvér, ktorý vyvynul OpenSSL Project pre použitie v OpenSSL Toolkit (http://www.openssl.org/) a kryptografický softvér napísaný Ericom Youngom (eay@cryptsoft.com) a UPnP softvér napísaný Thomasom Bernardom. Copyright @@ -28,7 +33,7 @@ This product includes software developed by the OpenSSL Project for use in the O (%1-bit) - + (%1-bit) @@ -209,7 +214,7 @@ This product includes software developed by the OpenSSL Project for use in the O IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. - + DÔLEŽITÉ: Všetky doterajšie záložné kópie peňaženky ktoré ste zhotovili by mali byť nahradené novým zašifrovaným súborom s peňaženkou. Z bezpečnostných dôvodov sa predchádzajúce kópie nezašifrovanej peňaženky stanú neužitočné keď začnete používať novú zašifrovanú peňaženku. Warning: The Caps Lock key is on! @@ -320,11 +325,11 @@ This product includes software developed by the OpenSSL Project for use in the O &Sending addresses... - + Posielajúca adresa ... &Receiving addresses... - + Prijímajúca adresa... Open &URI... @@ -444,7 +449,7 @@ This product includes software developed by the OpenSSL Project for use in the O Open a bitcoin: URI or payment request - + Otvoriť bitcoin URI alebo výzvu k platbe &Command-line options @@ -452,7 +457,7 @@ This product includes software developed by the OpenSSL Project for use in the O Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - + Zobraziť pomocnú správu od Bitcoin Jadra pre získanie zoznamu dostupných možností príkazového riadku Bitcoin client @@ -673,7 +678,7 @@ Adresa: %4 Copy after fee - + Kopírovať za poplatok Copy bytes @@ -685,7 +690,7 @@ Adresa: %4 Copy low output - + Kopírovať malý výstup. Copy change @@ -749,31 +754,31 @@ Adresa: %4 This label turns red, if the transaction size is greater than 1000 bytes. - + Tento popis zčervená ak veľkosť transakcie presiahne 1000 bytov. This means a fee of at least %1 per kB is required. - + To znamená že požadovaný poplatok je aspoň %1 za kB. Can vary +/- 1 byte per input. - + Môže sa pohybovať +/- 1 bajt pre vstup. Transactions with higher priority are more likely to get included into a block. - + Transakcie s vysokou prioritou sa pravdepodobnejsie dostanú do bloku. This label turns red, if the priority is smaller than "medium". - + Tento popis zčervenie ak je priorita nižčia ako "medium". This label turns red, if any recipient receives an amount smaller than %1. - + Tento popis zčervenie ak ktorýkoľvek príjemca dostane sumu menšiu ako %1. This means a fee of at least %1 is required. - + To znamená že je požadovaný poplatok aspoň %1. Amounts below 0.546 times the minimum relay fee are shown as dust. @@ -781,7 +786,7 @@ Adresa: %4 This label turns red, if the change is smaller than %1. - + Tento popis zžervenie ak výdavok je menší než %1. (no label) @@ -910,7 +915,7 @@ Adresa: %4 Set SSL root certificates for payment request (default: -system-) - + Nastaviť koreňový certifikát pre výzvy na platbu (prednastavené: -system-) Show splash screen on startup (default: 1) @@ -918,7 +923,7 @@ Adresa: %4 Choose data directory on startup (default: 0) - + Zvoľte dátový priečinok pri štarte (prednastavené: 0) @@ -933,7 +938,7 @@ Adresa: %4 As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - + Keďže spúštate program prvý krát, môžte si vybrať kde bude Bitcoin Jadro ukladať svoje dáta. Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. @@ -1027,7 +1032,7 @@ Adresa: %4 Number of script &verification threads - + Počet skript overujucich vlákien Connect to the Bitcoin network through a SOCKS proxy. @@ -1051,7 +1056,7 @@ Adresa: %4 Active command-line options that override above options: - + Aktévne možnosti príkazového riadku ktoré prepíšu možnosti vyššie: Reset all client options to default. @@ -1067,7 +1072,7 @@ Adresa: %4 (0 = auto, <0 = leave that many cores free) - + (0 = auto, <0 = nechať toľko jadier voľných) W&allet @@ -1083,11 +1088,11 @@ Adresa: %4 If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. - + Ak vypnete míňanie nepotvrdeného výdavku tak výdavok z transakcie bude možné použiť až keď daná transakcia bude mať aspoň jedno potvrdenie. Toto má vplyv aj na výpočet vášho zostatku. &Spend unconfirmed change - + Minúť nepotvrdený výdavok Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. @@ -1281,7 +1286,7 @@ Adresa: %4 Cannot start bitcoin: click-to-pay handler - + Nedá sa spustiť obslužný program bitcoin: click-to-pay zaplatiť kliknutím Net manager warning @@ -1289,19 +1294,19 @@ Adresa: %4 Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. - + Vaše aktívne proxy nepodporuje SOCKS5, ktoré je potrebné pre vyzvu na zaplatenie cez proxy. Payment request fetch URL is invalid: %1 - + URL pre stiahnutie výzvy na zaplatenie je neplatné: %1 Payment request file handling - + Obsluha súboru s požiadavkou na platbu Payment request file can not be read or processed! This can be caused by an invalid payment request file. - + Súbor s výzvou na zaplatenie sa nedá čítať alebo spracovať! To môže byť spôsobené aj neplatným súborom s výzvou. Unverified payment requests to custom payment scripts are unsupported. @@ -1317,7 +1322,7 @@ Adresa: %4 Payment request can not be parsed or processed! - + Požiadavka na platbu nemôže byť analyzovaná alebo spracovaná! Bad response from server %1 @@ -1344,7 +1349,7 @@ Adresa: %4 Error: Cannot parse configuration file: %1. Only use key=value syntax. - + Chyba: Nedá sa rozlúštit súbor s nastaveniami: %1. Používajte výlučne kľúč=hodnota syntax. Error: Invalid combination of -regtest and -testnet. @@ -1478,7 +1483,7 @@ Adresa: %4 Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. - + Otvoriť Bitcoin log súbor pre ladenie z aktuálneho dátového adresára. Toto môže trvať niekoľko sekúnd pre veľké súbory. Clear console @@ -1541,15 +1546,15 @@ Adresa: %4 Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. - + Znovu použiť jednu z už použitých adries pre prijímanie. Znovu používanie adries je sporná otázka bezpečnosti aj súkromia. Používajte to len v prípade ak znovu generujete výzvu na zaplatenie ktorú ste už vyrobili v minulosti. R&euse an existing receiving address (not recommended) - + Znovu použiť jestvujúcu prijímaciu adresu (neodporúča sa) An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. - + Pridať voliteľnú správu k výzve na zaplatenie, ktorá sa zobrazí keď bude výzva otvorená. Poznámka: Správa nebude poslaná s platbou cez sieť Bitcoin. An optional label to associate with the new receiving address. @@ -1561,7 +1566,7 @@ Adresa: %4 An optional amount to request. Leave this empty or zero to not request a specific amount. - + Voliteľná požadovaná suma. Nechajte prázdne alebo nulu ak nepožadujete určitú sumu. Clear all fields of the form. @@ -1750,7 +1755,7 @@ Adresa: %4 If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - + Ak aktivované ale adresa pre výdavok je prázdna alebo neplatná, výdavok bude poslaný na novovytvorenú adresu. Custom change address @@ -1806,7 +1811,7 @@ Adresa: %4 Copy after fee - + Kopírovať za poplatok Copy bytes @@ -1818,7 +1823,7 @@ Adresa: %4 Copy low output - + Kopírovať nízky výstup Copy change @@ -1858,7 +1863,7 @@ Adresa: %4 The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - + Transakcia bola zamietnutá! Toto sa môže stať ak niektoré coins vo vašej peňaženke už boli minuté, ako keď použijete kópiu wallet.dat a coins boli minuté z kópie ale neoznačené ako minuté tu. Warning: Invalid Bitcoin address @@ -1945,11 +1950,11 @@ Adresa: %4 Enter a label for this address to add it to the list of used addresses - + Vložte popis pre túto adresu aby sa uložila do zoznamu použitých adries A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network. - + Správa ktorá bola pripojená k bitcoin: URI a ktorá bude uložená s transakcou pre Vaše potreby. Poznámka: Táto správa nebude poslaná cez sieť Bitcoin. This is an unverified payment request. @@ -2240,7 +2245,7 @@ Adresa: %4 Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. - + Vytvorené coins musia dospieť %1 blokov kým môžu byť minuté. Keď vytvoríte tento blok, bude rozoslaný do siete aby bol akceptovaný do reťaze blokov. Ak sa nedostane reťaze, jeho stav sa zmení na "zamietnutý" a nebude sa dať minúť. Toto sa môže občas stať ak iná nóda vytvorí blok približne v tom istom čase. Debug information @@ -2272,7 +2277,7 @@ Adresa: %4 Open for %n more block(s) - + Otvoriť pre %n viac blokOtvoriť pre %n viac blokov Otvoriť pre %n viac blokov unknown @@ -2314,7 +2319,7 @@ Adresa: %4 Open for %n more block(s) - + Otvorené pre ešte %1 blokOtvorené pre %n viac blokov Otvorené pre %n blokov Open until %1 @@ -2485,7 +2490,7 @@ Adresa: %4 There was an error trying to save the transaction history to %1. - + Vyskytla sa chyba pri pokuse o uloženie histórie transakcií do %1. Exporting Successful @@ -2679,11 +2684,21 @@ If the file does not exist, create it with owner-readable-only file permissions. It is also recommended to set alertnotify so you are notified of problems; for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com - + %s, musíte nastaviť rpcpassword heslo v súbore nastavení: +%s +Odporúča sa používať nasledujúce náhodné heslo: +rpcuser=bitcoinrpc +rpcpassword=%s +(nemusíte si pamätať toto heslo) +Užívateľské meno a heslo NESMÚ byť rovnaké. +Ak súbor neexistuje, vytvorte ho s prístupovým právom owner-readable-only čitateľné len pre majiteľa. +Tiež sa odporúča nastaviť alertnotify aby ste boli upozorňovaní na problémy; +napríklad: alertnotify=echo %%s | mail -s "Bitcoin Výstraha" admin@foo.com + Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH) - + Prijateľlné šifry (prednastavené: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH) An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s @@ -2695,7 +2710,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15) - + Priebežne obmedzuj transakcie bez poplatku na <n>*1000 bajtov za minútu (prednastavené: 15) Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development. @@ -2703,19 +2718,19 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Enter regression test mode, which uses a special chain in which blocks can be solved instantly. - + Vojsť do režimu regresného testovania, ktorý používa špeciálnu reťaz v ktorej môžu byť bloky v okamihu vyriešené. Error: Listening for incoming connections failed (listen returned error %d) - + Chyba: Zlyhalo počúvanie prichádzajúcich spojení (listen vrátil chybu %d) Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - + Transakcia bola zamietnutá! Toto sa môže stať ak niektoré coins vo vašej peňaženke už boli minuté, ako keď použijete kópiu wallet.dat a coins boli minuté z kópie ale neoznačené ako minuté tu. Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! - + Chyba: Táto transakcia vyžaduje transakčný poplatok aspoň %s kvôli svojej sume, komplexite alebo použitiu nedávno prijatých prostriedkov. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) @@ -2723,39 +2738,39 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Fees smaller than this are considered zero fee (for transaction creation) (default: - + Poplatky menšie než toto sa považujú za nulové (pre vytvorenie transakcie) (prednastavené: Flush database activity from memory pool to disk log every <n> megabytes (default: 100) - + Odložiť aktivitu databázy spoločnej pamäti do logu na disku každých <n> megabajtov (prednastavené: 100) How thorough the block verification of -checkblocks is (0-4, default: 3) - + Ako dôkladne sú overované bloky -checkblocks (0-4, prednastavené: 3) In this mode -genproclimit controls how many blocks are generated immediately. - + V tomto režime -getproclimit kontroluje koľko blokov sa vytvorí okamžite. Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) - + Nastaviť počeť vlákien overujúcich skripty (%u až %d, 0 = auto, <0 = nechať toľkoto jadier voľných, prednastavené: %d) Set the processor limit for when generation is on (-1 = unlimited, default: -1) - + Nastaviť obmedzenie pre procesor keď je zapnuté generovanie (-1 = bez obmedzenia, prednastavené: -1) This is a pre-release test build - use at your own risk - do not use for mining or merchant applications - + Toto je pred-testovacia verzia - použitie je na vlastné riziko - nepoužívajte na tvorbu bitcoin ani obchodovanie. Unable to bind to %s on this computer. Bitcoin Core is probably already running. - + Nepodarilo sa pripojiť na %s na tomto počítači. Bitcoin Jadro je už pravdepodobne spustené. Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy) - + Použite rozdielne SOCKS5 proxy pre dosiahnutie peer-ov cez Tor skryté služby (prednastavené: -proxy) Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. @@ -2763,15 +2778,17 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly. - + Varovanie: Skontroluj či je na počítači nastavený správny čas a dátum. Ak sú hodiny nastavené nesprávne, Bitcoin nebude správne pracovať. Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - + Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti. + +The network does not appear to fully agree! Some miners appear to be experiencing issues. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. - + Varovanie: Zjavne sa úplne nezhodujeme s našimi peer-mi! Možno potrebujete prejsť na novšiu verziu alebo ostatné nódy potrebujú vyššiu verziu. Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. @@ -2779,7 +2796,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - + Varovanie: wallet.dat je poškodený, údaje úspešne získané! Pôvodný wallet.dat uložený ako wallet.{timestamp}.bak v %s; ak váš zostatok alebo transakcie niesu správne, mali by ste súbor obnoviť zo zálohy. (default: 1) @@ -2799,7 +2816,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Bitcoin Core Daemon - + Démon Jadro Bitcoin Block creation options: @@ -2807,7 +2824,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Clear list of wallet transactions (diagnostic tool; implies -rescan) - + Vyčistiť zoznam transakcií peňaženky (diagnostický nástroj; zahŕňa -rescan) Connect only to the specified node(s) @@ -2819,7 +2836,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) - + Pripojiť ku JSON-RPC na <port> (prednastavené: 8332 alebo testnet: 18332) Connection options: @@ -2835,7 +2852,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Disable safemode, override a real safe mode event (default: 0) - + Vypnúť bezpečný režim, vypnúť udalosť skutočný bezpečný režim (prednastavené: 0) Discover own IP address (default: 1 when listening and no -externalip) @@ -2843,7 +2860,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Do not load the wallet and disable wallet RPC calls - + Nenahrat peňaženku a zablokovať volania RPC. Do you want to rebuild the block database now? @@ -2907,11 +2924,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Failed to write file info - + Zlyhalo zapisovanie informácié o súbore Failed to write to coin database - + Zlyhalo zapisovanie do databázy coins Failed to write transaction index @@ -2927,7 +2944,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Fees smaller than this are considered zero fee (for relaying) (default: - + Poplatky menšie než toto sa považujú za nulové (pre preposielanie) (prednastavené: Find peers using DNS lookup (default: 1 unless -connect) @@ -2935,7 +2952,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Force safe mode (default: 0) - + Vnútiť bezpečný režim (prenastavené: 0) Generate coins (default: 0) @@ -2947,7 +2964,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. If <category> is not supplied, output all debugging information. - + Ak nie je uvedená <category>, na výstupe zobrazuj všetky informácie pre ladenie. Importing... @@ -2967,7 +2984,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Prepend debug output with timestamp (default: 1) - + Na začiatok logu pre ladenie vlož dátum a čas (prednastavené: 1) RPC client options: @@ -2983,7 +3000,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set database cache size in megabytes (%d to %d, default: %d) - + Nastaviť veľkosť pomocnej pamäti databázy v megabajtoch (%d na %d, prednatavené: %d) Set maximum block size in bytes (default: %d) @@ -2999,11 +3016,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Spend unconfirmed change when sending transactions (default: 1) - + Míňať nepotvrdený výdavok pri odosielaní (prednastavené: 1) This is intended for regression testing tools and app development. - + Toto je mienené nástrojom pre regresné testovania a vývoj programu. Usage (deprecated, use bitcoin-cli): @@ -3031,7 +3048,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Warning: Deprecated argument -debugnet ignored, use -debug=net - + Varovanie: Zastaralý parameter -debugnet bol ignorovaný, použite -debug=net You need to rebuild the database using -reindex to change -txindex @@ -3047,15 +3064,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) - + Vykonať príkaz keď po prijatí patričné varovanie alebo vidíme veľmi dlhé rozdvojenie siete (%s v cmd je nahradené správou) Output debugging information (default: 0, supplying <category> is optional) - + Výstup informácií pre ladenie (prednastavené: 0, uvádzanie <category> je voliteľné) Set maximum size of high-priority/low-fee transactions in bytes (default: %d) - + Nastaviť najväčšiu veľkosť vysoká-dôležitosť/nízke-poplatky transakcií v bajtoch (prednastavené: %d) Information @@ -3071,15 +3088,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Limit size of signature cache to <n> entries (default: 50000) - + Obmedziť veľkosť pomocnej pamäti pre podpisy na <n> vstupov (prednastavené: 50000) Log transaction priority and fee per kB when mining blocks (default: 0) - + Zaznamenávať dôležitosť transakcií a poplatky za kB ak hľadáme bloky (prednastavené: 0) Maintain a full transaction index (default: 0) - + Udržiavaj úplný zoznam transakcií (prednastavené: 0) Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) @@ -3087,11 +3104,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) - + Maximálna veľkosť vysielacieho zásobníka pre jedno spojenie, <n>*1000 bytov (predvolené: 1000) Only accept block chain matching built-in checkpoints (default: 1) - + Akceptuj iba kontrolné body zhodné s blockchain (prednastavené: 1) Only connect to nodes in network <net> (IPv4, IPv6 or Tor) @@ -3099,15 +3116,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Print block on startup, if found in block index - + Vytlač blok pri spustení, ak nájdený v zozname blokov Print block tree on startup (default: 0) - + Vytlačiť strom blokov pri spustení (prednastavené: 0) RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) - + Možnosti RPC SSL: (Pozri v Bitcoin Wiki pokyny pre SSL nastavenie) RPC server options: @@ -3119,7 +3136,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Randomly fuzz 1 of every <n> network messages - + Náhodne premiešaj 1 z každých <n> sieťových správ Run a thread to flush wallet periodically (default: 1) @@ -3207,7 +3224,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Zapping all transactions from wallet... - + Zmazať všetky transakcie z peňaženky... on startup From 79d06dc6e07103b31b530f71b7187ea82c34266b Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Wed, 21 May 2014 18:50:46 +0800 Subject: [PATCH 077/336] Remove redundant c_str --- src/addrman.h | 4 ++-- src/init.cpp | 2 +- src/leveldbwrapper.h | 4 ++-- src/main.h | 12 ++++++------ src/net.h | 2 +- src/script.h | 2 +- src/wallet.h | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index e2b0cb1093..5328a93b45 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -420,7 +420,7 @@ public: Check(); } if (fRet) - LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew); + LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString(), nTried, nNew); return fRet; } @@ -436,7 +436,7 @@ public: Check(); } if (nAdd) - LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew); + LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew); return nAdd > 0; } diff --git a/src/init.cpp b/src/init.cpp index 7664988762..bc4924b48d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -914,7 +914,7 @@ bool AppInit2(boost::thread_group& threadGroup) for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) { uint256 hash = (*mi).first; - if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) + if (boost::algorithm::starts_with(hash.ToString(), strMatch)) { CBlockIndex* pindex = (*mi).second; CBlock block; diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h index 53e9e439bd..043a56bf38 100644 --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -93,7 +93,7 @@ public: if (!status.ok()) { if (status.IsNotFound()) return false; - LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str()); + LogPrintf("LevelDB read failure: %s\n", status.ToString()); HandleError(status); } try { @@ -122,7 +122,7 @@ public: if (!status.ok()) { if (status.IsNotFound()) return false; - LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str()); + LogPrintf("LevelDB read failure: %s\n", status.ToString()); HandleError(status); } return true; diff --git a/src/main.h b/src/main.h index f47c9ee825..1dc48c0af8 100644 --- a/src/main.h +++ b/src/main.h @@ -862,13 +862,13 @@ public: { return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", pprev, nHeight, - hashMerkleRoot.ToString().c_str(), - GetBlockHash().ToString().c_str()); + hashMerkleRoot.ToString(), + GetBlockHash().ToString()); } void print() const { - LogPrintf("%s\n", ToString().c_str()); + LogPrintf("%s\n", ToString()); } // Check whether this block index entry is valid up to the passed validity level. @@ -953,14 +953,14 @@ public: std::string str = "CDiskBlockIndex("; str += CBlockIndex::ToString(); str += strprintf("\n hashBlock=%s, hashPrev=%s)", - GetBlockHash().ToString().c_str(), - hashPrev.ToString().c_str()); + GetBlockHash().ToString(), + hashPrev.ToString()); return str; } void print() const { - LogPrintf("%s\n", ToString().c_str()); + LogPrintf("%s\n", ToString()); } }; diff --git a/src/net.h b/src/net.h index 729b1bcd57..58a8fa739b 100644 --- a/src/net.h +++ b/src/net.h @@ -430,7 +430,7 @@ public: nRequestTime = it->second; else nRequestTime = 0; - LogPrint("net", "askfor %s %d (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); + LogPrint("net", "askfor %s %d (%s)\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); // Make sure not to reuse time indexes to keep things in the same order int64_t nNow = GetTimeMicros() - 1000000; diff --git a/src/script.h b/src/script.h index 0d8a8544bd..aed2b7a6ad 100644 --- a/src/script.h +++ b/src/script.h @@ -722,7 +722,7 @@ public: void print() const { - LogPrintf("%s\n", ToString().c_str()); + LogPrintf("%s\n", ToString()); } CScriptID GetID() const diff --git a/src/wallet.h b/src/wallet.h index b2c06d3f61..81dfbba9cb 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -720,12 +720,12 @@ public: std::string ToString() const { - return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString().c_str(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str()); + return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str()); } void print() const { - LogPrintf("%s\n", ToString().c_str()); + LogPrintf("%s\n", ToString()); } }; From a48355dc44e8b86c2fc9f8b7973ac9e81a295be7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 May 2014 13:05:04 +0200 Subject: [PATCH 078/336] Remove forward declaration for non-existent class CCoinsDB Found by stephenreed on #bitcoin.dev. --- src/main.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.h b/src/main.h index f47c9ee825..6f39b6e89d 100644 --- a/src/main.h +++ b/src/main.h @@ -102,7 +102,6 @@ extern unsigned int nCoinCacheSize; static const uint64_t nMinDiskSpace = 52428800; -class CCoinsDB; class CBlockTreeDB; struct CDiskBlockPos; class CTxUndo; From d90491a766e7ab5e9cc0a6207fe8ad88a803dfb1 Mon Sep 17 00:00:00 2001 From: LongShao007 <007longshao@gmail.com> Date: Thu, 22 May 2014 21:41:59 +0800 Subject: [PATCH 079/336] Update test_main.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i think should delete (#include "bitcoin-config.h")。 --- src/qt/test/test_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index a2adb00327..220da28cfe 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,4 +1,3 @@ -#include "bitcoin-config.h" #if defined(HAVE_CONFIG_H) #include "bitcoin-config.h" #endif From a60838d09aed4d976e9343e8329d61afff204435 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 May 2014 14:15:19 +0200 Subject: [PATCH 080/336] Replace non-threadsafe strerror Log the name of the error as well as the error code if a network problem happens. This makes network troubleshooting more convenient. Use thread-safe strerror_r and the WIN32 equivalent FormatMessage. --- configure.ac | 2 ++ src/net.cpp | 24 ++++++++++++------------ src/netbase.cpp | 41 +++++++++++++++++++++++++++++++++++++---- src/netbase.h | 2 ++ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 6a8afe6e44..3a8d33a5a0 100644 --- a/configure.ac +++ b/configure.ac @@ -303,6 +303,8 @@ INCLUDES="$INCLUDES $PTHREAD_CFLAGS" # they also need to be passed down to any subprojects. Pull the results out of # the cache and add them to CPPFLAGS. AC_SYS_LARGEFILE +# detect POSIX or GNU variant of strerror_r +AC_FUNC_STRERROR_R if test x$ac_cv_sys_file_offset_bits != x && test x$ac_cv_sys_file_offset_bits != xno && diff --git a/src/net.cpp b/src/net.cpp index 6bde1e7999..4cbd26a563 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -178,7 +178,7 @@ bool RecvLine(SOCKET hSocket, string& strLine) { // socket error int nErr = WSAGetLastError(); - LogPrint("net", "recv failed: %d\n", nErr); + LogPrint("net", "recv failed: %s\n", NetworkErrorString(nErr)); return false; } } @@ -489,10 +489,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) #ifdef WIN32 u_long nOne = 1; if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) - LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError()); + LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError())); #else if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) - LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno); + LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno)); #endif // Add node @@ -736,7 +736,7 @@ void SocketSendData(CNode *pnode) int nErr = WSAGetLastError(); if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) { - LogPrintf("socket send error %d\n", nErr); + LogPrintf("socket send error %s\n", NetworkErrorString(nErr)); pnode->CloseSocketDisconnect(); } } @@ -896,7 +896,7 @@ void ThreadSocketHandler() if (have_fds) { int nErr = WSAGetLastError(); - LogPrintf("socket select error %d\n", nErr); + LogPrintf("socket select error %s\n", NetworkErrorString(nErr)); for (unsigned int i = 0; i <= hSocketMax; i++) FD_SET(i, &fdsetRecv); } @@ -933,7 +933,7 @@ void ThreadSocketHandler() { int nErr = WSAGetLastError(); if (nErr != WSAEWOULDBLOCK) - LogPrintf("socket error accept failed: %d\n", nErr); + LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); } else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS) { @@ -1007,7 +1007,7 @@ void ThreadSocketHandler() if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) { if (!pnode->fDisconnect) - LogPrintf("socket recv error %d\n", nErr); + LogPrintf("socket recv error %s\n", NetworkErrorString(nErr)); pnode->CloseSocketDisconnect(); } } @@ -1585,7 +1585,7 @@ bool BindListenPort(const CService &addrBind, string& strError) SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); if (hListenSocket == INVALID_SOCKET) { - strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError()); + strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } @@ -1609,7 +1609,7 @@ bool BindListenPort(const CService &addrBind, string& strError) if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) #endif { - strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError()); + strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } @@ -1638,7 +1638,7 @@ bool BindListenPort(const CService &addrBind, string& strError) if (nErr == WSAEADDRINUSE) strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin Core is probably already running."), addrBind.ToString()); else - strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString(), nErr, strerror(nErr)); + strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr)); LogPrintf("%s\n", strError); return false; } @@ -1647,7 +1647,7 @@ bool BindListenPort(const CService &addrBind, string& strError) // Listen for incoming connections if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) { - strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %d)"), WSAGetLastError()); + strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError())); LogPrintf("%s\n", strError); return false; } @@ -1785,7 +1785,7 @@ public: BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) if (hListenSocket != INVALID_SOCKET) if (closesocket(hListenSocket) == SOCKET_ERROR) - LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); + LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); // clean up some globals (to help leak detection) BOOST_FOREACH(CNode *pnode, vNodes) diff --git a/src/netbase.cpp b/src/netbase.cpp index 82a681281d..e24a0a195c 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -361,7 +361,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe } if (nRet == SOCKET_ERROR) { - LogPrintf("select() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError()); + LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); closesocket(hSocket); return false; } @@ -372,13 +372,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR) #endif { - LogPrintf("getsockopt() for %s failed: %i\n", addrConnect.ToString(), WSAGetLastError()); + LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); closesocket(hSocket); return false; } if (nRet != 0) { - LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), strerror(nRet)); + LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet)); closesocket(hSocket); return false; } @@ -389,7 +389,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe else #endif { - LogPrintf("connect() to %s failed: %i\n", addrConnect.ToString(), WSAGetLastError()); + LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError())); closesocket(hSocket); return false; } @@ -1237,3 +1237,36 @@ bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a==b); } + +#ifdef WIN32 +std::string NetworkErrorString(int err) +{ + char buf[256]; + buf[0] = 0; + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buf, sizeof(buf), NULL)) + { + return strprintf("%s (%d)", buf, err); + } + else + { + return strprintf("Unknown error (%d)", err); + } +} +#else +std::string NetworkErrorString(int err) +{ + char buf[256]; + const char *s = buf; + buf[0] = 0; + /* Too bad there are two incompatible implementations of the + * thread-safe strerror. */ +#ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */ + s = strerror_r(err, buf, sizeof(buf)); +#else /* POSIX variant always returns message in buffer */ + (void) strerror_r(err, buf, sizeof(buf)); +#endif + return strprintf("%s (%d)", s, err); +} +#endif diff --git a/src/netbase.h b/src/netbase.h index 118f866d6c..5fd8be4aca 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -179,5 +179,7 @@ bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); +/** Return readable error string for a network error code */ +std::string NetworkErrorString(int err); #endif From 4665b1ab6f45bd35e3ffe2434395c81e5acbb91b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 23 May 2014 09:49:01 +0200 Subject: [PATCH 081/336] doc: Clarify wording about testing in README.md Weaken and clarify the wording a bit, it currently implies that we get more pull requests than we can ever handle which discourages contribution. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e9ec25980..ddeaf988ee 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ Testing ------- Testing and code review is the bottleneck for development; we get more pull -requests than we can review and test. Please be patient and help out, and -remember this is a security-critical project where any mistake might cost people +requests than we can review and test on short notice. Please be patient and help out by testing +other people's pull requests, and remember this is a security-critical project where any mistake might cost people lots of money. ### Automated Testing From 3e8ac6af9a993e262d1160fb2e6e1e1f1d5d19f2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 May 2014 18:01:10 +0200 Subject: [PATCH 082/336] Replace non-threadsafe gmtime and setlocale Make DateTimeStrFormat use boost::posix_time. Also re-enable the util_DateTimeStrFormat tests, as they are no longer platform specific. --- src/rpcprotocol.cpp | 10 +--------- src/test/util_tests.cpp | 4 +--- src/util.cpp | 12 ++++++++++++ src/util.h | 9 +-------- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 5cbaa535ab..2718f81783 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -51,15 +51,7 @@ string HTTPPost(const string& strMsg, const map& mapRequestHeader static string rfc1123Time() { - char buffer[64]; - time_t now; - time(&now); - struct tm* now_gmt = gmtime(&now); - string locale(setlocale(LC_TIME, NULL)); - setlocale(LC_TIME, "C"); // we want POSIX (aka "C") weekday/month strings - strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt); - setlocale(LC_TIME, locale.c_str()); - return string(buffer); + return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime()); } string HTTPReply(int nStatus, const string& strMsg, bool keepalive) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 3811569c0a..0e53a57593 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -108,13 +108,11 @@ BOOST_AUTO_TEST_CASE(util_HexStr) BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat) { -/*These are platform-dependant and thus removed to avoid useless test failures BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0), "1970-01-01 00:00:00"); BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 0x7FFFFFFF), "2038-01-19 03:14:07"); - // Formats used within Bitcoin BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", 1317425777), "2011-09-30 23:36:17"); BOOST_CHECK_EQUAL(DateTimeStrFormat("%Y-%m-%d %H:%M", 1317425777), "2011-09-30 23:36"); -*/ + BOOST_CHECK_EQUAL(DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", 1317425777), "Fri, 30 Sep 2011 23:36:17 +0000"); } BOOST_AUTO_TEST_CASE(util_ParseParameters) diff --git a/src/util.cpp b/src/util.cpp index aa3adf89ec..f7ceb3e95c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -14,6 +14,8 @@ #include +#include + #ifndef WIN32 // for posix_fallocate #ifdef __linux_ @@ -1400,3 +1402,13 @@ void SetupEnvironment() } #endif } + +std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) +{ + // std::locale takes ownership of the pointer + std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat)); + std::stringstream ss; + ss.imbue(loc); + ss << boost::posix_time::from_time_t(nTime); + return ss.str(); +} diff --git a/src/util.h b/src/util.h index 97185073e0..9e899b5084 100644 --- a/src/util.h +++ b/src/util.h @@ -325,14 +325,7 @@ inline int64_t GetTimeMicros() boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds(); } -inline std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) -{ - time_t n = nTime; - struct tm* ptmTime = gmtime(&n); - char pszTime[200]; - strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime); - return pszTime; -} +std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime); inline bool IsSwitchChar(char c) { From c47f5379bd25195d1e08638294f9ffbb5b1df0a8 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Fri, 23 May 2014 10:30:38 -0400 Subject: [PATCH 083/336] Add Tips and Tricks section to README --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index 3e9ec25980..98edf87ee0 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,38 @@ Periodically the translations are pulled from Transifex and merged into the git **Important**: We do not accept translation changes as github pull request because the next pull from Transifex would automatically overwrite them again. + +Development tips and tricks +--------------------------- + +**compiling for debugging** + +Run configure with the --enable-debug option, then make. Or run configure with +CXXFLAGS="-g -ggdb -O0" or whatever debug flags you need. + +**debug.log** + +If the code is behaving strangely, take a look in the debug.log file in the data directory; +error and debugging message are written there. + +The -debug=... command-line option controls debugging; running with just -debug will turn +on all categories (and give you a very large debug.log file). + +The Qt code routes qDebug() output to debug.log under category "qt": run with -debug=qt +to see it. + +**testnet and regtest modes** + +Run with the -testnet option to run with "play bitcoins" on the test network, if you +are testing multi-machine code that needs to operate across the internet. + +If you are testing something that can run on one machine, run with the -regtest option. +In regression test mode blocks can be created on-demand; see qa/rpc-tests/ for tests +that run in -regest mode. + +**DEBUG_LOCKORDER** + +Bitcoin Core is a multithreaded application, and deadlocks or other multithreading bugs +can be very difficult to track down. Compiling with -DDEBUG_LOCKORDER (configure +CXXFLAGS="-DDEBUG_LOCKORDER -g") inserts run-time checks to keep track of what locks +are held, and adds warning to the debug.log file if inconsistencies are detected. From a8a0db6f210c879396417d4eace8b188ca9a199a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 23 May 2014 17:54:57 +0200 Subject: [PATCH 084/336] qt: Periodic language update Last-minute language update before release 0.9.2. --- src/qt/locale/bitcoin_da.ts | 166 ++++++++++++++++----------------- src/qt/locale/bitcoin_id_ID.ts | 72 +++++++------- src/qt/locale/bitcoin_ko_KR.ts | 74 +++++++-------- src/qt/locale/bitcoin_ro_RO.ts | 6 +- 4 files changed, 159 insertions(+), 159 deletions(-) diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 5795701497..b13b38a878 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -25,7 +25,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Copyright - Copyright + Ophavsret The Bitcoin Core developers @@ -76,7 +76,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Export - Eksporter + Eksportér &Delete @@ -214,7 +214,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet. - VIGTIGT: Enhver tidligere sikkerhedskopi, som du har lavet af tegnebogsfilen, bør blive erstattet af den nyligt genererede, krypterede tegnebogsfil. Af sikkerhedsmæssige årsager vil tidligere sikkerhedskopier af den ikke-krypterede tegnebogsfil blive ubrugelig i det øjeblik, du starter med at anvende den nye, krypterede tegnebog. + VIGTIGT: Enhver tidligere sikkerhedskopi, som du har lavet af tegnebogsfilen, bør blive erstattet af den nyligt genererede, krypterede tegnebogsfil. Af sikkerhedsmæssige årsager vil tidligere sikkerhedskopier af den ikke-krypterede tegnebogsfil blive ubrugelige i det øjeblik, du starter med at anvende den nye, krypterede tegnebog. Warning: The Caps Lock key is on! @@ -337,11 +337,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Importing blocks from disk... - Importerer blokke fra disken... + Importerer blokke fra disken … Reindexing blocks on disk... - Genindekserer blokke på disken... + Genindekserer blokke på disken … Send coins to a Bitcoin address @@ -397,7 +397,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Encrypt the private keys that belong to your wallet - Krypter de private nøgler, der hører til din tegnebog + Kryptér de private nøgler, der hører til din tegnebog Sign messages with your Bitcoin addresses to prove you own them @@ -405,7 +405,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Verify messages to ensure they were signed with specified Bitcoin addresses - Verificér beskeder for at sikre, at de er underskrevet med de(n) angivne Bitcoin-adresse(r) + Verificér beskeder for at sikre, at de er underskrevet med de angivne Bitcoin-adresser &File @@ -469,7 +469,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open No block source available... - Ingen blokkilde tilgængelig... + Ingen blokkilde tilgængelig … Processed %1 of %2 (estimated) blocks of transaction history. @@ -861,7 +861,7 @@ Adresse: %4 FreespaceChecker A new data directory will be created. - + En ny datamappe vil blive oprettet. name @@ -869,15 +869,15 @@ Adresse: %4 Directory already exists. Add %1 if you intend to create a new directory here. - + Mappe eksisterer allerede. Tilføj %1, hvis du vil oprette en ny mappe her. Path already exists, and is not a directory. - + Sti eksisterer allerede og er ikke en mappe. Cannot create data directory here. - + Kan ikke oprette en mappe her. @@ -947,11 +947,11 @@ Adresse: %4 Use the default data directory - + Brug standardmappen for data Use a custom data directory: - + Brug tilpasset mappe for data: Bitcoin @@ -967,11 +967,11 @@ Adresse: %4 GB of free space available - + GB fri plads tilgængelig (of %1GB needed) - + (ud af %1 GB behøvet) @@ -1133,15 +1133,15 @@ Adresse: %4 &Minimize to the tray instead of the taskbar - Minimer til statusfeltet i stedet for proceslinjen + Minimér til statusfeltet i stedet for proceslinjen Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu. - Minimer i stedet for at afslutte programmet, når vinduet lukkes. Når denne indstilling er valgt, vil programmet kun blive lukket, når du har valgt Afslut i menuen. + Minimér i stedet for at afslutte programmet, når vinduet lukkes. Når denne indstilling er valgt, vil programmet kun blive lukket, når du har valgt Afslut i menuen. M&inimize on close - Minimer ved lukning + Minimér ved lukning &Display @@ -1149,11 +1149,11 @@ Adresse: %4 User Interface &language: - Brugergrænsefladesprog: + Sprog for brugergrænseflade: The user interface language can be set here. This setting will take effect after restarting Bitcoin. - Brugergrænsefladesproget kan angives her. Denne indstilling træder først i kraft, når Bitcoin genstartes. + Sproget for brugergrænsefladen kan angives her. Denne indstilling træder først i kraft, når Bitcoin genstartes. &Unit to show amounts in: @@ -1161,7 +1161,7 @@ Adresse: %4 Choose the default subdivision unit to show in the interface and when sending coins. - Vælg den standard underopdelingsenhed, som skal vises i brugergrænsefladen og ved afsendelse af bitcoins. + Vælg standard for underopdeling af enhed, som skal vises i brugergrænsefladen og ved afsendelse af bitcoins. Whether to show Bitcoin addresses in the transaction list or not. @@ -1181,7 +1181,7 @@ Adresse: %4 &Cancel - Annuller + Annullér default @@ -1209,7 +1209,7 @@ Adresse: %4 The supplied proxy address is invalid. - Ugyldig proxy-adresse + Den angivne proxy-adresse er ugyldig. @@ -1240,7 +1240,7 @@ Adresse: %4 Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance - Total transaktioner, som ikke er blevet bekræftet endnu, og som ikke endnu er en del af den nuværende saldo + Total saldo for transaktioner, som ikke er blevet bekræftet endnu, og som ikke endnu er en del af den tilgængelige saldo Immature: @@ -1283,7 +1283,7 @@ Adresse: %4 Payment request error - Fejl i betalingsforespørgelse + Fejl i betalingsforespørgsel Cannot start bitcoin: click-to-pay handler @@ -1335,7 +1335,7 @@ Adresse: %4 Network request error - + Fejl i netværksforespørgsel @@ -1346,7 +1346,7 @@ Adresse: %4 Error: Specified data directory "%1" does not exist. - + Fejl: Angivet datamappe "%1" eksisterer ikke. Error: Cannot parse configuration file: %1. Only use key=value syntax. @@ -1354,7 +1354,7 @@ Adresse: %4 Error: Invalid combination of -regtest and -testnet. - + Fejl: Ugyldig kombination af -regtest og -testnet. Bitcoin Core didn't yet exit safely... @@ -1362,7 +1362,7 @@ Adresse: %4 Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Indtast en Bitcoin-adresse (f.eks. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + Indtast en Bitcoin-adresse (fx 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1484,7 +1484,7 @@ Adresse: %4 Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. - Åbn Bitcoin-fejlsøgningslogfilen fra det nuværende datakatalog. Dette kan tage nogle få sekunder for en store logfiler. + Åbn Bitcoin-fejlsøgningslogfilen fra den nuværende datamappe. Dette kan tage nogle få sekunder for store logfiler. Clear console @@ -1880,7 +1880,7 @@ Adresse: %4 Are you sure you want to send? - Er du sikker på at du vil sende? + Er du sikker på, at du vil sende? added as transaction fee @@ -1888,7 +1888,7 @@ Adresse: %4 Payment request expired - Betalingsforespørgsel udløb + Betalingsforespørgsel udløbet Invalid payment address %1 @@ -1907,7 +1907,7 @@ Adresse: %4 The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Bitcoin-adressen som betalingen skal sendes til (f.eks. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + Bitcoin-adressen som betalingen skal sendes til (fx 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Enter a label for this address to add it to your address book @@ -1997,7 +1997,7 @@ Adresse: %4 The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Bitcoin-adressen som beskeden skal underskrives med (f.eks. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + Bitcoin-adressen som beskeden skal underskrives med (fx 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Choose previously used address @@ -2017,7 +2017,7 @@ Adresse: %4 Enter the message you want to sign here - Indtast beskeden, du ønsker at underskrive + Indtast her beskeden, du ønsker at underskrive Signature @@ -2025,7 +2025,7 @@ Adresse: %4 Copy the current signature to the system clipboard - Kopier den nuværende underskrift til systemets udklipsholder + Kopiér den nuværende underskrift til systemets udklipsholder Sign the message to prove you own this Bitcoin address @@ -2049,11 +2049,11 @@ Adresse: %4 Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. - Indtast den underskrevne adresse, beskeden (inkluder linjeskift, mellemrum mv. nøjagtigt, som de fremgår) og underskriften for at verificére beskeden. Vær forsigtig med ikke at lægge mere i underskriften end besked selv, så du undgår at blive narret af et man-in-the-middle-angreb. + Indtast herunder den underskrivende adresse, beskeden (inkludér linjeskift, mellemrum mv. nøjagtigt, som de fremgår) og underskriften for at verificere beskeden. Vær forsigtig med ikke at lægge mere i underskriften end besked selv, så du undgår at blive narret af et man-in-the-middle-angreb. The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Bitcoin-adressen som beskeden er underskrevet med (f.eks. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + Bitcoin-adressen som beskeden er underskrevet med (fx 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Verify the message to ensure it was signed with the specified Bitcoin address @@ -2069,7 +2069,7 @@ Adresse: %4 Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) - Indtast en Bitcoin-adresse (f.eks. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + Indtast en Bitcoin-adresse (fx 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) Click "Sign Message" to generate signature @@ -2081,7 +2081,7 @@ Adresse: %4 Please check the address and try again. - Tjek venligst adressen, og forsøg igen. + Tjek venligst adressen og forsøg igen. The entered address does not refer to a key. @@ -2117,11 +2117,11 @@ Adresse: %4 Message verification failed. - Verificéring af besked mislykkedes. + Verificering af besked mislykkedes. Message verified. - Besked verificéret. + Besked verificeret. @@ -2136,7 +2136,7 @@ Adresse: %4 [testnet] - [testnet] + [testnetværk] @@ -2174,7 +2174,7 @@ Adresse: %4 , broadcast through %n node(s) - , transmitteret igennem %n knude(r), transmitteret igennem %n knude(r) + , transmitteret igennem %n knude, transmitteret igennem %n knuder Date @@ -2210,7 +2210,7 @@ Adresse: %4 matures in %n more block(s) - modner efter yderligere %n blok(ke)modner efter yderligere %n blok(ke) + modner efter yderligere %n blokmodner efter yderligere %n blokke not accepted @@ -2238,7 +2238,7 @@ Adresse: %4 Transaction ID - Transaktionens ID + Transaktions-ID Merchant @@ -2471,7 +2471,7 @@ Adresse: %4 Copy transaction ID - Kopier transaktionens ID + Kopiér transaktions-ID Edit label @@ -2560,7 +2560,7 @@ Adresse: %4 WalletView &Export - Eksporter + Eksportér Export the data in the current tab to a file @@ -2568,7 +2568,7 @@ Adresse: %4 Backup Wallet - Sikkerhedskopier tegnebog + Sikkerhedskopiér tegnebog Wallet Data (*.dat) @@ -2576,7 +2576,7 @@ Adresse: %4 Backup Failed - Foretagelse af sikkerhedskopi fejlede + Sikkerhedskopiering mislykkedes There was an error trying to save the wallet data to %1. @@ -2588,7 +2588,7 @@ Adresse: %4 Backup Successful - Sikkerhedskopieret problemfri + Sikkerhedskopiering problemfri @@ -2619,7 +2619,7 @@ Adresse: %4 Specify data directory - Angiv datakatalog + Angiv datamappe Listen for connections on <port> (default: 8333 or testnet: 18333) @@ -2671,7 +2671,7 @@ Adresse: %4 Accept connections from outside (default: 1 if no -proxy or -connect) - Accepter forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect) + Acceptér forbindelser udefra (standard: 1 hvis hverken -proxy eller -connect) %s, you must set a rpcpassword in the configuration file: @@ -2694,7 +2694,7 @@ rpcpassword=%s Brugernavnet og adgangskode MÅ IKKE være det samme. Hvis filen ikke eksisterer, opret den og giv ingen andre end ejeren læserettighed. Det anbefales også at angive alertnotify, så du påmindes om problemer; -f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com +fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com @@ -2731,7 +2731,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! - Fejl: Denne transaktion kræver et transaktionsgebyr på minimum %s pga. dens størrelse, kompleksitet eller anvendelse af nyligt modtagne bitcoins! + Fejl: Denne transaktion kræver et transaktionsgebyr på minimum %s pga. dens beløb, kompleksitet eller anvendelse af nyligt modtagne bitcoins! Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) @@ -2783,11 +2783,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues. - + Advarsel: Netværket ser ikke ud til at være fuldt ud enige! Enkelte minere ser ud til at opleve problemer. Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade. - + Advarsel: Vi ser ikke ud til at være fuldt ud enige med andre noder! Du kan være nødt til at opgradere, eller andre noder kan være nødt til at opgradere. Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect. @@ -2795,7 +2795,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup. - Advarsel: wallet.dat ødelagt, data reddet! Oprindelig wallet.net gemt som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi. + Advarsel: wallet.dat ødelagt, data reddet! Oprindelig wallet.dat gemt som wallet.{timestamp}.bak i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi. (default: 1) @@ -2947,7 +2947,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Find peers using DNS lookup (default: 1 unless -connect) - Find ligeværdige ved DNS-opslag (standard: 1 hvis ikke -connect) + Find andre knuder ved DNS-opslag (standard: 1 hvis ikke -connect) Force safe mode (default: 0) @@ -2955,11 +2955,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Generate coins (default: 0) - Generer bitcoins (standard: 0) + Generér bitcoins (standard: 0) How many blocks to check at startup (default: 288, 0 = all) - Antal blokke som tjekkes ved opstart (0=alle, standard: 288) + Antal blokke som tjekkes ved opstart (standard: 288, 0=alle) If <category> is not supplied, output all debugging information. @@ -2971,7 +2971,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Incorrect or no genesis block found. Wrong datadir for network? - + Ukorrekt eller ingen tilblivelsesblok fundet. Forkert datamappe for netværk? Invalid -onion address: '%s' @@ -3011,7 +3011,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Specify wallet file (within data directory) - + Angiv tegnebogsfil (inden for datamappe) Spend unconfirmed change when sending transactions (default: 1) @@ -3027,11 +3027,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Verifying blocks... - Verificerer blokke... + Verificerer blokke … Verifying wallet... - Verificerer tegnebog... + Verificerer tegnebog … Wait for RPC server to start @@ -3039,7 +3039,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Wallet %s resides outside data directory %s - + Tegnebog %1 findes uden for datamappe %s Wallet options: @@ -3051,7 +3051,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com You need to rebuild the database using -reindex to change -txindex - + Du er nødt til at genopbygge databasen ved hjælp af -reindex for at ændre -txindex Imports blocks from external blk000??.dat file @@ -3063,7 +3063,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) - + Udfør kommando, når en relevant alarm modtages eller vi ser en virkelig lang udsplitning (%s i cmd erstattes af besked) Output debugging information (default: 0, supplying <category> is optional) @@ -3079,11 +3079,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Invalid amount for -minrelaytxfee=<amount>: '%s' - Ugyldigt beløb til -minrelaytxfee=<beløb>:'%s' + Ugyldigt beløb til -minrelaytxfee=<beløb>: "%s" Invalid amount for -mintxfee=<amount>: '%s' - Ugyldigt beløb til -mintxfee=<beløb>:'%s' + Ugyldigt beløb til -mintxfee=<beløb>: "%s" Limit size of signature cache to <n> entries (default: 50000) @@ -3099,15 +3099,15 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) - Maksimum for modtagelsesbuffer pr. forbindelse, <n>*1000 bytes (standard: 5000) + Maksimum for modtagelsesbuffer pr. forbindelse, <n>*1000 byte (standard: 5000) Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) - Maksimum for afsendelsesbuffer pr. forbindelse, <n>*1000 bytes (standard: 1000) + Maksimum for afsendelsesbuffer pr. forbindelse, <n>*1000 byte (standard: 1000) Only accept block chain matching built-in checkpoints (default: 1) - Accepter kun blokkæde, som matcher indbyggede kontrolposter (standard: 1) + Acceptér kun blokkæde, som matcher indbyggede kontrolposter (standard: 1) Only connect to nodes in network <net> (IPv4, IPv6 or Tor) @@ -3155,7 +3155,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Set minimum block size in bytes (default: 0) - Angiv minimumsblokstørrelse i bytes (standard: 0) + Angiv minimumsblokstørrelse i byte (standard: 0) Sets the DB_PRIVATE flag in the wallet db environment (default: 1) @@ -3203,11 +3203,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Use UPnP to map the listening port (default: 0) - Forsøg at bruge UPnP til at konfigurere den lyttende port (standard: 0) + Brug UPnP til at konfigurere den lyttende port (standard: 0) Use UPnP to map the listening port (default: 1 when listening) - Forsøg at bruge UPnP til at konfigurere den lyttende port (standard: 1 når lytter) + Brug UPnP til at konfigurere den lyttende port (standard: 1 under lytning) Username for JSON-RPC connections @@ -3311,11 +3311,11 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Invalid -proxy address: '%s' - Ugyldig -proxy adresse: '%s' + Ugyldig -proxy adresse: "%s" Unknown network specified in -onlynet: '%s' - Ukendt netværk anført i -onlynet: '%s' + Ukendt netværk anført i -onlynet: "%s" Unknown -socks proxy version requested: %i @@ -3323,15 +3323,15 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Cannot resolve -bind address: '%s' - Kan ikke finde -bind adressen: '%s' + Kan ikke finde -bind adressen: "%s" Cannot resolve -externalip address: '%s' - Kan ikke finde -externalip adressen: '%s' + Kan ikke finde -externalip adressen: "%s" Invalid amount for -paytxfee=<amount>: '%s' - Ugyldigt beløb for -paytxfee=<amount>: '%s' + Ugyldigt beløb for -paytxfee=<beløb>: "%s" Invalid amount @@ -3381,7 +3381,7 @@ f.eks.: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions. - Du skal angive rpcpassword=<password> i konfigurationsfilen: + Du skal angive rpcpassword=<adgangskode> i konfigurationsfilen: %s Hvis filen ikke eksisterer, opret den og giv ingen andre end ejeren læserettighed. diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index c4dee5f92d..2b9685f6a0 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -433,7 +433,7 @@ Produk ini termasuk software yang dibangun oleh Proyek OpenSSL untuk Toolkit Ope Request payments (generates QR codes and bitcoin: URIs) - + Permintaan pembayaran (membangkitkan kode QR dan bitcoin: URIs) &About Bitcoin Core @@ -473,7 +473,7 @@ Produk ini termasuk software yang dibangun oleh Proyek OpenSSL untuk Toolkit Ope Processed %1 of %2 (estimated) blocks of transaction history. - + Proses % 1 dar i% 2 (perkiraan) blok catatan transaksi Processed %1 blocks of transaction history. @@ -509,7 +509,7 @@ Produk ini termasuk software yang dibangun oleh Proyek OpenSSL untuk Toolkit Ope Transactions after this will not yet be visible. - + Transaksi setelah ini tidak akan ditampilkan Error @@ -561,7 +561,7 @@ Alamat: %4 A fatal error occurred. Bitcoin can no longer continue safely and will quit. - + Terjadi kesalahan fatal. Bitcoin tidak bisa lagi meneruskan dengan aman dan akan berhenti. @@ -611,15 +611,15 @@ Alamat: %4 (un)select all - + (Tidak)memilih semua Tree mode - + mode pohon List mode - + Mode daftar Amount @@ -663,11 +663,11 @@ Alamat: %4 Lock unspent - + Kunci terpakai. Unlock unspent - + Membuka kunci terpakai Copy quantity @@ -1350,7 +1350,7 @@ Alamat: %4 Error: Cannot parse configuration file: %1. Only use key=value syntax. - + Kesalahan: Tidak dapat memproses pengaturan berkas: %1. Hanya menggunakan kunci= nilai sintak. Error: Invalid combination of -regtest and -testnet. @@ -1408,7 +1408,7 @@ Alamat: %4 General - + Umum Using OpenSSL version @@ -1460,7 +1460,7 @@ Alamat: %4 &Clear - + &Kosongkan Totals @@ -1504,31 +1504,31 @@ Alamat: %4 %1 B - + %1 B %1 KB - + %1 KB %1 MB - + %1 MB %1 GB - + %1 GB %1 m - + %1 menit %1 h - + %1 Jam %1 h %2 m - + %1 Jam %2 menit @@ -1551,7 +1551,7 @@ Alamat: %4 R&euse an existing receiving address (not recommended) - + Gunakan lagi alamat penerima yang ada (tidak disarankan) An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. @@ -1716,7 +1716,7 @@ Alamat: %4 automatically selected - + Pemilihan otomatis Insufficient funds! @@ -1947,7 +1947,7 @@ Alamat: %4 This is a verified payment request. - + Permintaan pembayaran terverifikasi. Enter a label for this address to add it to the list of used addresses @@ -1959,7 +1959,7 @@ Alamat: %4 This is an unverified payment request. - + Permintaan pembayaran tidak terverifikasi. Pay To: @@ -2005,7 +2005,7 @@ Alamat: %4 Alt+A - Alt+J + Alt+A Paste address from clipboard @@ -2726,7 +2726,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - + Jalankan perintah ketika perubahan transaksi dompet (%s di cmd digantikan oleh TxID) Fees smaller than this are considered zero fee (for transaction creation) (default: @@ -2790,11 +2790,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. (default: 1) - + (pengaturan awal: 1) (default: wallet.dat) - + (pengaturan awal: wallet.dat) <category> can be: @@ -2830,7 +2830,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + Pilih koneksi: Corrupted block database detected @@ -2858,11 +2858,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error initializing block database - + Kesalahan menginisialisasi database blok Error initializing wallet database environment %s! - + Kesalahan menginisialisasi dompet pada database%s! Error loading block database @@ -2958,7 +2958,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Importing... - + mengimpor... Incorrect or no genesis block found. Wrong datadir for network? @@ -2970,7 +2970,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Not enough file descriptors available. - + Deskripsi berkas tidak tersedia dengan cukup. Prepend debug output with timestamp (default: 1) @@ -2978,7 +2978,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. RPC client options: - + Pilihan RPC klien: Rebuild block chain index from current blk000??.dat files @@ -2998,7 +2998,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set the number of threads to service RPC calls (default: 4) - + Mengatur jumlah urutan untuk layanan panggilan RPC (pengaturan awal: 4) Specify wallet file (within data directory) @@ -3174,11 +3174,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Start Bitcoin Core Daemon - + Memulai Bitcoin Core Daemon System error: - + Kesalahan sistem: Transaction amount too small diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index fb013f4c1d..8e2b681ba9 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -33,7 +33,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http (%1-bit) - + (%1-비트) @@ -611,7 +611,7 @@ Address: %4 (un)select all - + 모두 선택(하지 않음) Tree mode @@ -663,11 +663,11 @@ Address: %4 Lock unspent - + 비트코인이 사용되지 않은 주소를 잠금 처리합니다. Unlock unspent - + 비트코인이 사용되지 않은 주소를 잠금 해제합니다. Copy quantity @@ -767,7 +767,7 @@ Address: %4 Transactions with higher priority are more likely to get included into a block. - + 우선 순위가 높은 거래의 경우 블럭에 포함될 가능성이 더 많습니다. This label turns red, if the priority is smaller than "medium". @@ -779,11 +779,11 @@ Address: %4 This means a fee of at least %1 is required. - + 최소 %1의 거래 수수료가 필요하다는 뜻입니다. Amounts below 0.546 times the minimum relay fee are shown as dust. - + 노드 릴레이를 위한 최저 수수료의 0.546배보다 낮은 거래는 먼지 거래로 표현됩니다. This label turns red, if the change is smaller than %1. @@ -916,7 +916,7 @@ Address: %4 Set SSL root certificates for payment request (default: -system-) - + 지불 요청을 위해 SSL 최상위 인증을 설정합니다. (기본값: -system-) Show splash screen on startup (default: 1) @@ -939,11 +939,11 @@ Address: %4 As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - + 프로그램이 처음으로 실행되고 있습니다. 비트코인 코어가 어디에 데이터를 저장할지 선택할 수 있습니다. Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - + 비트코인 코어가 블럭체인의 복사본을 다운로드 저장합니다. 적어도 %1GB의 데이터가 이 폴더에 저장되며 시간이 경과할수록 점차 증가합니다. 그리고 지갑 또한 이 폴더에 저장됩니다. Use the default data directory @@ -959,7 +959,7 @@ Address: %4 Error: Specified data directory "%1" can not be created. - + 오류 : 별도 정의한 폴더명 "%1" 생성에 실패했습니다. Error @@ -1033,7 +1033,7 @@ Address: %4 Number of script &verification threads - + 스크립트 인증 쓰레드의 개수 Connect to the Bitcoin network through a SOCKS proxy. @@ -1081,11 +1081,11 @@ Address: %4 Expert - + 전문가 Enable coin &control features - + 코인 상세 제어기능을 활성화합니다 - &C If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. @@ -1173,7 +1173,7 @@ Address: %4 Whether to show coin control features or not. - + 코인 상세 제어기능에 대한 표시 여부를 선택할 수 있습니다. &OK @@ -1197,7 +1197,7 @@ Address: %4 Client restart required to activate changes. - + 변경 사항을 적용하기 위해서는 프로그램이 종료 후 재시작되어야 합니다. Client will be shutdown, do you want to proceed? @@ -1205,7 +1205,7 @@ Address: %4 This change would require a client restart. - + 이 변경 사항 적용을 위해 프로그램 재시작이 필요합니다. The supplied proxy address is invalid. @@ -1279,7 +1279,7 @@ Address: %4 Requested payment amount of %1 is too small (considered dust). - + 요청한 금액 %1의 양이 너무 적습니다. (스팸성 거래로 간주) Payment request error @@ -1295,7 +1295,7 @@ Address: %4 Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. - + 현재의 프록시가 SOCKS5를 지원하지 않아 지불 요청을 수행할 수 없습니다. Payment request fetch URL is invalid: %1 @@ -1547,11 +1547,11 @@ Address: %4 Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. - + 이전에 사용된 수취용 주소를 사용할려고 합니다. 주소의 재사용은 보안과 개인정보 보호 측면에서 문제를 초래할 수 있습니다. 이전 지불 요청을 재생성하는 경우가 아니라면 주소 재사용을 권하지 않습니다. R&euse an existing receiving address (not recommended) - + 현재의 수취용 주소를 재사용합니다만 권장하지는 않습니다. (R&) An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. @@ -1567,7 +1567,7 @@ Address: %4 An optional amount to request. Leave this empty or zero to not request a specific amount. - + 요청할 금액 입력칸으로 선택 사항입니다. 빈 칸으로 두거나 특정 금액이 필요하지 않는 경우 0을 입력하세요. Clear all fields of the form. @@ -1951,7 +1951,7 @@ Address: %4 Enter a label for this address to add it to the list of used addresses - + 사용된 주소 목록에 새 주소를 추가하기 위해 제목을 입력합니다. A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network. @@ -1963,7 +1963,7 @@ Address: %4 Pay To: - + 송금할 대상 : Memo: @@ -2246,7 +2246,7 @@ Address: %4 Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. - + 신규 채굴된 코인이 사용되기 위해서는 %1 개의 블럭이 경과되어야 합니다. 블럭을 생성할 때 블럭체인에 추가되도록 네트워크에 전파되는 과정을 거치는데, 블럭체인에 포함되지 못하고 실패한다면 해당 블럭의 상태는 '미승인'으로 표현되고 비트코인 또한 사용될 수 없습니다. 이 현상은 다른 노드가 비슷한 시간대에 동시에 블럭을 생성할 때 종종 발생할 수 있습니다. Debug information @@ -2316,7 +2316,7 @@ Address: %4 Immature (%1 confirmations, will be available after %2) - + 충분히 숙성되지 않은 상태 (%1 승인, %2 후에 사용 가능합니다) Open for %n more block(s) @@ -2348,7 +2348,7 @@ Address: %4 Confirming (%1 of %2 recommended confirmations) - + 승인 중 (권장되는 승인 회수 %2 대비 현재 승인 수 %1) Conflicted @@ -2580,7 +2580,7 @@ Address: %4 There was an error trying to save the wallet data to %1. - + 지갑 데이터를 %1 폴더에 저장하는 동안 오류가 발생했습니다. The wallet data was successfully saved to %1. @@ -2659,7 +2659,7 @@ Address: %4 Bitcoin Core RPC client version - + 비트코인 코어 RPC 클라이언트 버전 Run in the background as a daemon and accept commands @@ -2729,7 +2729,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Fees smaller than this are considered zero fee (for transaction creation) (default: - + 해당 금액보다 적은 수수료는 수수료 면제로 간주됩니다. (거래 생성의 목적)(기본값: Flush database activity from memory pool to disk log every <n> megabytes (default: 100) @@ -2789,11 +2789,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. (default: 1) - + (기본값: 1) (default: wallet.dat) - + (기본값: wallet.dat) <category> can be: @@ -2829,7 +2829,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + 연결 설정 : Corrupted block database detected @@ -2837,7 +2837,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Debugging/Testing options: - + 디버그 및 테스트 설정 Disable safemode, override a real safe mode event (default: 0) @@ -2929,11 +2929,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Fee per kB to add to transactions you send - + 송금 거래시 추가되는 KB 당 수수료입니다. Fees smaller than this are considered zero fee (for relaying) (default: - + 해당 금액보다 적은 수수료는 수수료 면제로 간주됩니다. (릴레이 목적)(기본값: Find peers using DNS lookup (default: 1 unless -connect) @@ -2941,7 +2941,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Force safe mode (default: 0) - + 안전 모드로 강제 진입하는 기능입니다.(기본값: 0) Generate coins (default: 0) diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index 1d9d4cc936..d09c40f62e 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -795,7 +795,7 @@ Adresa: %4 change from %1 (%2) - + restul de la %1 (%2) (change) @@ -1587,7 +1587,7 @@ Adresa: %4 Show the selected request (does the same as double clicking an entry) - + Arata cererea selectata (acelas lucru ca si dublu-click pe o inregistrare) Show @@ -3008,7 +3008,7 @@ spre exemplu: alertnotify=echo %%s | mail -s "Alerta Bitcoin" admin@fo Set the number of threads to service RPC calls (default: 4) - + Stabileste numarul de thread-uri care servesc apeluri RPC (implicit: 4) Specify wallet file (within data directory) From cdb36eff9f060330a1727dec82299f255459aa2d Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Fri, 23 May 2014 13:58:12 -0300 Subject: [PATCH 085/336] Fix warning when compiling in OS X --- src/qt/notificator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 38a029dbe5..3d588cd317 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -28,8 +28,10 @@ #endif +#ifdef USE_DBUS // https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128 const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128; +#endif Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent) : QObject(parent), From e832f5e39b3237368b8774cea2c21ac8529c5cbf Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 23 May 2014 20:35:49 +0200 Subject: [PATCH 086/336] doc: Add historical release notes for 0.9.1 --- doc/release-notes/release-notes-0.9.1.md | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 doc/release-notes/release-notes-0.9.1.md diff --git a/doc/release-notes/release-notes-0.9.1.md b/doc/release-notes/release-notes-0.9.1.md new file mode 100644 index 0000000000..0552053d27 --- /dev/null +++ b/doc/release-notes/release-notes-0.9.1.md @@ -0,0 +1,53 @@ +Bitcoin Core version 0.9.1 is now available from: + + https://bitcoin.org/bin/0.9.1/ + +This is a security update. It is recommended to upgrade to this release +as soon as possible. + +It is especially important to upgrade if you currently have version +0.9.0 installed and are using the graphical interface OR you are using +bitcoind from any pre-0.9.1 version, and have enabled SSL for RPC and +have configured allowip to allow rpc connections from potentially +hostile hosts. + +Please report bugs using the issue tracker at github: + + https://github.com/bitcoin/bitcoin/issues + +How to Upgrade +-------------- + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or +bitcoind/bitcoin-qt (on Linux). + +If you are upgrading from version 0.7.2 or earlier, the first time you run +0.9.1 your blockchain files will be re-indexed, which will take anywhere from +30 minutes to several hours, depending on the speed of your machine. + +0.9.1 Release notes +======================= + +No code changes were made between 0.9.0 and 0.9.1. Only the dependencies were changed. + +- Upgrade OpenSSL to 1.0.1g. This release fixes the following vulnerabilities which can + affect the Bitcoin Core software: + + - CVE-2014-0160 ("heartbleed") + A missing bounds check in the handling of the TLS heartbeat extension can + be used to reveal up to 64k of memory to a connected client or server. + + - CVE-2014-0076 + The Montgomery ladder implementation in OpenSSL does not ensure that + certain swap operations have a constant-time behavior, which makes it + easier for local users to obtain ECDSA nonces via a FLUSH+RELOAD cache + side-channel attack. + +- Add statically built executables to Linux build + +Credits +-------- + +Credits go to the OpenSSL team for fixing the vulnerabilities quickly. From e9df7f87574b32d70aec2dad5f8d84a68c618dee Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 24 May 2014 11:12:47 -0400 Subject: [PATCH 087/336] Qt: Fix monospace font in osx 10.9 The "Monospace" hint was added in Qt 4.8, and it works as intended as opposed to "TypeWriter" which fails to load a font. --- src/qt/guiutil.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 7b264d27c7..49c0867450 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -76,7 +76,11 @@ QString dateTimeStr(qint64 nTime) QFont bitcoinAddressFont() { QFont font("Monospace"); +#if QT_VERSION >= 0x040800 + font.setStyleHint(QFont::Monospace); +#else font.setStyleHint(QFont::TypeWriter); +#endif return font; } From 2869b1349b2cce3ac8fa8a39e0df65e4201c438a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Sat, 24 May 2014 11:11:42 -0400 Subject: [PATCH 088/336] release: Bump the OSX SDK to 10.7 for gitian builds This fixes the display on Retina Macbooks. It also moves us away from depending on the ancient XCode3 sdk. --- .../gitian-descriptors/gitian-osx-bitcoin.yml | 25 ++++++++----------- .../gitian-descriptors/gitian-osx-depends.yml | 15 ++++++----- .../gitian-descriptors/gitian-osx-native.yml | 15 ++++++----- contrib/gitian-descriptors/gitian-osx-qt.yml | 24 +++++++----------- doc/README_osx.txt | 14 +++++++---- doc/release-process.md | 8 +++--- 6 files changed, 45 insertions(+), 56 deletions(-) diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml index aea4b93a1f..e29047d610 100644 --- a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml +++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml @@ -17,33 +17,28 @@ remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: -- "osx-native-depends-r2.tar.gz" -- "osx-depends-r2.tar.gz" -- "osx-depends-qt-5.2.1-r2.tar.gz" -- "MacOSX10.6.pkg" +- "osx-native-depends-r3.tar.gz" +- "osx-depends-r3.tar.gz" +- "osx-depends-qt-5.2.1-r3.tar.gz" +- "MacOSX10.7.sdk.tar.gz" script: | - echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c - HOST=x86_64-apple-darwin11 PREFIX=`pwd`/osx-cross-depends/prefix - SDK=`pwd`/osx-cross-depends/SDKs/MacOSX10.6.sdk + SDK=`pwd`/osx-cross-depends/SDKs/MacOSX10.7.sdk NATIVEPREFIX=`pwd`/osx-cross-depends/native-prefix export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export SOURCES_PATH=`pwd` - mkdir osx-cross-depends + mkdir -p osx-cross-depends/SDKs - cd osx-cross-depends - mkdir -p SDKs - 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i - cd .. + tar -C osx-cross-depends/SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz - tar -C osx-cross-depends -xf osx-native-depends-r2.tar.gz - tar -C osx-cross-depends -xf osx-depends-r2.tar.gz - tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r2.tar.gz + tar -C osx-cross-depends -xf osx-native-depends-r3.tar.gz + tar -C osx-cross-depends -xf osx-depends-r3.tar.gz + tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r3.tar.gz export PATH=`pwd`/osx-cross-depends/native-prefix/bin:$PATH cd bitcoin diff --git a/contrib/gitian-descriptors/gitian-osx-depends.yml b/contrib/gitian-descriptors/gitian-osx-depends.yml index 8e91a30ded..adc86e5cb4 100644 --- a/contrib/gitian-descriptors/gitian-osx-depends.yml +++ b/contrib/gitian-descriptors/gitian-osx-depends.yml @@ -18,8 +18,8 @@ files: - "openssl-1.0.1g.tar.gz" - "protobuf-2.5.0.tar.bz2" - "qrencode-3.4.3.tar.bz2" -- "MacOSX10.6.pkg" -- "osx-native-depends-r2.tar.gz" +- "MacOSX10.7.sdk.tar.gz" +- "osx-native-depends-r3.tar.gz" script: | @@ -29,9 +29,8 @@ script: | echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c - echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c - REVISION=r2 + REVISION=r3 export SOURCES_PATH=`pwd` export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export PATH=$HOME:$PATH @@ -44,7 +43,7 @@ script: | PREFIX=`pwd`/prefix NATIVEPREFIX=`pwd`/native-prefix BUILD_BASE=`pwd`/build - SDK=`pwd`/SDKs/MacOSX10.6.sdk + SDK=`pwd`/SDKs/MacOSX10.7.sdk HOST=x86_64-apple-darwin11 MIN_VERSION=10.6 @@ -70,10 +69,10 @@ script: | mkdir -p ${PREFIX}/lib mkdir -p ${BUILD_BASE} - mkdir -p ${SDK} - 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + mkdir -p SDKs + tar -C SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz - tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz + tar xf /home/ubuntu/build/osx-native-depends-r3.tar.gz # bdb SOURCE_FILE=${SOURCES_PATH}/db-4.8.30.NC.tar.gz diff --git a/contrib/gitian-descriptors/gitian-osx-native.yml b/contrib/gitian-descriptors/gitian-osx-native.yml index 6040e5ac5b..a753ad704f 100644 --- a/contrib/gitian-descriptors/gitian-osx-native.yml +++ b/contrib/gitian-descriptors/gitian-osx-native.yml @@ -24,7 +24,7 @@ files: - "dyld-195.5.tar.gz" - "ld64-127.2.tar.gz" - "protobuf-2.5.0.tar.bz2" -- "MacOSX10.6.pkg" +- "MacOSX10.7.sdk.tar.gz" - "cdrkit-1.1.11.tar.gz" - "libdmg-hfsplus-v0.1.tar.gz" - "clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz" @@ -38,14 +38,13 @@ script: | echo "2cf0484c87cf79b606b351a7055a247dae84093ae92c747a74e0cde2c8c8f83c dyld-195.5.tar.gz" | sha256sum -c echo "97b75547b2bd761306ab3e15ae297f01e7ab9760b922bc657f4ef72e4e052142 ld64-127.2.tar.gz" | sha256sum -c echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c - echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c echo "d1c030756ecc182defee9fe885638c1785d35a2c2a297b4604c0e0dcc78e47da cdrkit-1.1.11.tar.gz" | sha256sum -c echo "6569a02eb31c2827080d7d59001869ea14484c281efab0ae7f2b86af5c3120b3 libdmg-hfsplus-v0.1.tar.gz" | sha256sum -c echo "b9d57a88f9514fa1f327a1a703756d0c1c960f4c58494a5bd80313245d13ffff clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz" | sha256sum -c echo "cc12bdbd7a09f71cb2a6a3e6ec3e0abe885ca7111c2b47857f5095e5980caf4f cdrkit-deterministic.patch" | sha256sum -c - REVISION=r2 + REVISION=r3 export REFERENCE_DATETIME export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export FAKETIME=$REFERENCE_DATETIME @@ -78,7 +77,7 @@ script: | NATIVEPREFIX=`pwd`/native-prefix BUILD_BASE=`pwd`/build - SDK=`pwd`/SDKs/MacOSX10.6.sdk + SDK=`pwd`/SDKs/MacOSX10.7.sdk HOST=x86_64-apple-darwin11 MIN_VERSION=10.6 @@ -91,8 +90,8 @@ script: | mkdir -p ${NATIVEPREFIX}/bin mkdir -p ${NATIVEPREFIX}/lib - mkdir -p ${SDK} - 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + mkdir -p SDKs + tar -C SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz # Clang SOURCE_FILE=${SOURCES_PATH}/clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz @@ -112,7 +111,7 @@ script: | tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} mkdir -p ${BUILD_DIR}/sdks pushd ${BUILD_DIR}/sdks; - ln -sf ${SDK} MacOSX10.6.sdk + ln -sf ${SDK} MacOSX10.7.sdk ln -sf ${SOURCES_PATH}/cctools-809.tar.gz ${BUILD_DIR}/cctools2odcctools/cctools-809.tar.gz ln -sf ${SOURCES_PATH}/ld64-127.2.tar.gz ${BUILD_DIR}/cctools2odcctools/ld64-127.2.tar.gz ln -sf ${SOURCES_PATH}/dyld-195.5.tar.gz ${BUILD_DIR}/cctools2odcctools/dyld-195.5.tar.gz @@ -127,7 +126,7 @@ script: | sed -i 's/\# Dynamically linked LTO/\t ;\&\n\t linux*)\n# Dynamically linked LTO/' ${BUILD_DIR}/cctools2odcctools/files/configure.ac cd ${BUILD_DIR}/cctools2odcctools - ./extract.sh --osxver 10.6 + ./extract.sh --osxver 10.7 cd odcctools-809 ./configure --prefix=${NATIVEPREFIX} --target=${HOST} CFLAGS="${CFLAGS} -I${NATIVEPREFIX}/include -D__DARWIN_UNIX03 -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS" LDFLAGS="${LDFLAGS} -Wl,-rpath=\\\$\$ORIGIN/../lib" --with-sysroot=${SDK} diff --git a/contrib/gitian-descriptors/gitian-osx-qt.yml b/contrib/gitian-descriptors/gitian-osx-qt.yml index d0be016e68..b57908dbd9 100644 --- a/contrib/gitian-descriptors/gitian-osx-qt.yml +++ b/contrib/gitian-descriptors/gitian-osx-qt.yml @@ -13,16 +13,15 @@ reference_datetime: "2013-06-01 00:00:00" remotes: [] files: - "qt-everywhere-opensource-src-5.2.1.tar.gz" -- "osx-native-depends-r2.tar.gz" -- "osx-depends-r2.tar.gz" -- "MacOSX10.6.pkg" +- "osx-native-depends-r3.tar.gz" +- "osx-depends-r3.tar.gz" +- "MacOSX10.7.sdk.tar.gz" script: | echo "84e924181d4ad6db00239d87250cc89868484a14841f77fb85ab1f1dbdcd7da1 qt-everywhere-opensource-src-5.2.1.tar.gz" | sha256sum -c - echo "a2ccf2299de4e0bb88bd17a3355f02b747575b97492c7c2f5b789a64ccc4cbd6 MacOSX10.6.pkg" | sha256sum -c - REVISION=r2 + REVISION=r3 export SOURCES_PATH=`pwd` export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export ZERO_AR_DATE=1 @@ -42,7 +41,7 @@ script: | PREFIX=`pwd`/prefix NATIVEPREFIX=`pwd`/native-prefix BUILD_BASE=`pwd`/build - SDK=`pwd`/SDKs/MacOSX10.6.sdk + SDK=`pwd`/SDKs/MacOSX10.7.sdk HOST=x86_64-apple-darwin11 MIN_VERSION=10.6 @@ -68,18 +67,13 @@ script: | mkdir -p ${PREFIX}/lib mkdir -p ${BUILD_BASE} - mkdir -p ${SDK} - 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i - - tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz - - mkdir -p SDKs - 7z -bd -so -y e ${SOURCES_PATH}/MacOSX10.6.pkg Payload | gzip -d -c | cpio -i + tar -C SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz + + tar xf /home/ubuntu/build/osx-native-depends-r3.tar.gz - tar xf /home/ubuntu/build/osx-native-depends-r2.tar.gz export PATH=`pwd`/native-prefix/bin:$PATH - tar xf /home/ubuntu/build/osx-depends-r2.tar.gz + tar xf /home/ubuntu/build/osx-depends-r3.tar.gz SOURCE_FILE=${SOURCES_PATH}/qt-everywhere-opensource-src-5.2.1.tar.gz BUILD_DIR=${BUILD_BASE}/qt-everywhere-opensource-src-5.2.1 diff --git a/doc/README_osx.txt b/doc/README_osx.txt index 6eae4f5cf1..2be56c1592 100644 --- a/doc/README_osx.txt +++ b/doc/README_osx.txt @@ -37,11 +37,15 @@ originally done in toolchain4. To complicate things further, all builds must target an Apple SDK. These SDKs are free to download, but not redistributable. -To obtain it, register for a developer account, then download xcode_3.2.6_and_ios_sdk_4.3.dmg: -https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_3.2.6_and_ios_sdk_4.3__final/xcode_3.2.6_and_ios_sdk_4.3.dmg -This file is several gigabytes in size, but only a single .pkg file inside is -needed (MacOSX10.6.pkg). From Linux, 7-zip can be used to extract this file. -The DMG can then be discarded. +To obtain it, register for a developer account, then download xcode4630916281a.dmg: +https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg +This file is several gigabytes in size, but only a single directory inside is +needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk + +Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file. +To create a tarball suitable for gitian input, mount the dmg in OSX, then create it with: + $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.7.sdk.tar.gz MacOSX10.7.sdk + The gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to diff --git a/doc/release-process.md b/doc/release-process.md index be00cb8092..6d08c48496 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -36,12 +36,10 @@ Release Process mkdir -p inputs; cd inputs/ Register and download the Apple SDK (see OSX Readme for details) - visit https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_3.2.6_and_ios_sdk_4.3__final/xcode_3.2.6_and_ios_sdk_4.3.dmg + visit https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg - Extract MacOSX10.6.pkg using 7zip - 7z e -y xcode_3.2.6_and_ios_sdk_4.3.dmg 5.hfs - 7z -y e 5.hfs "Xcode and iOS SDK/Packages/MacOSX10.6.pkg" - rm 5.hfs + Using a Mac, create a tarball for the 10.7 SDK + tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.7.sdk.tar.gz MacOSX10.7.sdk Fetch and build inputs: (first time, or when dependency versions change) From b90711cabffa8bf83ddee98cfc179c0aef5732ef Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Wed, 28 May 2014 01:38:40 +0200 Subject: [PATCH 089/336] [Qt] Fix Transaction details shows wrong To: --- src/qt/transactiondesc.cpp | 33 +++++++++++++------------------- src/qt/transactiondesc.h | 3 ++- src/qt/transactiontablemodel.cpp | 2 +- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 45fb3d40c2..0cfcb048c8 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -42,7 +42,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) } } -QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit) +QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit) { QString strHTML; @@ -86,26 +86,19 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u if (nNet > 0) { // Credit - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (CBitcoinAddress(rec->address).IsValid()) { - if (wallet->IsMine(txout)) + CTxDestination address = CBitcoinAddress(rec->address).Get(); + if (wallet->mapAddressBook.count(address)) { - CTxDestination address; - if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) - { - if (wallet->mapAddressBook.count(address)) - { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); - if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; - else - strHTML += " (" + tr("own address") + ")"; - strHTML += "
"; - } - } - break; + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(rec->address); + if (!wallet->mapAddressBook[address].name.empty()) + strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + else + strHTML += " (" + tr("own address") + ")"; + strHTML += "
"; } } } @@ -224,7 +217,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int u if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty()) strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
"; - strHTML += "" + tr("Transaction ID") + ": " + TransactionRecord::formatSubTxId(wtx.GetHash(), vout) + "
"; + strHTML += "" + tr("Transaction ID") + ": " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "
"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm) diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h index 92d093b3eb..f5a1328a71 100644 --- a/src/qt/transactiondesc.h +++ b/src/qt/transactiondesc.h @@ -8,6 +8,7 @@ #include #include +class TransactionRecord; class CWallet; class CWalletTx; @@ -18,7 +19,7 @@ class TransactionDesc: public QObject Q_OBJECT public: - static QString toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit); + static QString toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit); private: TransactionDesc() {} diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 8cf2b0a1b1..b9fcd0d6b0 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -222,7 +222,7 @@ public: std::map::iterator mi = wallet->mapWallet.find(rec->hash); if(mi != wallet->mapWallet.end()) { - return TransactionDesc::toHTML(wallet, mi->second, rec->idx, unit); + return TransactionDesc::toHTML(wallet, mi->second, rec, unit); } } return QString(""); From d2b82dd7d8cdc87555d1983e47fe10a7b92f2d87 Mon Sep 17 00:00:00 2001 From: Mathy Vanvoorden Date: Fri, 9 May 2014 12:52:08 +0200 Subject: [PATCH 090/336] Spelling fix in comment Rebased-By: Wladimir J. van der Laan Rebased-From: 3704a6a --- src/qt/bitcoingui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index e6190aec13..68ae8b4668 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -188,7 +188,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); - // prevents an oben debug window from becoming stuck/unusable on client shutdown + // prevents an open debug window from becoming stuck/unusable on client shutdown connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide())); // Install event filter to be able to catch status tip events (QEvent::StatusTip) From 066d9a53c79db63b019e38be7995440f9fcfe7ff Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Thu, 29 May 2014 05:21:58 +0200 Subject: [PATCH 091/336] [Qt] Fix Start bitcoin on system login --- src/qt/guiutil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 49c0867450..183fcac4a0 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -574,7 +574,7 @@ bool SetStartOnSystemStartup(bool fAutoStart) return true; } -#elif defined(LINUX) +#elif defined(Q_OS_LINUX) // Follow the Desktop Application Autostart Spec: // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html From 53a088154ce4e1fc483afa120a9063811dd0e7ea Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Thu, 29 May 2014 12:33:17 +0200 Subject: [PATCH 092/336] rename fNoListen to fListen and move to net - better code readability and it belongs to net - this is a prerequisite for a pull to add -listen to the GUI --- src/init.cpp | 4 ++-- src/main.cpp | 4 ++-- src/net.cpp | 3 ++- src/net.h | 1 + src/util.cpp | 1 - src/util.h | 1 - 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bc4924b48d..06ad84af25 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -732,12 +732,12 @@ bool AppInit2(boost::thread_group& threadGroup) } // see Step 2: parameter interactions for more information about these - fNoListen = !GetBoolArg("-listen", true); + fListen = GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); fNameLookup = GetBoolArg("-dns", true); bool fBound = false; - if (!fNoListen) { + if (fListen) { if (mapArgs.count("-bind")) { BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { CService addrBind; diff --git a/src/main.cpp b/src/main.cpp index 18c00d90ac..5f61a13782 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3550,7 +3550,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (!pfrom->fInbound) { // Advertise our address - if (!fNoListen && !IsInitialBlockDownload()) + if (fListen && !IsInitialBlockDownload()) { CAddress addr = GetLocalAddress(&pfrom->addr); if (addr.IsRoutable()) @@ -4318,7 +4318,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pnode->setAddrKnown.clear(); // Rebroadcast our address - if (!fNoListen) + if (fListen) { CAddress addr = GetLocalAddress(&pnode->addr); if (addr.IsRoutable()) diff --git a/src/net.cpp b/src/net.cpp index c2dde97040..ef6674011b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -45,6 +45,7 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8; // Global state variables // bool fDiscover = true; +bool fListen = true; uint64_t nLocalServices = NODE_NETWORK; CCriticalSection cs_mapLocalHost; map mapLocalHost; @@ -96,7 +97,7 @@ unsigned short GetListenPort() // find 'best' local address for a particular peer bool GetLocal(CService& addr, const CNetAddr *paddrPeer) { - if (fNoListen) + if (!fListen) return false; int nBestScore = -1; diff --git a/src/net.h b/src/net.h index ac90ef25ef..55502ed893 100644 --- a/src/net.h +++ b/src/net.h @@ -105,6 +105,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); extern bool fDiscover; +extern bool fListen; extern uint64_t nLocalServices; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; diff --git a/src/util.cpp b/src/util.cpp index 336ef31725..d106b03230 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -94,7 +94,6 @@ bool fPrintToDebugLog = true; bool fDaemon = false; bool fServer = false; string strMiscWarning; -bool fNoListen = false; bool fLogTimestamps = false; volatile bool fReopenDebugLog = false; CClientUIInterface uiInterface; diff --git a/src/util.h b/src/util.h index ffcb20d822..b09f9bb15e 100644 --- a/src/util.h +++ b/src/util.h @@ -100,7 +100,6 @@ extern bool fPrintToConsole; extern bool fPrintToDebugLog; extern bool fServer; extern std::string strMiscWarning; -extern bool fNoListen; extern bool fLogTimestamps; extern volatile bool fReopenDebugLog; From 58bfa79f0e277c34b20279c2fef56ec9c1ca2479 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 29 May 2014 12:13:02 -0400 Subject: [PATCH 093/336] gitian: Add cfields to gitian download scripts --- contrib/gitian-downloader/cfields-key.php | 52 +++++++++++++++++++ .../gitian-downloader/linux-download-config | 3 ++ .../gitian-downloader/win32-download-config | 3 ++ 3 files changed, 58 insertions(+) create mode 100644 contrib/gitian-downloader/cfields-key.php diff --git a/contrib/gitian-downloader/cfields-key.php b/contrib/gitian-downloader/cfields-key.php new file mode 100644 index 0000000000..6b0bd240ba --- /dev/null +++ b/contrib/gitian-downloader/cfields-key.php @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) + +mQINBFOHTh4BEADdKsRvmNhX+B+bcPsgMkp8ztwJA5g/rmrOlHQpKOOf4P2tAr6w +FmXCChWF9Iq3pDFQ0t0iq5rgisFPyrGVT/VToMmH+/PSLTyIdAlgkRYDMAPsMAFV +MaADH4yiAgJ3cdXtysjaNQV5O25ypqq6/obUjZJD5Enn6b/UgHe2+7LTmTNsskOx +5s/WPPht79EY1kM4JQfmDx68CsmqeSAlT6yeO3RQcLn/l46cfXiwzMO4h1hsZS1r +pgciRp0EHK9uAjF2rjqt8v4SDxwyTnwfpBBulzvH9mBf+HRXWzoTMR4sC/oOZext +hKAH/ex47BxN3HU3ftNhCK2c1xcU1UOGSjbf0RdbwuSCxxa7mktEDumvOxAk9EBB ++PDPv7jO1FBK3rsJdscYQIL0AiRyO49VfNLARa34OqUi8pOAxKBQ9plO02W1gp7a +DVBPI05TZ46Y8dTR2Bc1raAgOyxnXM7jfiQG2gSULiKAJAI4HwOiodaiiHAxDaIo +a3mtsmfN25TZUQuA0I0BvHbJvLRlVnyZm3XVOcwReKJpZJV4qRhd3XNrERZdz6ZK +cAZnyC/X+Uzo4HfnVSsJk1GpIa4seYyrVCFfHMiAA6SkgAUFbV26KCOv4rNR2GlV +l2fVhu1RKOEUJ8nRcEqf93SehRVYdI67LepIPgmIwi0KG4HhoTbIHDAKWQARAQAB +tCtDb3J5IEZpZWxkcyA8Y2ZpZWxkc0BiaXRjb2luZm91bmRhdGlvbi5vcmc+iQI4 +BBMBAgAiBQJTh04eAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAcJJH/ +6w73cBTiEADIGZSueBFmaOTJCgasKGguHns/n8P94EQBZr07rrgN99Rzp85WvDUN +Qa72wj3GNcAffN7aZlIWv4g+fjyr9AzHekjI/7iwwSYIfjfTR/xRUW7czRfKAOrK +iwpEzgv440i7PBvkS/AhNdUNkm+cJvaQUej/F2/O52qDLEpHuzvjAUUWlSeF9/oO +AjM9dfC24L5k5cVwQvH9noxk3EyuE7BuiGE5a+kKiORrtxiHeUG6GYQxuqrPucLU +fI67ETyXa0YSpYm5/O65BKMTMpmkMvv1JC2kqqsYTrO5p158CrKzq2xvpuG4ABsb +9KwICUGW31Ndr6TXwQJFa1b7VK4G1g6M1DFkVTOLJnEyOwgYxsXrV5QFpzpAOAji +6KcxNGeow1avAFYbqjjLgu9UNuq6b8du13hjkQxVs2NAP1Kd/u2ADwxQHMhZGVEC +9LIcLVSP9ShY6fR8m6fwSlJfpiV81uLNVD8KIyvp+pYTQ/FnxoPhPIwalYquBZKi +0u38igW75IzZ0fYvJgTumE/8ofSVkutVtrQb21eJclVrJGMNweTlJcJhAWdKkjDC +e6mSj8GItKV1ef+eusXSzs/wPyTaqgkELvvAOZdwUq3kobQErE5HOuPEOvcwuY96 +DcxLexirCGW5wCUq7Db0c0dUjQwzzb5OTW2jdnPVR0qxi29TnOJ2aLkCDQRTh04e +ARAAuJKpI6NTCQrjEqe9AYywN8676+fPS5bqXkyb/iub6MXeQdwpH0K42lXAaYMq +ow/0aLlvGWCHuJJGozoOWpTzQ+VPbhpdARoLCop5fYTpy8Q17ubLeeODDtr6jtDN +lmg+9PBIErIVUnUS2wNZuJRVsfwlLaU3T2v8kQnQ6AEbl/QwyWW9nB8rAWBu6Hvs +VdtcBmtHSr9xAGBGfW6rSVhTitikR4lWJPdNJxI3pLaswpLIUIQ1rssKO4glljcp +C6nhMvRkDLvDFvDP9QnmwY/A4ch5S6ANPrhOjQuu9njjQ+/ImrJTjAXqHwg5KdTc +NKxufgvi9elOQ422o0No3yKdRoRA4kdcUmqA9gNZDyX0ZTd17aNqc42Zt3aYLJ11 +bLZZp0qnfhkmhbsBZZtaLNkuF+RGPWysxY7KPMm+nHn6f3Wpr18E+T02wi02r4nS +HOQI+gppDqy3Vq3ZZNoUZynctiLZVHkqi+WYXqfD2tEn8UJKpht7jrZlNgkHFgT7 +T0/U4+JmaQ/HltE+IexAIH0GP0Jt6hmRoZimdoy8Q8NY5t/fn9CQNJm5InrHvooN +aFmZMvzGTGiTqBqnA/7k9FCUEG98LK11MsIssY8YE/F6HD69R3ISyRvhUbpFvhD8 +c6zOkEKngTWvyRevrDrDz2yoZ1+T1X350+92rbEc/8WyutcAEQEAAYkCHwQYAQIA +CQUCU4dOHgIbDAAKCRAcJJH/6w73cAakEACv4EUEjtFjqnGB0Lru5FKs1obWcf37 +c4a5yYvOw58dkEZ9hsq34qWGLT128n6R24KEG+3O4CbplAD5Kt2eAPracbPHMAn8 +TGmC+KjiGlBR5xCY9dD0fn5EbRWOa+Fdcj1DpneaqMl9vLnBbqGp7pa/MwSOc+FB +0Ms2rcGJJMNHgITfP22eCf6pvf/xq7kKbUJ3Kjqdc2hWlRMjC/OOeITdrgycfDk/ +AOzLNqk5q7bYOxna6rWDLGSkCATyQKaBTVK7wRd1VrIhI4vfFqy+BWYXyXJ0pxjS +eaCDwbWHX/KW+0qLsmHxFMAyHJPjs8LEwK/DRbmWhe1HzPcBKmpyjqlkuxPjAdSl +hP4+IBvVNLf2Kh3uFHehk9A6oCYZGe3lLfQnOxIantXF7IROTmiZZsb+08w6cIXE ++r6kWG6vP2aCVtzYNfY+2p5xfg3yMxcxENJki1WSCOq6WVf9IWFzSJu+0+eazD3L +3QpZoSX5VvT6x05C0Ay1ert0Q5MyF84Eh8mDqL4PhpWtQhZMp8SG4jqFVgrhM4sl +vWGYXGns4tbnNPiiksjBD8TTvG3+mt48sNJIpHThjdWJSZjllYG7jV8oi7HrX8M2 +LOwWWLYxHkqi9wpmrWHSmniex6ABozcqrb+EgSMnHuSd7glmOJxHToJIudJbKG5D +MrD0ofsytfy1LQ== +=DE4h +-----END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config index b5e0561aa3..f5e6382b84 100644 --- a/contrib/gitian-downloader/linux-download-config +++ b/contrib/gitian-downloader/linux-download-config @@ -37,3 +37,6 @@ signers: E944AE667CF960B1004BC32FCA662BE18B877A60: name: "Andreas Schildbach" key: aschildbach + C060A6635913D98A3587D7DB1C2491FFEB0EF770: + name: "Cory Fields" + key: "cfields" diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config index 5d56db863e..06c164180d 100644 --- a/contrib/gitian-downloader/win32-download-config +++ b/contrib/gitian-downloader/win32-download-config @@ -37,3 +37,6 @@ signers: E944AE667CF960B1004BC32FCA662BE18B877A60: name: "Andreas Schildbach" key: aschildbach + C060A6635913D98A3587D7DB1C2491FFEB0EF770: + name: "Cory Fields" + key: "cfields" From b5ef85c7a22f6aa67d2241936f083c6c81702fb1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 29 May 2014 18:17:34 +0200 Subject: [PATCH 094/336] No references to centralized databases in help text. --- src/rpcwallet.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index a8f267d7fc..e3b35dbb04 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -318,7 +318,7 @@ Value sendtoaddress(const Array& params, bool fHelp) " to which you're sending the transaction. This is not part of the \n" " transaction, just kept in your wallet.\n" "\nResult:\n" - "\"transactionid\" (string) The transaction id. (view at https://blockchain.info/tx/[transactionid])\n" + "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1") + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"") @@ -747,7 +747,7 @@ Value sendfrom(const Array& params, bool fHelp) " to which you're sending the transaction. This is not part of the transaction, \n" " it is just kept in your wallet.\n" "\nResult:\n" - "\"transactionid\" (string) The transaction id. (view at https://blockchain.info/tx/[transactionid])\n" + "\"transactionid\" (string) The transaction id.\n" "\nExamples:\n" "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n" + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") + @@ -807,7 +807,7 @@ Value sendmany(const Array& params, bool fHelp) "4. \"comment\" (string, optional) A comment\n" "\nResult:\n" "\"transactionid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" - " the number of addresses. See https://blockchain.info/tx/[transactionid]\n" + " the number of addresses.\n" "\nExamples:\n" "\nSend two amounts to two different addresses:\n" + HelpExampleCli("sendmany", "\"tabby\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") + @@ -1209,8 +1209,7 @@ Value listtransactions(const Array& params, bool fHelp) " category of transactions.\n" " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n" " category of transactions.\n" - " \"txid\": \"transactionid\", (string) The transaction id (see https://blockchain.info/tx/[transactionid]. Available \n" - " for 'send' and 'receive' category of transactions.\n" + " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n" " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n" " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n" " for 'send' and 'receive' category of transactions.\n" @@ -1375,7 +1374,7 @@ Value listsinceblock(const Array& params, bool fHelp) " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" - " \"txid\": \"transactionid\", (string) The transaction id (see https://blockchain.info/tx/[transactionid]. Available for 'send' and 'receive' category of transactions.\n" + " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n" " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n" " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n" " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" @@ -1447,7 +1446,7 @@ Value gettransaction(const Array& params, bool fHelp) " \"blockhash\" : \"hash\", (string) The block hash\n" " \"blockindex\" : xx, (numeric) The block index\n" " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n" - " \"txid\" : \"transactionid\", (string) The transaction id, see also https://blockchain.info/tx/[transactionid]\n" + " \"txid\" : \"transactionid\", (string) The transaction id.\n" " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n" " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n" " \"details\" : [\n" From 21790821da80f885049095c72086968e0d5e5a08 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Thu, 29 May 2014 12:51:14 -0400 Subject: [PATCH 095/336] Fix name of Cory's pgp key --- contrib/gitian-downloader/{cfields-key.php => cfields-key.pgp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contrib/gitian-downloader/{cfields-key.php => cfields-key.pgp} (100%) diff --git a/contrib/gitian-downloader/cfields-key.php b/contrib/gitian-downloader/cfields-key.pgp similarity index 100% rename from contrib/gitian-downloader/cfields-key.php rename to contrib/gitian-downloader/cfields-key.pgp From c21c74bec43a693283fecbdfb62fee4523317a81 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 29 May 2014 15:30:46 -0400 Subject: [PATCH 096/336] osx: Fix missing dock menu with qt5 Qt5 Removed the qt_mac_set_dock_menu function and left no replacement. It was later re-added and deprecated for backwards-compatibility. Qt5.2 adds the non-deprecated QMenu::setAsDockMenu(). Use that when possible. --- src/qt/macdockiconhandler.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm index 64291c9188..74fb64ace3 100644 --- a/src/qt/macdockiconhandler.mm +++ b/src/qt/macdockiconhandler.mm @@ -62,6 +62,8 @@ MacDockIconHandler::MacDockIconHandler() : QObject() this->setMainWindow(NULL); #if QT_VERSION < 0x050000 qt_mac_set_dock_menu(this->m_dockMenu); +#elif QT_VERSION >= 0x050200 + this->m_dockMenu->setAsDockMenu(); #endif [pool release]; } From 5823449e2d7f76fa1f24fed881a8a5041b34b6bf Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 30 May 2014 12:01:20 +0200 Subject: [PATCH 097/336] Limit number of known addresses per peer --- src/mruset.h | 1 + src/net.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mruset.h b/src/mruset.h index c36a0c8f37..c1c08b0288 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -32,6 +32,7 @@ public: 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); } + void clear() { set.clear(); queue.clear(); } bool inline friend operator==(const mruset& a, const mruset& b) { return a.set == b.set; } bool inline friend operator==(const mruset& a, const std::set& b) { return a.set == b; } bool inline friend operator<(const mruset& a, const mruset& b) { return a.set < b.set; } diff --git a/src/net.h b/src/net.h index ac90ef25ef..d3346873bc 100644 --- a/src/net.h +++ b/src/net.h @@ -262,7 +262,7 @@ public: // flood relay std::vector vAddrToSend; - std::set setAddrKnown; + mruset setAddrKnown; bool fGetAddr; std::set setKnown; @@ -278,7 +278,7 @@ public: int64_t nPingUsecTime; bool fPingQueued; - CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION) + CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) { nServices = 0; hSocket = hSocketIn; From 09a54a65c0d05fe93c4a31603eca8a9a76ff6526 Mon Sep 17 00:00:00 2001 From: Huang Le <4tarhl@gmail.com> Date: Fri, 30 May 2014 23:44:44 +0800 Subject: [PATCH 098/336] Use pnode->nLastRecv as sync score directly NodeSyncScore() should find the node which we recv data most recently, so put a negative sign to pnode->nLastRecv is indeed wrong. Also change the return value type to int64_t. Signed-off-by: Huang Le <4tarhl@gmail.com> --- src/net.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index c2dde97040..b0e6699ed2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1455,13 +1455,13 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu // for now, use a very simple selection metric: the node from which we received // most recently -double static NodeSyncScore(const CNode *pnode) { - return -pnode->nLastRecv; +static int64_t NodeSyncScore(const CNode *pnode) { + return pnode->nLastRecv; } void static StartSync(const vector &vNodes) { CNode *pnodeNewSync = NULL; - double dBestScore = 0; + int64_t nBestScore = 0; int nBestHeight = g_signals.GetHeight().get_value_or(0); @@ -1473,10 +1473,10 @@ void static StartSync(const vector &vNodes) { (pnode->nStartingHeight > (nBestHeight - 144)) && (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) { // if ok, compare node's score with the best so far - double dScore = NodeSyncScore(pnode); - if (pnodeNewSync == NULL || dScore > dBestScore) { + int64_t nScore = NodeSyncScore(pnode); + if (pnodeNewSync == NULL || nScore > nBestScore) { pnodeNewSync = pnode; - dBestScore = dScore; + nBestScore = nScore; } } } From aab2c0fd7e7f629b20192ab9f05b281e5783cacc Mon Sep 17 00:00:00 2001 From: Huang Le <4tarhl@gmail.com> Date: Sat, 31 May 2014 01:23:53 +0800 Subject: [PATCH 099/336] Remove template matching params from GetOpName() Since they are not real opcodes, being reported as OP_UNKNOWN is less confusing for human-readable decoding. Signed-off-by: Huang Le <4tarhl@gmail.com> --- src/script.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index ac6d4b316f..381e84d0b7 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -208,14 +208,13 @@ const char* GetOpName(opcodetype opcode) case OP_NOP9 : return "OP_NOP9"; case OP_NOP10 : return "OP_NOP10"; - - - // template matching params - case OP_PUBKEYHASH : return "OP_PUBKEYHASH"; - case OP_PUBKEY : return "OP_PUBKEY"; - case OP_SMALLDATA : return "OP_SMALLDATA"; - case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; + + // Note: + // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum + // as kind of implementation hack, they are *NOT* real opcodes. If found in real + // Script, just let the default: case deal with them. + default: return "OP_UNKNOWN"; } From cb7a3edc3d60311752e8f76c0302ffd0a1fd0eb9 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 31 May 2014 12:04:34 +0200 Subject: [PATCH 100/336] remove dup of extern int nConnectTimeout; in netbase --- src/netbase.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/netbase.h b/src/netbase.h index f5a64cb51f..23cfb1f158 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -17,6 +17,7 @@ #include extern int nConnectTimeout; +extern bool fNameLookup; #ifdef WIN32 // In MSVC, this is defined as a macro, undefine it to prevent a compile and link error @@ -33,9 +34,6 @@ enum Network NET_MAX, }; -extern int nConnectTimeout; -extern bool fNameLookup; - /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ class CNetAddr { From 223a6f7800c67696c01cf142e263a6593fa56e55 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Sun, 1 Jun 2014 15:25:21 +0200 Subject: [PATCH 101/336] Fix stray uppercase A in tx_valid.json. --- src/test/data/tx_valid.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index 1f51d3ce55..0757496c89 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -16,7 +16,7 @@ ["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], ["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], -"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], From 11ef78f1150f6b10a97f4f4e9b508308ac7581d9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 1 Jun 2014 16:25:02 +0200 Subject: [PATCH 102/336] Periodic language update Pull updated translations from Transifex before 0.9.2 --- src/qt/locale/bitcoin_da.ts | 566 ++++++++++++++++----------------- src/qt/locale/bitcoin_ko_KR.ts | 74 ++--- src/qt/locale/bitcoin_nb.ts | 6 +- src/qt/locale/bitcoin_zh_CN.ts | 82 ++--- 4 files changed, 365 insertions(+), 363 deletions(-) diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index b13b38a878..a0514035fd 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -3,11 +3,11 @@ AboutDialog About Bitcoin Core - + Om Bitcoin Core <b>Bitcoin Core</b> version - + <b>Bitcoin Core</b> version @@ -29,11 +29,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open The Bitcoin Core developers - + Udviklerne af Bitcoin Core (%1-bit) - + (%1-bit)
@@ -48,7 +48,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &New - &Ny + Ny Copy the currently selected address to the system clipboard @@ -56,11 +56,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Copy - &Kopiér + Kopiér C&lose - + Luk &Copy Address @@ -84,15 +84,15 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Choose the address to send coins to - + Vælg adresse at sende bitcoins til Choose the address to receive coins with - + Vælg adresse at modtage bitcoins med C&hoose - + Vælg Sending addresses @@ -108,7 +108,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. - + Dette er dine Bitcoin-adresser til at modtage betalinger med. Det anbefales are bruge en ny modtagelsesadresse for hver transaktion. Copy &Label @@ -120,7 +120,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Export Address List - + Eksportér adresseliste Comma separated file (*.csv) @@ -128,11 +128,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Exporting Failed - + Eksport mislykkedes There was an error trying to save the address list to %1. - + En fejl opstod under gemning af adresseliste til %1. @@ -273,7 +273,7 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Node - + Knude Show general overview of wallet @@ -325,15 +325,15 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open &Sending addresses... - &Afsendelsesadresser... + Afsendelsesadresser … &Receiving addresses... - &Modtagelsesadresser... + Modtagelsesadresser … Open &URI... - + Åbn URI … Importing blocks from disk... @@ -433,31 +433,31 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open Request payments (generates QR codes and bitcoin: URIs) - + Forespørg betalinger (genererer QR-koder og "bitcoin:"-URI'er) &About Bitcoin Core - + Om Bitcoin Core Show the list of used sending addresses and labels - + Vis listen over brugte afsendelsesadresser og -mærkater Show the list of used receiving addresses and labels - + Vis listen over brugte modtagelsesadresser og -mærkater Open a bitcoin: URI or payment request - + Åbn en "bitcoin:"-URI eller betalingsforespørgsel &Command-line options - + Tilvalg for kommandolinje Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options - + Vis Bitcoin Core hjælpebesked for at få en liste over mulige tilvalg for Bitcoin kommandolinje Bitcoin client @@ -493,11 +493,11 @@ Produktet indeholder software som er udviklet af OpenSSL Project til brug i Open %1 and %2 - + %1 og %2 %n year(s) - + %n år%n år %1 behind @@ -575,15 +575,15 @@ Adresse: %4 CoinControlDialog Coin Control Address Selection - + Adressevalg for coin-styring Quantity: - + Mængde: Bytes: - + Byte: Amount: @@ -591,35 +591,35 @@ Adresse: %4 Priority: - + Prioritet: Fee: - + Gebyr: Low Output: - + Lavt output: After Fee: - + Efter gebyr: Change: - + Byttepenge: (un)select all - + (af)vælg alle Tree mode - + Trætilstand List mode - + Listetilstand Amount @@ -635,7 +635,7 @@ Adresse: %4 Confirmations - + Bekræftelser Confirmed @@ -643,151 +643,151 @@ Adresse: %4 Priority - + Prioritet Copy address - Kopier adresse + Kopiér adresse Copy label - Kopier mærkat + Kopiér mærkat Copy amount - Kopier beløb + Kopiér beløb Copy transaction ID - Kopier transaktionens ID + Kopiér transaktions-ID Lock unspent - + Fastlås ubrugte Unlock unspent - + Lås ubrugte op Copy quantity - + Kopiér mængde Copy fee - + Kopiér gebyr Copy after fee - + Kopiér efter-gebyr Copy bytes - + Kopiér byte Copy priority - + Kopiér prioritet Copy low output - + Kopiér lavt output Copy change - + Kopiér byttepenge highest - + højest higher - + højere high - + højt medium-high - + mellemhøj medium - + medium low-medium - + mellemlav low - + lav lower - + lavere lowest - + lavest (%1 locked) - + (%1 fastlåst) none - + ingen Dust - + Støv yes - + ja no - + nej This label turns red, if the transaction size is greater than 1000 bytes. - + Dette mærkat bliver rødt, hvis transaktionsstørrelsen er større end 1000 byte. This means a fee of at least %1 per kB is required. - + Dette betyder, at et gebyr på mindst %1 pr. kB er nødvendigt. Can vary +/- 1 byte per input. - + Kan variere ±1 byte pr. input. Transactions with higher priority are more likely to get included into a block. - + Transaktioner med højere prioritet har højere sansynlighed for at blive inkluderet i en blok. This label turns red, if the priority is smaller than "medium". - + Dette mærkat bliver rødt, hvis prioriteten er mindre end "medium". This label turns red, if any recipient receives an amount smaller than %1. - + Dette mærkat bliver rødt, hvis mindst én modtager et beløb mindre end %1. This means a fee of at least %1 is required. - + Dette betyder, at et gebyr på mindst %1 er nødvendigt. Amounts below 0.546 times the minimum relay fee are shown as dust. - + Beløb under 0,546 gange det minimale videreførselsgebyr vises som støv. This label turns red, if the change is smaller than %1. - + Dette mærkat bliver rødt, hvis byttepengene er mindre end %1. (no label) @@ -795,11 +795,11 @@ Adresse: %4 change from %1 (%2) - + byttepenge fra %1 (%2) (change) - + (byttepange) @@ -814,11 +814,11 @@ Adresse: %4 The label associated with this address list entry - + Mærkatet, der er associeret med denne indgang i adresselisten The address associated with this address list entry. This can only be modified for sending addresses. - + Adressen, der er associeret med denne indgang i adresselisten. Denne kan kune ændres for afsendelsesadresser. &Address @@ -884,7 +884,7 @@ Adresse: %4 HelpMessageDialog Bitcoin Core - Command-line options - + Bitcoin Core – tilvalg for kommandolinje Bitcoin Core @@ -908,7 +908,7 @@ Adresse: %4 Set language, for example "de_DE" (default: system locale) - Angiv sprog, f.eks "de_DE" (standard: systemlokalitet) + Angiv sprog, fx "da_DK" (standard: systemlokalitet) Start minimized @@ -916,15 +916,15 @@ Adresse: %4 Set SSL root certificates for payment request (default: -system-) - + Sæt SSL-rodcertifikater for betalingsforespørgsel (standard: -system-) Show splash screen on startup (default: 1) - Vis opstartsbillede ved start (standard: 1) + Vis opstartsbillede ved opstart (standard: 1) Choose data directory on startup (default: 0) - + Vælg datamappe ved opstart (standard: 0) @@ -935,15 +935,15 @@ Adresse: %4 Welcome to Bitcoin Core. - + Velkommen til Bitcoin Core. As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - + Siden dette er første gang, programmet startes, kan du vælge, hvor Bitcoin Core skal gemme sin data. Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. - + Bitcoin Core vil downloade og gemme et kopi af Bitcoin-blokkæden. Mindst %1 GB data vil blive gemt i denne mappe, og den vil vokse over tid. Tegnebogen vil også blive gemt i denne mappe. Use the default data directory @@ -959,7 +959,7 @@ Adresse: %4 Error: Specified data directory "%1" can not be created. - + Fejl: Angivet datamappe "%1" kan ikke oprettes. Error @@ -978,23 +978,23 @@ Adresse: %4 OpenURIDialog Open URI - + Åbn URI Open payment request from URI or file - + Åbn betalingsforespørgsel fra URI eller fil URI: - + URI: Select payment request file - + Vælg fil for betalingsforespørgsel Select payment request file to open - + Vælg fil for betalingsforespørgsel til åbning @@ -1025,39 +1025,39 @@ Adresse: %4 Size of &database cache - + Størrelsen på databasens cache MB - + MB Number of script &verification threads - + Antallet af scriptverificeringstråde Connect to the Bitcoin network through a SOCKS proxy. - + Forbind til Bitcoin-netværket gennem en SOCKS-proxy. &Connect through SOCKS proxy (default proxy): - + Forbind gennem SOCKS-proxy (standard-proxy): IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1) - + IP-adresse for proxyen (fx IPv4: 127.0.0.1 / IPv6: ::1) Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. - + Tredjeparts-URL'er (fx et blokhåndteringsværktøj), der vises i transaktionsfanen som genvejsmenupunkter. %s i URL'en erstattes med transaktionens hash. Flere URL'er separeres med en lodret streg |. Third party transaction URLs - + Tredjeparts-transaktions-URL'er Active command-line options that override above options: - + Aktuelle tilvalg for kommandolinjen, der tilsidesætter ovenstående tilvalg: Reset all client options to default. @@ -1073,27 +1073,27 @@ Adresse: %4 (0 = auto, <0 = leave that many cores free) - + (0 = auto, <0 = efterlad så mange kerner fri) W&allet - + Tegnebog Expert - + Ekspert Enable coin &control features - + Slå egenskaber for coin-styring til If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. - + Hvis du slår brug af ubekræftede byttepenge fra, kan byttepengene fra en transaktion ikke bruges, før pågældende transaktion har mindst én bekræftelse. Dette påvirker også måden hvorpå din saldo beregnes. &Spend unconfirmed change - + Brug ubekræftede byttepenge Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. @@ -1173,7 +1173,7 @@ Adresse: %4 Whether to show coin control features or not. - + Hvorvidt egenskaber for coin-styring skal vises eller ej. &OK @@ -1189,7 +1189,7 @@ Adresse: %4 none - + ingeningen Confirm options reset @@ -1197,15 +1197,15 @@ Adresse: %4 Client restart required to activate changes. - + Genstart af klienten er nødvendig for at aktivere ændringer. Client will be shutdown, do you want to proceed? - + Klienten vil blive lukket ned; vil du fortsætte? This change would require a client restart. - + Denne ændring vil kræve en genstart af klienten. The supplied proxy address is invalid. @@ -1228,7 +1228,7 @@ Adresse: %4 Available: - + Tilgængelig: Your current spendable balance @@ -1236,7 +1236,7 @@ Adresse: %4 Pending: - + Uafgjort: Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance @@ -1279,7 +1279,7 @@ Adresse: %4 Requested payment amount of %1 is too small (considered dust). - + Forespurgt betalingsbeløb på %1 er for lille (regnes som støv). Payment request error @@ -1291,27 +1291,27 @@ Adresse: %4 Net manager warning - + Net-håndterings-advarsel Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy. - + Din aktuelle proxy understøtter ikke SOCKS5, hvilket kræves for betalingsforespørgsler via proxy. Payment request fetch URL is invalid: %1 - + Betalingsforespørgslens hentnings-URL er ugyldig: %1 Payment request file handling - + Filhåndtering for betalingsanmodninger Payment request file can not be read or processed! This can be caused by an invalid payment request file. - + Betalingsanmodningsfil kan ikke indlæses eller bearbejdes! Dette kan skyldes en ugyldig betalingsanmodningsfil. Unverified payment requests to custom payment scripts are unsupported. - + Ikke-verificerede betalingsforespørgsler for tilpassede betalings-scripts understøttes ikke. Refund from %1 @@ -1319,19 +1319,19 @@ Adresse: %4 Error communicating with %1: %2 - + Fejl under kommunikation med %1: %2 Payment request can not be parsed or processed! - + Betalingsanmodning kan ikke fortolkes eller bearbejdes! Bad response from server %1 - + Fejlagtigt svar fra server %1 Payment acknowledged - + Betaling anerkendt Network request error @@ -1350,7 +1350,7 @@ Adresse: %4 Error: Cannot parse configuration file: %1. Only use key=value syntax. - + Fejl: Kan ikke fortolke konfigurationsfil: %1. Brug kun syntaksen nøgle=værdi. Error: Invalid combination of -regtest and -testnet. @@ -1358,7 +1358,7 @@ Adresse: %4 Bitcoin Core didn't yet exit safely... - + Bitcoin Core blev ikke afsluttet på sikker vis … Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -1369,11 +1369,11 @@ Adresse: %4 QRImageWidget &Save Image... - &Gem foto... + Gem billede … &Copy Image - &Kopiér foto + Kopiér foto Save QR Code @@ -1381,7 +1381,7 @@ Adresse: %4 PNG Image (*.png) - + PNG-billede (*.png) @@ -1404,11 +1404,11 @@ Adresse: %4 Debug window - + Fejlsøgningsvindue General - + Generelt Using OpenSSL version @@ -1456,23 +1456,23 @@ Adresse: %4 &Network Traffic - + Netværkstrafik &Clear - + Ryd Totals - + Totaler In: - + Indkommende: Out: - Ud: + Udgående: Build date @@ -1535,7 +1535,7 @@ Adresse: %4 ReceiveCoinsDialog &Amount: - &Mængde: + Beløb: &Label: @@ -1543,35 +1543,35 @@ Adresse: %4 &Message: - &Besked: + Besked: Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. - + Genbrug en af de tidligere brugte modtagelsesadresser. Genbrug af adresser har indflydelse på sikkerhed og privatliv. Brug ikke dette med mindre du genskaber en betalingsforespørgsel fra tidligere. R&euse an existing receiving address (not recommended) - + Genbrug en eksisterende modtagelsesadresse (anbefales ikke) An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network. - + En valgfri besked, der føjes til betalingsanmodningen, og som vil vises, når anmodningen åbnes. Bemærk: Beskeden vil ikke sendes med betalingen over Bitcoin-netværket. An optional label to associate with the new receiving address. - + Et valgfrit mærkat, der associeres med den nye modtagelsesadresse. Use this form to request payments. All fields are <b>optional</b>. - + Brug denne formular for at anmode om betalinger. Alle felter er <b>valgfri</b>. An optional amount to request. Leave this empty or zero to not request a specific amount. - + Et valgfrit beløb til anmodning. Lad dette felt være tomt eller indeholde nul for at anmode om et ikke-specifikt beløb. Clear all fields of the form. - Ryd alle fælter af formen. + Ryd alle felter af formen. Clear @@ -1579,35 +1579,35 @@ Adresse: %4 Requested payments history - + Historik over betalingsanmodninger &Request payment - &Anmod betaling + Anmod om betaling Show the selected request (does the same as double clicking an entry) - + Vis den valgte forespørgsel (gør det samme som dobbeltklik på en indgang) Show - + Vis Remove the selected entries from the list - + Fjern de valgte indgange fra listen Remove - + Fjern Copy label - Kopier mærkat + Kopiér mærkat Copy message - + Kopiér besked Copy amount @@ -1618,23 +1618,23 @@ Adresse: %4 ReceiveRequestDialog QR Code - QR Kode + QR-kode Copy &URI - Kopiér &URL + Kopiér URI Copy &Address - Kopiér &Adresse + Kopiér adresse &Save Image... - &Gem foto... + Gem billede … Request payment to %1 - + Anmod om betaling til %1 Payment information @@ -1666,7 +1666,7 @@ Adresse: %4 Error encoding URI into QR Code. - Fejl ved kodning fra URI til QR-kode + Fejl ved kodning fra URI til QR-kode. @@ -1693,11 +1693,11 @@ Adresse: %4 (no message) - + (ingen besked) (no amount) - + (intet beløb) @@ -1708,27 +1708,27 @@ Adresse: %4 Coin Control Features - + Egenskaber for coin-styring Inputs... - + Inputs … automatically selected - + valgt automatisk Insufficient funds! - + Utilstrækkelige midler! Quantity: - + Mængde: Bytes: - + Byte: Amount: @@ -1736,31 +1736,31 @@ Adresse: %4 Priority: - + Prioritet: Fee: - + Gebyr: Low Output: - + Lavt output: After Fee: - + Efter gebyr: Change: - + Byttepenge: If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - + Hvis dette aktiveres, men byttepengeadressen er tom eller ugyldig, vil byttepenge blive sendt til en nygenereret adresse. Custom change address - + Tilpasset byttepengeadresse Send to multiple recipients at once @@ -1772,7 +1772,7 @@ Adresse: %4 Clear all fields of the form. - Ryd alle fælter af formen. + Ryd alle felter af formen. Clear &All @@ -1796,11 +1796,11 @@ Adresse: %4 %1 to %2 - + %1 til %2 Copy quantity - + Kopiér mængde Copy amount @@ -1808,35 +1808,35 @@ Adresse: %4 Copy fee - + Kopiér gebyr Copy after fee - + Kopiér efter-gebyr Copy bytes - + Kopiér byte Copy priority - + Kopiér prioritet Copy low output - + Kopiér lavt output Copy change - + Kopiér byttepenge Total Amount %1 (= %2) - + Totalbeløb %1 (= %2) or - + eller The recipient address is not valid, please recheck. @@ -1860,15 +1860,15 @@ Adresse: %4 Transaction creation failed! - + Oprettelse af transaktion mislykkedes! The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - + Transaktionen blev afvist! Dette kan ske, hvis nogle af dine bitcoins i din tegnebog allerede er brugt, som hvis du brugte en kopi af wallet.dat og dine bitcoins er blevet brugt i kopien, men ikke er markeret som brugt her. Warning: Invalid Bitcoin address - + Advarsel: Ugyldig Bitcoin-adresse (no label) @@ -1876,7 +1876,7 @@ Adresse: %4 Warning: Unknown change address - + Advarsel: Ukendt byttepengeadresse Are you sure you want to send? @@ -1892,7 +1892,7 @@ Adresse: %4 Invalid payment address %1 - + Ugyldig betalingsadresse %1 @@ -1919,11 +1919,11 @@ Adresse: %4 Choose previously used address - + Vælg tidligere brugt adresse This is a normal payment. - + Dette er en normal betaling. Alt+A @@ -1939,7 +1939,7 @@ Adresse: %4 Remove this entry - + Fjern denne indgang Message: @@ -1947,38 +1947,38 @@ Adresse: %4 This is a verified payment request. - + Dette er en verificeret betalingsforespørgsel. Enter a label for this address to add it to the list of used addresses - + Indtast et mærkat for denne adresse for at føje den til listen over brugte adresser A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network. - + En besked, som blev føjet til "bitcon:"-URI'en, som vil gemmes med transaktionen til din reference. Bemærk: Denne besked vil ikke blive sendt over Bitcoin-netværket. This is an unverified payment request. - + Dette er en ikke-verificeret betalingsforespørgsel. Pay To: - + Betal til: Memo: - + Memo: ShutdownWindow Bitcoin Core is shutting down... - + Bitcoin Core lukker ned … Do not shut down the computer until this window disappears. - + Luk ikke computeren ned, før dette vindue forsvinder. @@ -2001,7 +2001,7 @@ Adresse: %4 Choose previously used address - + Vælg tidligere brugt adresse Alt+A @@ -2132,7 +2132,7 @@ Adresse: %4 The Bitcoin Core developers - + Udviklerne af Bitcoin Core [testnet] @@ -2154,7 +2154,7 @@ Adresse: %4 conflicted - + konflikt %1/offline @@ -2242,11 +2242,11 @@ Adresse: %4 Merchant - + Forretningsdrivende Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours. - + Udvundne bitcoins skal modne %1 blokke, før de kan bruges. Da du genererede denne blok, blev den udsendt til netværket for at blive føjet til blokkæden. Hvis det ikke lykkes at få den i kæden, vil dens tilstand ændres til "ikke accepteret", og den vil ikke kunne bruges. Dette kan ske nu og da, hvis en anden knude udvinder en blok inden for nogle få sekunder fra din. Debug information @@ -2316,7 +2316,7 @@ Adresse: %4 Immature (%1 confirmations, will be available after %2) - + Umoden (%1 bekræftelser; vil være tilgængelig efter %2) Open for %n more block(s) @@ -2340,19 +2340,19 @@ Adresse: %4 Offline - + Offline Unconfirmed - + Ubekræftet Confirming (%1 of %2 recommended confirmations) - + Bekræfter (%1 af %2 anbefalede bekræftelser) Conflicted - + Konflikt Received with @@ -2483,23 +2483,23 @@ Adresse: %4 Export Transaction History - + Historik for eksport af transaktioner Exporting Failed - + Eksport mislykkedes There was an error trying to save the transaction history to %1. - + En fejl opstod under gemning af transaktionshistorik til %1. Exporting Successful - + Eksport problemfri The transaction history was successfully saved to %1. - + Transaktionshistorikken blev gemt til %1 med succes. Comma separated file (*.csv) @@ -2546,7 +2546,7 @@ Adresse: %4 WalletFrame No wallet has been loaded. - + Ingen tegnebog er indlæst. @@ -2580,11 +2580,11 @@ Adresse: %4 There was an error trying to save the wallet data to %1. - + Der skete en fejl under gemning af tegnebogsdata til %1. The wallet data was successfully saved to %1. - + Tegnebogsdata blev gemt til %1 med succes. Backup Successful @@ -2659,7 +2659,7 @@ Adresse: %4 Bitcoin Core RPC client version - + Bitcoin Core RPC-klient-version Run in the background as a daemon and accept commands @@ -2699,7 +2699,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH) - + Accepterede krypteringer (standard: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH) An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s @@ -2711,19 +2711,19 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15) - + Rate-begræns kontinuerligt frie transaktioner til <n>*1000 byte i minuttet (standard:15) Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development. - + Start regressionstesttilstand, som bruger en speciel kæde, hvor blokke kan løses med det samme. Dette er tiltænkt til testværktøjer for regression of programudvikling. Enter regression test mode, which uses a special chain in which blocks can be solved instantly. - + Start regressionstesttilstand, som bruger en speciel kæde, hvor blokke kan løses med det samme. Error: Listening for incoming connections failed (listen returned error %d) - + Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning returnerede fejl %d) Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. @@ -2739,27 +2739,27 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Fees smaller than this are considered zero fee (for transaction creation) (default: - + Gebyrer mindre end dette opfattes som nul-gebyr (for oprettelse af transaktioner) (standard: Flush database activity from memory pool to disk log every <n> megabytes (default: 100) - + Flyt databaseaktivitet fra hukommelsespulje til disklog hver <n> megabytes (standard: 100) How thorough the block verification of -checkblocks is (0-4, default: 3) - + Hvor gennemarbejdet blokverificeringen for -checkblocks er (0-4; standard: 3) In this mode -genproclimit controls how many blocks are generated immediately. - + I denne tilstand styrer -genproclimit hvor mange blokke, der genereres med det samme. Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) - + Sæt antallet af scriptverificeringstråde (%u til %d, 0 = auto, <0 = efterlad det antal kernet fri, standard: %d) Set the processor limit for when generation is on (-1 = unlimited, default: -1) - + Sæt processorbegrænsning for når generering er slået til (-1 = ubegrænset, standard: -1) This is a pre-release test build - use at your own risk - do not use for mining or merchant applications @@ -2767,11 +2767,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Unable to bind to %s on this computer. Bitcoin Core is probably already running. - + Ikke i stand til at tildele til %s på denne computer. Bitcoin Core kører sansynligvis allerede. Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy) - + Brug separat SOCS5-proxy for at nå andre knuder via Tor skjulte tjenester (standard: -proxy) Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction. @@ -2799,15 +2799,15 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com (default: 1) - + (standard: 1) (default: wallet.dat) - + (standard: wallet.dat) <category> can be: - + <kategori> kan være: Attempt to recover private keys from a corrupt wallet.dat @@ -2815,7 +2815,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Bitcoin Core Daemon - + Bitcoin Core-tjeneste Block creation options: @@ -2823,7 +2823,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Clear list of wallet transactions (diagnostic tool; implies -rescan) - + Ryd liste over transaktioner i tegnebog (diagnoseværktøj; medfører -rescan) Connect only to the specified node(s) @@ -2831,15 +2831,15 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Connect through SOCKS proxy - + Forbind gennem SOCKS-proxy Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) - + Forbind til JSON-RPC på <port> (standard: 8332 eller testnetværk: 18332) Connection options: - + Tilvalg for forbindelser: Corrupted block database detected @@ -2847,11 +2847,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Debugging/Testing options: - + Tilvalg for fejlfinding/test: Disable safemode, override a real safe mode event (default: 0) - + Slå sikker tilstand fra, tilsidesæt hændelser fra sikker tilstand (standard: 0) Discover own IP address (default: 1 when listening and no -externalip) @@ -2859,7 +2859,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Do not load the wallet and disable wallet RPC calls - + Indlæs ikke tegnebogen og slå tegnebogs-RPC-kald fra Do you want to rebuild the block database now? @@ -2939,11 +2939,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Fee per kB to add to transactions you send - + Føj gebyr pr. kB til transaktioner, du sender Fees smaller than this are considered zero fee (for relaying) (default: - + Gebyrer mindre end dette opfattes som nul-gebyr (for videreførsler) (standard: Find peers using DNS lookup (default: 1 unless -connect) @@ -2951,7 +2951,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Force safe mode (default: 0) - + Gennemtving sikker tilstand (standard: 0) Generate coins (default: 0) @@ -2963,11 +2963,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com If <category> is not supplied, output all debugging information. - + Hvis <kategori> ikke angives, udskriv al fejlsøgningsinformation. Importing... - + Importerer … Incorrect or no genesis block found. Wrong datadir for network? @@ -2975,7 +2975,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Invalid -onion address: '%s' - + Ugyldig -onion adresse: "%s" Not enough file descriptors available. @@ -2983,11 +2983,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Prepend debug output with timestamp (default: 1) - + Føj tidsstempel foran fejlsøgningsoutput (standard: 1) RPC client options: - + Tilvalg for RPC-klient: Rebuild block chain index from current blk000??.dat files @@ -2995,15 +2995,15 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Select SOCKS version for -proxy (4 or 5, default: 5) - + Vælg SOCKS-version for -proxy (4 eller 5, standard: 5) Set database cache size in megabytes (%d to %d, default: %d) - + Sæt cache-størrelse for database i megabytes (%d til %d; standard: %d) Set maximum block size in bytes (default: %d) - + Sæt maksimum blokstørrelse i byte (standard: %d) Set the number of threads to service RPC calls (default: 4) @@ -3015,15 +3015,15 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Spend unconfirmed change when sending transactions (default: 1) - + Brug ubekræftede byttepenge under afsendelse af transaktioner (standard: 1) This is intended for regression testing tools and app development. - + This is intended for regression testing tools and app development. Usage (deprecated, use bitcoin-cli): - + Brug (forældet, brug bitcoin-cli): Verifying blocks... @@ -3035,7 +3035,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Wait for RPC server to start - + Vent på opstart af RPC-server Wallet %s resides outside data directory %s @@ -3043,11 +3043,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Wallet options: - + Tilvalg for tegnebog: Warning: Deprecated argument -debugnet ignored, use -debug=net - + Advarsel: Forældet argument -debugnet ignoreret; brug -debug=net You need to rebuild the database using -reindex to change -txindex @@ -3059,7 +3059,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - + Kan ikke opnå en lås på datamappe %s. Bitcoin Core kører sansynligvis allerede. Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) @@ -3067,11 +3067,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Output debugging information (default: 0, supplying <category> is optional) - + Udskriv fejlsøgningsinformation (standard: 0, angivelse af <kategori> er valgfri) Set maximum size of high-priority/low-fee transactions in bytes (default: %d) - + Sæt maksimumstørrelse for højprioritet/lavgebyr-transaktioner i byte (standard: %d) Information @@ -3087,11 +3087,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Limit size of signature cache to <n> entries (default: 50000) - + Begræns størrelsen på signaturcache til <n> indgange (standard: 50000) Log transaction priority and fee per kB when mining blocks (default: 0) - + Prioritet for transaktionslog og gebyr pr. kB under udvinding af blokke (standard: 0) Maintain a full transaction index (default: 0) @@ -3115,31 +3115,31 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Print block on startup, if found in block index - + Udskriv blok under opstart, hvis den findes i blokindeks Print block tree on startup (default: 0) - + Udskriv bloktræ under startop (standard: 0) RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) - + Tilvalg for RPC SSL: (se Bitcoin Wiki for instruktioner i SSL-opstart) RPC server options: - + Tilvalg for RPC-server: Randomly drop 1 of every <n> network messages - + Drop tilfældigt 1 ud af hver <n> netværksbeskeder Randomly fuzz 1 of every <n> network messages - + Slør tilfældigt 1 ud af hver <n> netværksbeskeder Run a thread to flush wallet periodically (default: 1) - + Kør en tråd for at rydde tegnebog periodisk (standard: 1) SSL options: (see the Bitcoin Wiki for SSL setup instructions) @@ -3147,7 +3147,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Send command to Bitcoin Core - + Send kommando til Bitcoin Core Send trace/debug info to console instead of debug.log file @@ -3159,15 +3159,15 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Sets the DB_PRIVATE flag in the wallet db environment (default: 1) - + Sætter DB_PRIVATE-flaget i tegnebogens db-miljø (standard: 1) Show all debugging options (usage: --help -help-debug) - + Vis alle tilvalg for fejlsøgning (brug: --help -help-debug) Show benchmark information (default: 0) - + Vis information om ydelsesmåling (standard: 0) Shrink debug.log file on client startup (default: 1 when no -debug) @@ -3183,7 +3183,7 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Start Bitcoin Core Daemon - + Start Bitcoin Core-tjeneste System error: @@ -3223,11 +3223,11 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com Zapping all transactions from wallet... - + Zapper alle transaktioner fra tegnebog … on startup - + under opstart version diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index 8e2b681ba9..ce30a8603d 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -40,7 +40,7 @@ MIT/X11 프로그램 라이선스에 따라 배포합니다. COPYING 또는 http AddressBookPage Double-click to edit address or label - 주소 또는 표를 편집하기 위해 더블클릭 하시오 + 지갑 주소나 제목을 수정하려면 더블클릭하세요. Create a new address @@ -755,7 +755,7 @@ Address: %4 This label turns red, if the transaction size is greater than 1000 bytes. - + 만약 거래 양이 1000bytes 보다 크면 제목이 빨간색으로 변합니다 This means a fee of at least %1 per kB is required. @@ -771,11 +771,11 @@ Address: %4 This label turns red, if the priority is smaller than "medium". - + 우선권이 중간보다 작으면 제목이 빨간색으로 변합니다. This label turns red, if any recipient receives an amount smaller than %1. - + 만약 수령인이 받은 액수가 잔고의 1%보다 작으면 이 제목이 빨간색으로 변합니다. This means a fee of at least %1 is required. @@ -787,7 +787,7 @@ Address: %4 This label turns red, if the change is smaller than %1. - + 만약 잔돈이 1%보다 작다면 제목이 빨간색으로 변합니다 (no label) @@ -1053,7 +1053,7 @@ Address: %4 Third party transaction URLs - + 제 3자 거래 URLs Active command-line options that override above options: @@ -1093,7 +1093,7 @@ Address: %4 &Spend unconfirmed change - + &확인되지 않은 돈을 쓰다 Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. @@ -1303,7 +1303,7 @@ Address: %4 Payment request file handling - + 지불이 파일 처리를 요청합니다 Payment request file can not be read or processed! This can be caused by an invalid payment request file. @@ -1354,7 +1354,7 @@ Address: %4 Error: Invalid combination of -regtest and -testnet. - + 오류: 잘못된 -regtest 와 -testnet의 조합입니다. Bitcoin Core didn't yet exit safely... @@ -1460,7 +1460,7 @@ Address: %4 &Clear - + &지우기 Totals @@ -1712,7 +1712,7 @@ Address: %4 Inputs... - + 입력... automatically selected @@ -1864,7 +1864,7 @@ Address: %4 The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - + 거래가 거부되었습니다. 몇몇 코인들이 지갑에서 이미 사용된 경우, 예를 들어 코인을 이미 사용한 wallet.dat를 복사해서 사용한 경우 지금 지갑에 기록이 안되있어 이런 일이 생길 수 있습니다. Warning: Invalid Bitcoin address @@ -2651,7 +2651,7 @@ Address: %4 Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332) - + 포트 <port>을 통해 JSON-RPC 연결 (기본값: 8332 또는 testnet: 18332) Accept command line and JSON-RPC commands @@ -2693,7 +2693,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s - + IPv6 연결을 위해 RPC port %u 설정 중 오류가 발생했습니다. IPv4: %s 환경으로 돌아갑니다. Bind to given address and always listen on it. Use [host]:port notation for IPv6 @@ -2717,7 +2717,9 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. - + 에러: 거래가 거부되었습니다! 이런 일이 생길 수 있습니다 만약 몇개의 코인들을 지갑에서 이미 사용했다면요, 예를 들어 만약 당신이 wallet.dat를 복사해서 사용했거나 코인들을 사용 후에 복사했다면 여기선 표시가 안되서 사용할 수 없습니다 + +-번역은 했으나 약간 이상한점이 있어서 수정해야함- Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! @@ -2725,7 +2727,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) - + 지갑 거래가 바뀌면 명령을 실행합니다.(%s 안의 명령어가 TxID로 바뀝니다) Fees smaller than this are considered zero fee (for transaction creation) (default: @@ -2841,7 +2843,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Disable safemode, override a real safe mode event (default: 0) - + 안전 모드를 비활성화하고 안전 모드의 이벤트가 발생하더라도 무시합니다. (기본값: 0, 비활성화) Discover own IP address (default: 1 when listening and no -externalip) @@ -2861,7 +2863,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Error initializing wallet database environment %s! - + 지갑 데이터베이스 환경 초기화하는데 오류 Error loading block database @@ -2961,7 +2963,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Incorrect or no genesis block found. Wrong datadir for network? - + 올바르지 않거나 생성된 블록을 찾을 수 없습니다. 잘못된 네트워크 자료 디렉토리? Invalid -onion address: '%s' @@ -3053,7 +3055,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) - + 이 사항과 관련있는 경고가 발생하거나 아주 긴 포크가 발생했을 때 명령어를 실행해 주세요. (cmd 명령어 목록에서 %s는 메시지로 대체됩니다) Output debugging information (default: 0, supplying <category> is optional) @@ -3061,7 +3063,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Set maximum size of high-priority/low-fee transactions in bytes (default: %d) - + 최대 크기를 최우선으로 설정 / 바이트당 최소 수수료로 거래(기본값: %d) Information @@ -3077,11 +3079,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Limit size of signature cache to <n> entries (default: 50000) - + <n>번 째 순서에서 전자서명 캐쉬의 용량을 제한합니다. (기본값: 50000) Log transaction priority and fee per kB when mining blocks (default: 0) - + 블럭을 채굴할 때 kB당 거래 우선 순위와 수수료를 로그에 남깁니다. (기본값: 0, 비활성화) Maintain a full transaction index (default: 0) @@ -3089,11 +3091,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000) - + 최대 연결마다 1000bytes 버퍼를 받는다. (기본값: 5000) Maximum per-connection send buffer, <n>*1000 bytes (default: 1000) - + 최대 연결 마다 1000bytes 버퍼를 보낸다.(기본값: 1000) Only accept block chain matching built-in checkpoints (default: 1) @@ -3101,27 +3103,27 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Only connect to nodes in network <net> (IPv4, IPv6 or Tor) - + 노드가 있는 네트워크에만 접속 합니다(IPv4, IPv6 또는 Tor) Print block on startup, if found in block index - + 블럭 색인을 발견하면 구동 시 블럭을 출력합니다. Print block tree on startup (default: 0) - + 구동 시 블럭 트리를 출력합니다. (기본값: 0, 비활성화) RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) - + RPC SSL 옵션: (비트코인 위키의 SSL 설정 설명서 참고) RPC server options: - + RPC 서버 설정 Randomly drop 1 of every <n> network messages - + 모든 네트워크 메시지 마다 무작위로 1이 떨어진다 Randomly fuzz 1 of every <n> network messages @@ -3137,7 +3139,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Send command to Bitcoin Core - + 비트코인 코어로 명령 보내기 Send trace/debug info to console instead of debug.log file @@ -3149,15 +3151,15 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Sets the DB_PRIVATE flag in the wallet db environment (default: 1) - + 전자지갑 데이터베이스 환경에 DB_PRIVATE 플래그를 설정합니다. (기본값: 1, 활성화) Show all debugging options (usage: --help -help-debug) - + 모든 디버그 설정 보기(설정: --help -help-debug) Show benchmark information (default: 0) - + 벤치마크 정보 보기(기본값: 0) Shrink debug.log file on client startup (default: 1 when no -debug) @@ -3217,7 +3219,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. on startup - + 구동 중 version diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 1267ad65b9..9e38c69c60 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -599,7 +599,7 @@ Adresse: %4 Low Output: - Lav Utdata: + Svake Utdata: After Fee: @@ -1744,7 +1744,7 @@ Adresse: %4 Low Output: - Svak Utdata: + Svake Utdata: After Fee: @@ -2730,7 +2730,7 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@ Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds! - Feil: Denne transaksjonen trenger en gebyr på minst %s på grunn av beløpet, kompleksiteten eller bruk av allerede mottatte penger! + Feil: Denne transaksjonen trenger et gebyr på minst %s på grunn av beløpet, kompleksiteten eller bruk av allerede mottatte penger! Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index ea98c4e4b1..b87d27fe12 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -917,7 +917,7 @@ Address: %4 Set SSL root certificates for payment request (default: -system-) - + 设置SSL根证书的付款请求(默认:-系统-) Show splash screen on startup (default: 1) @@ -1050,11 +1050,11 @@ Address: %4 Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |. - + 出现在交易的选项卡的上下文菜单项的第三方网址 (例如:区块链接查询) 。 %s的URL被替换为交易哈希。多个的URL需要竖线 | 分隔。 Third party transaction URLs - + 第三方交易网址 Active command-line options that override above options: @@ -1074,7 +1074,7 @@ Address: %4 (0 = auto, <0 = leave that many cores free) - + (0 = 自动, <0 = 离开很多免费的核心) W&allet @@ -1086,7 +1086,7 @@ Address: %4 Enable coin &control features - + 启动货币 &控制功能 If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed. @@ -1094,7 +1094,7 @@ Address: %4 &Spend unconfirmed change - + &选择未经确认的花费 Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled. @@ -1351,7 +1351,7 @@ Address: %4 Error: Cannot parse configuration file: %1. Only use key=value syntax. - + 错误: 无法解析配置文件: %1. 只有钥匙=重要的私匙. Error: Invalid combination of -regtest and -testnet. @@ -1359,7 +1359,7 @@ Address: %4 Bitcoin Core didn't yet exit safely... - + 比特币核心钱包没有安全退出.... Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) @@ -2667,7 +2667,7 @@ Address: %4 Bitcoin Core RPC client version - + 比特币核心钱包RPC客户端版本 Run in the background as a daemon and accept commands @@ -2722,7 +2722,7 @@ rpcpassword=%s Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15) - + 自由交易不断的速率限制为<n>*1000 字节每分钟(默认值:15) Enter regression test mode, which uses a special chain in which blocks can be solved instantly. This is intended for regression testing tools and app development. @@ -2734,7 +2734,7 @@ rpcpassword=%s Error: Listening for incoming connections failed (listen returned error %d) - + 错误: 监听接收连接失败 (监听错误 %d) Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here. @@ -2750,27 +2750,27 @@ rpcpassword=%s Fees smaller than this are considered zero fee (for transaction creation) (default: - + 比这手续费更小的被认为零手续费 (交易产生) (默认: Flush database activity from memory pool to disk log every <n> megabytes (default: 100) - + 从缓冲池清理磁盘数据库活动日志每<n>兆字节 (默认值: 100) How thorough the block verification of -checkblocks is (0-4, default: 3) - + 如何有效的验证checkblocks区块(0-4, 默认值: 3) In this mode -genproclimit controls how many blocks are generated immediately. - + 在-genproclimit这种模式下控制产出多少区块 Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d) - + 设置脚本验证的程序 (%u 到 %d, 0 = 自动, <0 = 保留自由的核心, 默认值: %d) Set the processor limit for when generation is on (-1 = unlimited, default: -1) - + 设置处理器生成的限制 (-1 = 无限, 默认值: -1) This is a pre-release test build - use at your own risk - do not use for mining or merchant applications @@ -2778,7 +2778,7 @@ rpcpassword=%s Unable to bind to %s on this computer. Bitcoin Core is probably already running. - + 无法 %s的绑定到电脑上,比特币核心钱包可能已经在运行。 Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy) @@ -2810,11 +2810,11 @@ rpcpassword=%s (default: 1) - + (默认值: 1) (default: wallet.dat) - + (默认: wallet.dat) <category> can be: @@ -2850,7 +2850,7 @@ rpcpassword=%s Connection options: - + 连接选项: Corrupted block database detected @@ -2858,11 +2858,11 @@ rpcpassword=%s Debugging/Testing options: - + 调试/测试选项: Disable safemode, override a real safe mode event (default: 0) - + 禁止使用安全模式,重新写入一个真正的安全模式日志(默认值: 0) Discover own IP address (default: 1 when listening and no -externalip) @@ -2954,7 +2954,7 @@ rpcpassword=%s Fees smaller than this are considered zero fee (for relaying) (default: - + 比这手续费更小的被认为零手续费 (中继) (默认值: Find peers using DNS lookup (default: 1 unless -connect) @@ -2962,7 +2962,7 @@ rpcpassword=%s Force safe mode (default: 0) - + 强制安全模式(默认值: 0) Generate coins (default: 0) @@ -3010,7 +3010,7 @@ rpcpassword=%s Set database cache size in megabytes (%d to %d, default: %d) - + 设置以MB为单位的数据库缓存大小(%d 到 %d, 默认值: %d) Set maximum block size in bytes (default: %d) @@ -3070,7 +3070,7 @@ rpcpassword=%s Cannot obtain a lock on data directory %s. Bitcoin Core is probably already running. - + 无法获取数据目录的 %s. 比特币核心钱包可能已经在运行. Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message) @@ -3098,11 +3098,11 @@ rpcpassword=%s Limit size of signature cache to <n> entries (default: 50000) - + 签名缓冲大小限制每<n> 条目 (默认值: 50000) Log transaction priority and fee per kB when mining blocks (default: 0) - + 开采区块时,日志优先级和手续费每KB (默认值: 0) Maintain a full transaction index (default: 0) @@ -3126,15 +3126,15 @@ rpcpassword=%s Print block on startup, if found in block index - + 如果在搜索区块中找到,请启动打印区块 Print block tree on startup (default: 0) - 启动时打印块树 (默认: 0) + 启动时打印区块树 (默认值: 0) RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions) - + RPC SSL选项:(见有关比特币设置用于SSL说明的维基百科) RPC server options: @@ -3142,15 +3142,15 @@ rpcpassword=%s Randomly drop 1 of every <n> network messages - + 随机每1个丢失测试<n>网络信息 Randomly fuzz 1 of every <n> network messages - + 随机每1个模拟测试<n>网络信息 Run a thread to flush wallet periodically (default: 1) - + 运行一个程序,定时清理钱包 (默认值:1) SSL options: (see the Bitcoin Wiki for SSL setup instructions) @@ -3158,7 +3158,7 @@ rpcpassword=%s Send command to Bitcoin Core - + 发送指令到比特币核心钱包 Send trace/debug info to console instead of debug.log file @@ -3170,15 +3170,15 @@ rpcpassword=%s Sets the DB_PRIVATE flag in the wallet db environment (default: 1) - + 设置DB_PRIVATE钱包标志DB环境 (默认值: 1) Show all debugging options (usage: --help -help-debug) - + 显示所有调试选项 (用法: --帮助 -帮助调试) Show benchmark information (default: 0) - + 显示标准信息 (默认值: 0) Shrink debug.log file on client startup (default: 1 when no -debug) @@ -3194,7 +3194,7 @@ rpcpassword=%s Start Bitcoin Core Daemon - + 开启比特币核心钱包守护进程 System error: @@ -3238,7 +3238,7 @@ rpcpassword=%s on startup - + 启动中 version From 516053c349f8abde09597962f4dd3958a2825177 Mon Sep 17 00:00:00 2001 From: Tawanda Kembo Date: Thu, 22 May 2014 13:19:51 +0200 Subject: [PATCH 103/336] Make links on 'About Bitcoin Core' into clickable (squashed 5 comits into one) Made the following links clickable: http://www.opensource.org/licenses/mit-license.php http://www.openssl.org/ eay@cryptsoft.com (Squashed commits into one commit as suggested by @laanwj) Replaced label with text browser on About Bitcoin Core Screen So that the links on the About screen can be clickable Replaced html property with text property I have now removed unnecessary html so this should make life easier for translators and you @Diapolo :). What do you think? The size of the window needs to change The size of the window needs to change when you make links clickable. Thanks for pointing that out @laanwj Using the https://www.openssl.org over the http link Using the https://www.openssl.org over the http link as suggested by @Diapolo --- src/qt/forms/aboutdialog.ui | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index 3ab4675bf3..fec63f737a 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -110,9 +110,12 @@ This is experimental software. -Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. +Distributed under the MIT/X11 software license, see the accompanying file COPYING or <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>. -This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard. +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (<a href="https://www.openssl.org/">https://www.openssl.org/</a>) and cryptographic software written by Eric Young (<a href="mailto:eay@cryptsoft.com">eay@cryptsoft.com</a>) and UPnP software written by Thomas Bernard.
+ + + Qt::RichText true From 386e732a5f6a6f5bc2cdfd0136027475b16af7c7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 2 Jun 2014 09:14:23 +0200 Subject: [PATCH 104/336] gitian: make linux qt intermediate deterministic A qt installation date snuck into the host utils (lrelease etc) This doesn't affect the end product, so no dependency version bump. It also doesn't explain why gavin's and mine build is different --- contrib/gitian-descriptors/qt-linux.yml | 1 + doc/release-process.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/gitian-descriptors/qt-linux.yml b/contrib/gitian-descriptors/qt-linux.yml index 1462df3289..b163b4bb8c 100644 --- a/contrib/gitian-descriptors/qt-linux.yml +++ b/contrib/gitian-descriptors/qt-linux.yml @@ -40,6 +40,7 @@ script: | tar xzf qt-everywhere-opensource-src-4.6.4.tar.gz cd qt-everywhere-opensource-src-4.6.4 QTBUILDDIR=$(pwd) + sed 's/TODAY=`date +%Y-%m-%d`/TODAY=2011-01-30/' -i configure # Need to build 4.6-versioned host utilities as well (lrelease/qrc/lupdate/...) ./configure -prefix $INSTALLPREFIX -confirm-license -release -opensource -no-qt3support -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend -no-declarative -no-script -no-scripttools -no-javascript-jit -no-webkit -no-svg -no-xmlpatterns -no-sql-sqlite -no-nis -no-cups -no-iconv -no-dbus -no-gif -no-libtiff -no-opengl -nomake examples -nomake demos -nomake docs diff --git a/doc/release-process.md b/doc/release-process.md index 6d08c48496..10c03de162 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -93,8 +93,8 @@ Release Process 571789867d172500fa96d63d0ba8c5b1e1a3d6f44f720eddf2f93665affc88b3 bitcoin-deps-linux64-gitian-r5.zip f29b7d9577417333fb56e023c2977f5726a7c297f320b175a4108cf7cd4c2d29 boost-linux32-1.55.0-gitian-r1.zip 88232451c4104f7eb16e469ac6474fd1231bd485687253f7b2bdf46c0781d535 boost-linux64-1.55.0-gitian-r1.zip - 74ec2d301cf1a9d03b194153f545102ba45dad02b390485212fe6717de486361 qt-linux32-4.6.4-gitian-r1.tar.gz - 01d0477e299467f09280f15424781154e2b1ea4072c5edb16e044c234954fd9a qt-linux64-4.6.4-gitian-r1.tar.gz + 57e57dbdadc818cd270e7e00500a5e1085b3bcbdef69a885f0fb7573a8d987e1 qt-linux32-4.6.4-gitian-r1.tar.gz + 60eb4b9c5779580b7d66529efa5b2836ba1a70edde2a0f3f696d647906a826be qt-linux64-4.6.4-gitian-r1.tar.gz 60dc2d3b61e9c7d5dbe2f90d5955772ad748a47918ff2d8b74e8db9b1b91c909 boost-win32-1.55.0-gitian-r6.zip f65fcaf346bc7b73bc8db3a8614f4f6bee2f61fcbe495e9881133a7c2612a167 boost-win64-1.55.0-gitian-r6.zip 97e62002d338885336bb24e7cbb9471491294bd8857af7a83d18c0961f864ec0 bitcoin-deps-win32-gitian-r11.zip From 1411a51feffe327956350417079104f573caeb5d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 2 Jun 2014 11:01:02 +0200 Subject: [PATCH 105/336] doc: Update hash in release process for new windows deps intermediate This was forgotten in 25d4911. --- doc/release-process.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 10c03de162..60b93b7680 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -97,8 +97,8 @@ Release Process 60eb4b9c5779580b7d66529efa5b2836ba1a70edde2a0f3f696d647906a826be qt-linux64-4.6.4-gitian-r1.tar.gz 60dc2d3b61e9c7d5dbe2f90d5955772ad748a47918ff2d8b74e8db9b1b91c909 boost-win32-1.55.0-gitian-r6.zip f65fcaf346bc7b73bc8db3a8614f4f6bee2f61fcbe495e9881133a7c2612a167 boost-win64-1.55.0-gitian-r6.zip - 97e62002d338885336bb24e7cbb9471491294bd8857af7a83d18c0961f864ec0 bitcoin-deps-win32-gitian-r11.zip - ee3ea2d5aac1a67ea6bfbea2c04068a7c0940616ce48ee4f37c264bb9d4438ef bitcoin-deps-win64-gitian-r11.zip + acd59690a49dfbad6b436379843fe4ad1857ad91c603d52506690bc55f2a01a4 bitcoin-deps-win32-gitian-r12.zip + a3e5a62fcdad81f758e41848035e6a27be390981a14d590f2cf2509f87417a42 bitcoin-deps-win64-gitian-r12.zip 963e3e5e85879010a91143c90a711a5d1d5aba992e38672cdf7b54e42c56b2f1 qt-win32-5.2.0-gitian-r3.zip 751c579830d173ef3e6f194e83d18b92ebef6df03289db13ab77a52b6bc86ef0 qt-win64-5.2.0-gitian-r3.zip e2e403e1a08869c7eed4d4293bce13d51ec6a63592918b90ae215a0eceb44cb4 protobuf-win32-2.5.0-gitian-r4.zip From 91855f279d27c3772b70c6e491684ed74684685e Mon Sep 17 00:00:00 2001 From: tm314159 Date: Mon, 2 Jun 2014 11:32:33 -0700 Subject: [PATCH 106/336] Properly initialize CWallet::nTimeFirstKey --- src/wallet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet.h b/src/wallet.h index 96074151ad..d9d071c2b9 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -151,6 +151,7 @@ public: nOrderPosNext = 0; nNextResend = 0; nLastResend = 0; + nTimeFirstKey = 0; } CWallet(std::string strWalletFileIn) { From 65f78a111ff52c2212cc0a423662e7a41d1206dd Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Fri, 23 May 2014 12:09:59 -0500 Subject: [PATCH 107/336] Qt: Add GUI view of peer information. #4133 --- src/qt/Makefile.am | 3 + src/qt/clientmodel.cpp | 9 +- src/qt/clientmodel.h | 3 + src/qt/forms/rpcconsole.ui | 275 +++++++++++++++++++++++++++++++++++++ src/qt/guiutil.cpp | 48 +++++++ src/qt/guiutil.h | 6 + src/qt/peertablemodel.cpp | 238 ++++++++++++++++++++++++++++++++ src/qt/peertablemodel.h | 79 +++++++++++ src/qt/rpcconsole.cpp | 192 ++++++++++++++++++++++++-- src/qt/rpcconsole.h | 29 ++++ 10 files changed, 870 insertions(+), 12 deletions(-) create mode 100644 src/qt/peertablemodel.cpp create mode 100644 src/qt/peertablemodel.h diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 648971bd8f..1d85113d78 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -126,6 +126,7 @@ QT_MOC_CPP = \ moc_optionsdialog.cpp \ moc_optionsmodel.cpp \ moc_overviewpage.cpp \ + moc_peertablemodel.cpp \ moc_paymentserver.cpp \ moc_qvalidatedlineedit.cpp \ moc_qvaluecombobox.cpp \ @@ -191,6 +192,7 @@ BITCOIN_QT_H = \ overviewpage.h \ paymentrequestplus.h \ paymentserver.h \ + peertablemodel.h \ qvalidatedlineedit.h \ qvaluecombobox.h \ receivecoinsdialog.h \ @@ -294,6 +296,7 @@ BITCOIN_QT_CPP += \ overviewpage.cpp \ paymentrequestplus.cpp \ paymentserver.cpp \ + peertablemodel.cpp \ receivecoinsdialog.cpp \ receiverequestdialog.cpp \ recentrequeststablemodel.cpp \ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index d1f68ebd22..ce773e0f82 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -5,6 +5,7 @@ #include "clientmodel.h" #include "guiconstants.h" +#include "peertablemodel.h" #include "alert.h" #include "chainparams.h" @@ -22,11 +23,12 @@ static const int64_t nClientStartupTime = GetTime(); ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : - QObject(parent), optionsModel(optionsModel), + QObject(parent), optionsModel(optionsModel), peerTableModel(0), cachedNumBlocks(0), cachedReindexing(0), cachedImporting(0), numBlocksAtStartup(-1), pollTimer(0) { + peerTableModel = new PeerTableModel(this); pollTimer = new QTimer(this); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); pollTimer->start(MODEL_UPDATE_DELAY); @@ -173,6 +175,11 @@ OptionsModel *ClientModel::getOptionsModel() return optionsModel; } +PeerTableModel *ClientModel::getPeerTableModel() +{ + return peerTableModel; +} + QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index cab853d92d..c18d30178b 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -9,6 +9,7 @@ class AddressTableModel; class OptionsModel; +class PeerTableModel; class TransactionTableModel; class CWallet; @@ -42,6 +43,7 @@ public: ~ClientModel(); OptionsModel *getOptionsModel(); + PeerTableModel *getPeerTableModel(); //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; @@ -71,6 +73,7 @@ public: private: OptionsModel *optionsModel; + PeerTableModel *peerTableModel; int cachedNumBlocks; bool cachedReindexing; diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index fcb6bb60bb..bf737d9b99 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -652,6 +652,281 @@ + + + &Peers + + + + + + + 0 + 0 + + + + Select a peer to view detailed information. + + + 3 + + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed + + + true + + + + + + + + 0 + 0 + + + + + 3 + + + + + Version: + + + + + + + N/A + + + + + + + Last Receive: + + + + + + + User Agent: + + + + + + + N/A + + + + + + + + 160 + 0 + + + + N/A + + + + + + + Ping Time: + + + + + + + + 0 + 0 + + + + N/A + + + + + + + Connection Time: + + + + + + + N/A + + + + + + + N/A + + + + + + + Starting Height: + + + + + + + N/A + + + + + + + Bytes Sent: + + + + + + + Bytes Received: + + + + + + + N/A + + + + + + + Ban Score: + + + + + + + N/A + + + + + + + Direction: + + + + + + + N/A + + + + + + + Sync Node: + + + + + + + N/A + + + + + + + Last Send: + + + + + + + Services: + + + + + + + IP Address/port: + + + + + + + N/A + + + + + + + N/A + + + + + + + N/A + + + + + + + + 0 + 0 + + + + + + + + + diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 7b264d27c7..851c0130ed 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -11,6 +11,7 @@ #include "core.h" #include "init.h" +#include "protocol.h" #include "util.h" #ifdef WIN32 @@ -750,4 +751,51 @@ QString boostPathToQString(const boost::filesystem::path &path) } #endif +QString formatDurationStr(int secs) +{ + QStringList strList; + int days = secs / 86400; + int hours = (secs % 86400) / 3600; + int mins = (secs % 3600) / 60; + int seconds = secs % 60; + + if (days) + strList.append(QString(QObject::tr("%1 d")).arg(days)); + if (hours) + strList.append(QString(QObject::tr("%1 h")).arg(hours)); + if (mins) + strList.append(QString(QObject::tr("%1 m")).arg(mins)); + if (seconds || (!days && !hours && !mins)) + strList.append(QString(QObject::tr("%1 s")).arg(seconds)); + + return strList.join(" "); +} + +QString formatServicesStr(uint64_t mask) +{ + QStringList strList; + + // Just scan the last 8 bits for now. + for (int i=0; i < 8; i++) { + uint64_t check = 1 << i; + if (mask & check) + { + switch (check) + { + case NODE_NETWORK: + strList.append(QObject::tr("NETWORK")); + break; + default: + strList.append(QString("%1[%2]").arg(QObject::tr("UNKNOWN")).arg(check)); + } + } + } + + if (strList.size()) + return strList.join(" & "); + else + return QObject::tr("None"); + +} + } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 4f9416d1af..ea6b7de872 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -173,6 +173,12 @@ namespace GUIUtil /* Convert OS specific boost path to QString through UTF-8 */ QString boostPathToQString(const boost::filesystem::path &path); + /* Convert seconds into a QString with days, hours, mins, secs */ + QString formatDurationStr(int secs); + + /* Format CNodeStats.nServices bitmask into a user-readable string */ + QString formatServicesStr(uint64_t mask); + } // namespace GUIUtil #endif // GUIUTIL_H diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp new file mode 100644 index 0000000000..fba9d84e77 --- /dev/null +++ b/src/qt/peertablemodel.cpp @@ -0,0 +1,238 @@ +// Copyright (c) 2011-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "peertablemodel.h" + +#include "clientmodel.h" + +#include "net.h" +#include "sync.h" + +#include +#include +#include + +bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const +{ + const CNodeStats *pLeft = &(left.nodestats); + const CNodeStats *pRight = &(right.nodestats); + + if (order == Qt::DescendingOrder) + std::swap(pLeft, pRight); + + switch(column) + { + case PeerTableModel::Address: + return pLeft->addrName.compare(pRight->addrName) < 0; + case PeerTableModel::Subversion: + return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0; + case PeerTableModel::Height: + return pLeft->nStartingHeight < pRight->nStartingHeight; + } + + return false; +} + +// private implementation +class PeerTablePriv +{ +public: + /** Local cache of peer information */ + QList cachedNodeStats; + /** Column to sort nodes by */ + int sortColumn; + /** Order (ascending or descending) to sort nodes by */ + Qt::SortOrder sortOrder; + /** Index of rows by node ID */ + std::map mapNodeRows; + + /** Pull a full list of peers from vNodes into our cache */ + void refreshPeers() { + TRY_LOCK(cs_vNodes, lockNodes); + { + if (!lockNodes) + { + // skip the refresh if we can't immediately get the lock + return; + } + cachedNodeStats.clear(); +#if QT_VERSION >= 0x040700 + cachedNodeStats.reserve(vNodes.size()); +#endif + BOOST_FOREACH(CNode* pnode, vNodes) + { + CNodeCombinedStats stats; + stats.statestats.nMisbehavior = -1; + pnode->copyStats(stats.nodestats); + cachedNodeStats.append(stats); + } + } + + // if we can, retrieve the CNodeStateStats for each node. + TRY_LOCK(cs_main, lockMain); + { + if (lockMain) + { + BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats) + { + GetNodeStateStats(stats.nodestats.nodeid, stats.statestats); + } + } + } + + + if (sortColumn >= 0) + // sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily) + qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder)); + + // build index map + mapNodeRows.clear(); + int row = 0; + BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats) + { + mapNodeRows.insert(std::pair(stats.nodestats.nodeid, row++)); + } + } + + int size() + { + return cachedNodeStats.size(); + } + + CNodeCombinedStats *index(int idx) + { + if(idx >= 0 && idx < cachedNodeStats.size()) { + return &cachedNodeStats[idx]; + } + else + { + return 0; + } + } + +}; + +PeerTableModel::PeerTableModel(ClientModel *parent) : + QAbstractTableModel(parent),clientModel(parent),timer(0) +{ + columns << tr("Address") << tr("User Agent") << tr("Start Height"); + priv = new PeerTablePriv(); + // default to unsorted + priv->sortColumn = -1; + + // set up timer for auto refresh + timer = new QTimer(); + connect(timer, SIGNAL(timeout()), SLOT(refresh())); + + // load initial data + refresh(); +} + +void PeerTableModel::startAutoRefresh(int msecs) +{ + timer->setInterval(1000); + timer->start(); +} + +void PeerTableModel::stopAutoRefresh() +{ + timer->stop(); +} + +int PeerTableModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return priv->size(); +} + +int PeerTableModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 3; +} + +QVariant PeerTableModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + CNodeCombinedStats *rec = static_cast(index.internalPointer()); + + if(role == Qt::DisplayRole) + { + switch(index.column()) + { + case Address: + return QVariant(rec->nodestats.addrName.c_str()); + case Subversion: + return QVariant(rec->nodestats.cleanSubVer.c_str()); + case Height: + return rec->nodestats.nStartingHeight; + } + } + return QVariant(); +} + +QVariant PeerTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::DisplayRole && section < columns.size()) + { + return columns[section]; + } + } + return QVariant(); +} + +Qt::ItemFlags PeerTableModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return 0; + + Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return retval; +} + +QModelIndex PeerTableModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + CNodeCombinedStats *data = priv->index(row); + + if (data) + { + return createIndex(row, column, data); + } + else + { + return QModelIndex(); + } +} + +const CNodeCombinedStats *PeerTableModel::getNodeStats(int idx) { + return priv->index(idx); +} + +void PeerTableModel::refresh() +{ + emit layoutAboutToBeChanged(); + priv->refreshPeers(); + emit layoutChanged(); +} + +int PeerTableModel::getRowByNodeId(NodeId nodeid) +{ + std::map::iterator it = priv->mapNodeRows.find(nodeid); + if (it == priv->mapNodeRows.end()) + return -1; + + return it->second; +} + +void PeerTableModel::sort(int column, Qt::SortOrder order) +{ + priv->sortColumn = column; + priv->sortOrder = order; + refresh(); +} diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h new file mode 100644 index 0000000000..d947e21240 --- /dev/null +++ b/src/qt/peertablemodel.h @@ -0,0 +1,79 @@ +// Copyright (c) 2011-2013 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 PEERTABLEMODEL_H +#define PEERTABLEMODEL_H + +#include "main.h" +#include "net.h" + +#include +#include + +class PeerTablePriv; +class ClientModel; + +class QTimer; + +struct CNodeCombinedStats { + CNodeStats nodestats; + CNodeStateStats statestats; +}; + +class NodeLessThan +{ +public: + NodeLessThan(int nColumn, Qt::SortOrder fOrder): + column(nColumn), order(fOrder) {} + bool operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const; + +private: + int column; + Qt::SortOrder order; +}; + +/** + Qt model providing information about connected peers, similar to the + "getpeerinfo" RPC call. Used by the rpc console UI. + */ +class PeerTableModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit PeerTableModel(ClientModel *parent = 0); + const CNodeCombinedStats *getNodeStats(int idx); + int getRowByNodeId(NodeId nodeid); + void startAutoRefresh(int msecs); + void stopAutoRefresh(); + + enum ColumnIndex { + Address = 0, + Subversion = 1, + Height = 2 + }; + + /** @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; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + void sort(int column, Qt::SortOrder order); + /*@}*/ + +public slots: + void refresh(); + +private: + ClientModel *clientModel; + QStringList columns; + PeerTablePriv *priv; + QTimer *timer; + +}; + +#endif // PEERTABLEMODEL_H diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 0a46a722e4..ed048cf3cc 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -7,6 +7,10 @@ #include "clientmodel.h" #include "guiutil.h" +#include "peertablemodel.h" + +#include "main.h" +#include "util.h" #include "rpcserver.h" #include "rpcclient.h" @@ -195,6 +199,10 @@ RPCConsole::RPCConsole(QWidget *parent) : clientModel(0), historyPtr(0) { + detailNodeStats = CNodeCombinedStats(); + detailNodeStats.nodestats.nodeid = -1; + detailNodeStats.statestats.nMisbehavior = -1; + ui->setupUi(this); GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this); @@ -214,6 +222,7 @@ RPCConsole::RPCConsole(QWidget *parent) : startExecutor(); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); + ui->detailWidget->hide(); clear(); } @@ -277,6 +286,23 @@ void RPCConsole::setClientModel(ClientModel *model) updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); + // set up peer table + ui->peerWidget->setModel(model->getPeerTableModel()); + ui->peerWidget->verticalHeader()->hide(); + ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH); + columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(ui->peerWidget, MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH); + + // connect the peerWidget's selection model to our peerSelected() handler + QItemSelectionModel *peerSelectModel = ui->peerWidget->selectionModel(); + connect(peerSelectModel, + SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, + SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); + connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged())); + // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientName->setText(model->clientName()); @@ -474,17 +500,7 @@ QString RPCConsole::FormatBytes(quint64 bytes) void RPCConsole::setTrafficGraphRange(int mins) { ui->trafficGraph->setGraphRangeMins(mins); - if(mins < 60) { - ui->lblGraphRange->setText(QString(tr("%1 m")).arg(mins)); - } else { - int hours = mins / 60; - int minsLeft = mins % 60; - if(minsLeft == 0) { - ui->lblGraphRange->setText(QString(tr("%1 h")).arg(hours)); - } else { - ui->lblGraphRange->setText(QString(tr("%1 h %2 m")).arg(hours).arg(minsLeft)); - } - } + ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60)); } void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) @@ -492,3 +508,157 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) ui->lblBytesIn->setText(FormatBytes(totalBytesIn)); ui->lblBytesOut->setText(FormatBytes(totalBytesOut)); } + +void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected) +{ + if (selected.indexes().isEmpty()) + return; + + // mark the cached banscore as unknown + detailNodeStats.statestats.nMisbehavior = -1; + + const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row()); + + if (stats) + { + detailNodeStats.nodestats.nodeid = stats->nodestats.nodeid; + updateNodeDetail(stats); + ui->detailWidget->show(); + ui->detailWidget->setDisabled(false); + } +} + +void RPCConsole::peerLayoutChanged() +{ + const CNodeCombinedStats *stats = NULL; + bool fUnselect = false, fReselect = false, fDisconnected = false; + + if (detailNodeStats.nodestats.nodeid == -1) + // no node selected yet + return; + + // find the currently selected row + int selectedRow; + QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes(); + if (selectedModelIndex.isEmpty()) + selectedRow = -1; + else + selectedRow = selectedModelIndex.first().row(); + + // check if our detail node has a row in the table (it may not necessarily + // be at selectedRow since its position can change after a layout change) + int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(detailNodeStats.nodestats.nodeid); + + if (detailNodeRow < 0) + { + // detail node dissapeared from table (node disconnected) + fUnselect = true; + fDisconnected = true; + detailNodeStats.nodestats.nodeid = 0; + } + else + { + if (detailNodeRow != selectedRow) + { + // detail node moved position + fUnselect = true; + fReselect = true; + } + + // get fresh stats on the detail node. + stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow); + } + + if (fUnselect && selectedRow >= 0) + { + ui->peerWidget->selectionModel()->select(QItemSelection(selectedModelIndex.first(), selectedModelIndex.last()), + QItemSelectionModel::Deselect); + } + + if (fReselect) + { + ui->peerWidget->selectRow(detailNodeRow); + } + + if (stats) + updateNodeDetail(stats); + + if (fDisconnected) + { + ui->peerHeading->setText(QString(tr("Peer Disconnected"))); + ui->detailWidget->setDisabled(true); + QDateTime dt = QDateTime::fromTime_t(detailNodeStats.nodestats.nLastSend); + if (detailNodeStats.nodestats.nLastSend) + ui->peerLastSend->setText(dt.toString("yyyy-MM-dd hh:mm:ss")); + dt.setTime_t(detailNodeStats.nodestats.nLastRecv); + if (detailNodeStats.nodestats.nLastRecv) + ui->peerLastRecv->setText(dt.toString("yyyy-MM-dd hh:mm:ss")); + dt.setTime_t(detailNodeStats.nodestats.nTimeConnected); + ui->peerConnTime->setText(dt.toString("yyyy-MM-dd hh:mm:ss")); + } +} + +void RPCConsole::updateNodeDetail(const CNodeCombinedStats *combinedStats) +{ + CNodeStats stats = combinedStats->nodestats; + + // keep a copy of timestamps, used to display dates upon disconnect + detailNodeStats.nodestats.nLastSend = stats.nLastSend; + detailNodeStats.nodestats.nLastRecv = stats.nLastRecv; + detailNodeStats.nodestats.nTimeConnected = stats.nTimeConnected; + + // update the detail ui with latest node information + ui->peerHeading->setText(QString("%1").arg(tr("Node Detail"))); + ui->peerAddr->setText(QString(stats.addrName.c_str())); + ui->peerServices->setText(GUIUtil::formatServicesStr(stats.nServices)); + ui->peerLastSend->setText(stats.nLastSend ? GUIUtil::formatDurationStr(GetTime() - stats.nLastSend) : tr("never")); + ui->peerLastRecv->setText(stats.nLastRecv ? GUIUtil::formatDurationStr(GetTime() - stats.nLastRecv) : tr("never")); + ui->peerBytesSent->setText(FormatBytes(stats.nSendBytes)); + ui->peerBytesRecv->setText(FormatBytes(stats.nRecvBytes)); + ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetTime() - stats.nTimeConnected)); + ui->peerPingTime->setText(stats.dPingTime == 0 ? tr("N/A") : QString(tr("%1 secs")).arg(QString::number(stats.dPingTime, 'f', 3))); + ui->peerVersion->setText(QString("%1").arg(stats.nVersion)); + ui->peerSubversion->setText(QString(stats.cleanSubVer.c_str())); + ui->peerDirection->setText(stats.fInbound ? tr("Inbound") : tr("Outbound")); + ui->peerHeight->setText(QString("%1").arg(stats.nStartingHeight)); + ui->peerSyncNode->setText(stats.fSyncNode ? tr("Yes") : tr("No")); + + // if we can, display the peer's ban score + CNodeStateStats statestats = combinedStats->statestats; + if (statestats.nMisbehavior >= 0) + { + // we have a new nMisbehavor value - update the cache + detailNodeStats.statestats.nMisbehavior = statestats.nMisbehavior; + } + + // pull the ban score from cache. -1 means it hasn't been retrieved yet (lock busy). + if (detailNodeStats.statestats.nMisbehavior >= 0) + ui->peerBanScore->setText(QString("%1").arg(detailNodeStats.statestats.nMisbehavior)); + else + ui->peerBanScore->setText(tr("Fetching...")); +} + +void RPCConsole::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + columnResizingFixer->stretchColumnWidth(PeerTableModel::Address); +} + +void RPCConsole::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + + // peerWidget needs a resize in case the dialog has non-default geometry + columnResizingFixer->stretchColumnWidth(PeerTableModel::Address); + + // start the PeerTableModel refresh timer + clientModel->getPeerTableModel()->startAutoRefresh(1000); +} + +void RPCConsole::hideEvent(QHideEvent *event) +{ + QWidget::hideEvent(event); + + // stop PeerTableModel auto refresh + clientModel->getPeerTableModel()->stopAutoRefresh(); +} diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 091a6d294f..c17d5397ec 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -5,10 +5,18 @@ #ifndef RPCCONSOLE_H #define RPCCONSOLE_H +#include "guiutil.h" +#include "net.h" + +#include "peertablemodel.h" + #include class ClientModel; +class QItemSelection; +class CNodeCombinedStats; + namespace Ui { class RPCConsole; } @@ -35,6 +43,19 @@ public: protected: virtual bool eventFilter(QObject* obj, QEvent *event); +private: + /** show detailed information on ui about selected node */ + void updateNodeDetail(const CNodeCombinedStats *combinedStats); + + enum ColumnWidths + { + ADDRESS_COLUMN_WIDTH = 250, + MINIMUM_COLUMN_WIDTH = 120 + }; + + /** track the node that we are currently viewing detail on in the peers tab */ + CNodeCombinedStats detailNodeStats; + private slots: void on_lineEdit_returnPressed(); void on_tabWidget_currentChanged(int index); @@ -44,6 +65,9 @@ private slots: void on_sldGraphRange_valueChanged(int value); /** update traffic statistics */ void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut); + void resizeEvent(QResizeEvent *event); + void showEvent(QShowEvent *event); + void hideEvent(QHideEvent *event); public slots: void clear(); @@ -57,6 +81,10 @@ public slots: void browseHistory(int offset); /** Scroll console view to end */ void scrollToEnd(); + /** Handle selection of peer in peers list */ + void peerSelected(const QItemSelection &selected, const QItemSelection &deselected); + /** Handle updated peer information */ + void peerLayoutChanged(); signals: // For RPC command executor @@ -70,6 +98,7 @@ private: Ui::RPCConsole *ui; ClientModel *clientModel; QStringList history; + GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer; int historyPtr; void startExecutor(); From bbe1925ce3e627fd405d83e3c947e1f430a1d720 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 3 Jun 2014 14:42:20 +0200 Subject: [PATCH 108/336] [Qt] style police and small addition in rpcconsole - fix spaces, indentation and coding style glitches --- src/qt/clientmodel.cpp | 4 +++- src/qt/guiutil.cpp | 3 +-- src/qt/guiutil.h | 1 - src/qt/peertablemodel.cpp | 2 -- src/qt/peertablemodel.h | 7 ++++--- src/qt/receiverequestdialog.cpp | 2 +- src/qt/receiverequestdialog.h | 4 +++- src/qt/rpcconsole.cpp | 15 ++++++++------- src/qt/rpcconsole.h | 10 ++++++---- src/qt/transactiondesc.h | 1 + 10 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index ce773e0f82..1c008428a3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -23,7 +23,9 @@ static const int64_t nClientStartupTime = GetTime(); ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : - QObject(parent), optionsModel(optionsModel), peerTableModel(0), + QObject(parent), + optionsModel(optionsModel), + peerTableModel(0), cachedNumBlocks(0), cachedReindexing(0), cachedImporting(0), numBlocksAtStartup(-1), pollTimer(0) diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 62db0487fc..1922d228c5 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -780,7 +780,7 @@ QString formatServicesStr(uint64_t mask) QStringList strList; // Just scan the last 8 bits for now. - for (int i=0; i < 8; i++) { + for (int i = 0; i < 8; i++) { uint64_t check = 1 << i; if (mask & check) { @@ -799,7 +799,6 @@ QString formatServicesStr(uint64_t mask) return strList.join(" & "); else return QObject::tr("None"); - } } // namespace GUIUtil diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index ea6b7de872..45c78b4e14 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -178,7 +178,6 @@ namespace GUIUtil /* Format CNodeStats.nServices bitmask into a user-readable string */ QString formatServicesStr(uint64_t mask); - } // namespace GUIUtil #endif // GUIUTIL_H diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index fba9d84e77..db5ce639b1 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -81,7 +81,6 @@ public: } } - if (sortColumn >= 0) // sort cacheNodeStats (use stable sort to prevent rows jumping around unneceesarily) qStableSort(cachedNodeStats.begin(), cachedNodeStats.end(), NodeLessThan(sortColumn, sortOrder)); @@ -110,7 +109,6 @@ public: return 0; } } - }; PeerTableModel::PeerTableModel(ClientModel *parent) : diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h index d947e21240..385bf0e0c1 100644 --- a/src/qt/peertablemodel.h +++ b/src/qt/peertablemodel.h @@ -11,10 +11,12 @@ #include #include -class PeerTablePriv; class ClientModel; +class PeerTablePriv; +QT_BEGIN_NAMESPACE class QTimer; +QT_END_NAMESPACE struct CNodeCombinedStats { CNodeStats nodestats; @@ -24,7 +26,7 @@ struct CNodeCombinedStats { class NodeLessThan { public: - NodeLessThan(int nColumn, Qt::SortOrder fOrder): + NodeLessThan(int nColumn, Qt::SortOrder fOrder) : column(nColumn), order(fOrder) {} bool operator()(const CNodeCombinedStats &left, const CNodeCombinedStats &right) const; @@ -73,7 +75,6 @@ private: QStringList columns; PeerTablePriv *priv; QTimer *timer; - }; #endif // PEERTABLEMODEL_H diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 062638f2bc..d8dad15c0d 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -13,10 +13,10 @@ #include #include +#include #include #include #include -#include #if QT_VERSION < 0x050000 #include #endif diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 5614ac635a..9b78e495c3 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -11,10 +11,12 @@ #include #include +class OptionsModel; + namespace Ui { class ReceiveRequestDialog; } -class OptionsModel; + QT_BEGIN_NAMESPACE class QMenu; QT_END_NAMESPACE diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ed048cf3cc..3b7d37ff39 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -10,10 +10,9 @@ #include "peertablemodel.h" #include "main.h" -#include "util.h" - #include "rpcserver.h" #include "rpcclient.h" +#include "util.h" #include "json/json_spirit_value.h" #include @@ -297,10 +296,8 @@ void RPCConsole::setClientModel(ClientModel *model) // connect the peerWidget's selection model to our peerSelected() handler QItemSelectionModel *peerSelectModel = ui->peerWidget->selectionModel(); - connect(peerSelectModel, - SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), - this, - SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); + connect(peerSelectModel, SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged())); // Provide initial values @@ -511,6 +508,8 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut) void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected) { + Q_UNUSED(deselected); + if (selected.indexes().isEmpty()) return; @@ -638,6 +637,8 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *combinedStats) ui->peerBanScore->setText(tr("Fetching...")); } +// We override the virtual resizeEvent of the QWidget to adjust tables column +// sizes as the tables width is proportional to the dialogs width. void RPCConsole::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); @@ -651,7 +652,7 @@ void RPCConsole::showEvent(QShowEvent *event) // peerWidget needs a resize in case the dialog has non-default geometry columnResizingFixer->stretchColumnWidth(PeerTableModel::Address); - // start the PeerTableModel refresh timer + // start PeerTableModel auto refresh clientModel->getPeerTableModel()->startAutoRefresh(1000); } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index c17d5397ec..3fee34d00e 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -6,17 +6,19 @@ #define RPCCONSOLE_H #include "guiutil.h" -#include "net.h" - #include "peertablemodel.h" +#include "net.h" + #include class ClientModel; - -class QItemSelection; class CNodeCombinedStats; +QT_BEGIN_NAMESPACE +class QItemSelection; +QT_END_NAMESPACE + namespace Ui { class RPCConsole; } diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h index f5a1328a71..4bd4293210 100644 --- a/src/qt/transactiondesc.h +++ b/src/qt/transactiondesc.h @@ -9,6 +9,7 @@ #include class TransactionRecord; + class CWallet; class CWalletTx; From 06a91d9698762fe56fca3bd33484bddc9f020405 Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Fri, 23 May 2014 18:04:09 +0200 Subject: [PATCH 109/336] VerifyDB progress --- src/init.cpp | 2 +- src/main.cpp | 14 +++++++++++++- src/main.h | 11 +++++++++-- src/qt/bitcoingui.cpp | 27 +++++++++++++++++++++++++++ src/qt/bitcoingui.h | 5 +++++ src/qt/clientmodel.cpp | 10 ++++++++++ src/qt/clientmodel.h | 3 +++ src/qt/splashscreen.cpp | 2 ++ src/rpcblockchain.cpp | 2 +- src/ui_interface.h | 3 +++ 10 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bc4924b48d..840a07d610 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -858,7 +858,7 @@ bool AppInit2(boost::thread_group& threadGroup) } uiInterface.InitMessage(_("Verifying blocks...")); - if (!VerifyDB(GetArg("-checklevel", 3), + if (!CVerifyDB().VerifyDB(GetArg("-checklevel", 3), GetArg("-checkblocks", 288))) { strLoadError = _("Corrupted block database detected"); break; diff --git a/src/main.cpp b/src/main.cpp index 18c00d90ac..30fa9c6d70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2968,7 +2968,17 @@ bool static LoadBlockIndexDB() return true; } -bool VerifyDB(int nCheckLevel, int nCheckDepth) +CVerifyDB::CVerifyDB() +{ + uiInterface.ShowProgress(_("Verifying blocks..."), 0); +} + +CVerifyDB::~CVerifyDB() +{ + uiInterface.ShowProgress("", 100); +} + +bool CVerifyDB::VerifyDB(int nCheckLevel, int nCheckDepth) { LOCK(cs_main); if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL) @@ -2989,6 +2999,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth) for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); + uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))))); if (pindex->nHeight < chainActive.Height()-nCheckDepth) break; CBlock block; @@ -3028,6 +3039,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth) CBlockIndex *pindex = pindexState; while (pindex != chainActive.Tip()) { boost::this_thread::interruption_point(); + uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50)))); pindex = chainActive.Next(pindex); CBlock block; if (!ReadBlockFromDisk(block, pindex)) diff --git a/src/main.h b/src/main.h index 8a05eb60d2..42cf4a0861 100644 --- a/src/main.h +++ b/src/main.h @@ -144,8 +144,6 @@ bool InitBlockIndex(); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Verify consistency of the block and coin databases */ -bool VerifyDB(int nCheckLevel, int nCheckDepth); /** Print the loaded block tree */ void PrintBlockTree(); /** Process protocol messages received from a given node */ @@ -1024,6 +1022,15 @@ public: std::string GetRejectReason() const { return strRejectReason; } }; +/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ +class CVerifyDB { +public: + + CVerifyDB(); + ~CVerifyDB(); + bool VerifyDB(int nCheckLevel, int nCheckDepth); +}; + /** An in-memory indexed chain of blocks. */ class CChain { private: diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 68ae8b4668..3469f990ac 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -409,6 +410,9 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) // Receive and report messages from client model connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); + // Show progress dialog + connect(clientModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int))); + rpcConsole->setClientModel(clientModel); #ifdef ENABLE_WALLET if(walletFrame) @@ -949,6 +953,29 @@ void BitcoinGUI::detectShutdown() } } +void BitcoinGUI::showProgress(const QString &title, int nProgress) +{ + if (nProgress == 0) + { + progressDialog = new QProgressDialog(title, "", 0, 100); + progressDialog->setWindowModality(Qt::ApplicationModal); + progressDialog->setMinimumDuration(0); + progressDialog->setCancelButton(0); + progressDialog->setAutoClose(false); + progressDialog->setValue(0); + } + else if (nProgress == 100) + { + if (progressDialog) + { + progressDialog->close(); + progressDialog->deleteLater(); + } + } + else if (progressDialog) + progressDialog->setValue(nProgress); +} + static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b4675b95ac..275fa35f39 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -26,6 +26,7 @@ QT_BEGIN_NAMESPACE class QAction; class QLabel; class QProgressBar; +class QProgressDialog; QT_END_NAMESPACE /** @@ -73,6 +74,7 @@ private: QLabel *labelBlocksIcon; QLabel *progressBarLabel; QProgressBar *progressBar; + QProgressDialog *progressDialog; QMenuBar *appMenuBar; QAction *overviewAction; @@ -191,6 +193,9 @@ private slots: /** called by a timer to check if fRequestShutdown has been set **/ void detectShutdown(); + + /** Show progress dialog e.g. for verifychain */ + void showProgress(const QString &title, int nProgress); }; #endif // BITCOINGUI_H diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index ce773e0f82..656c8bd113 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -206,6 +206,14 @@ QString ClientModel::formatClientStartupTime() const } // Handlers for core signals +static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress) +{ + // emits signal "showProgress" + QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(title)), + Q_ARG(int, nProgress)); +} + static void NotifyBlocksChanged(ClientModel *clientmodel) { // This notification is too frequent. Don't trigger a signal. @@ -230,6 +238,7 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch void ClientModel::subscribeToCoreSignals() { // Connect signals to client + uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); @@ -238,6 +247,7 @@ void ClientModel::subscribeToCoreSignals() void ClientModel::unsubscribeFromCoreSignals() { // Disconnect signals from client + uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index c18d30178b..9c9a35b654 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -95,6 +95,9 @@ signals: //! Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); + // Show progress dialog e.g. for verifychain + void showProgress(const QString &title, int nProgress); + public slots: void updateTimer(); void updateNumConnections(int numConnections); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 7c79b0efd0..1162e2d87f 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -129,6 +129,7 @@ void SplashScreen::subscribeToCoreSignals() { // Connect signals to client uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); + uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1)); #endif @@ -138,6 +139,7 @@ void SplashScreen::unsubscribeFromCoreSignals() { // Disconnect signals from client uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); + uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET if(pwalletMain) pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index a303b5d3ef..ff5057b526 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -427,7 +427,7 @@ Value verifychain(const Array& params, bool fHelp) if (params.size() > 1) nCheckDepth = params[1].get_int(); - return VerifyDB(nCheckLevel, nCheckDepth); + return CVerifyDB().VerifyDB(nCheckLevel, nCheckDepth); } Value getblockchaininfo(const Array& params, bool fHelp) diff --git a/src/ui_interface.h b/src/ui_interface.h index 7b655ac951..e1a3e04e12 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -94,6 +94,9 @@ public: /** A wallet has been loaded. */ boost::signals2::signal LoadWallet; + + /** Show progress e.g. for verifychain */ + boost::signals2::signal ShowProgress; }; extern CClientUIInterface uiInterface; From a98b8707dc5606a5c119a123b1b66d5e7ab5a815 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzotta Date: Tue, 3 Jun 2014 11:40:24 +0200 Subject: [PATCH 110/336] Some documentation fixes + link to my Docker/LXC guide I added a link to my guide about using docker containers + LXC (I am planning to maintain this at work for future bitcoin versions), then I mentioned other virtualization options (KVM, LXC). This commit includes a fix issue for documentation issue #4269 that consists in telling users to checkout correct bitcoin version before using the gitian descriptors (otherwise all hell can break loose). Also, I replaced URL for Debian 7.4 ISO with a correct one and added link to official Debian ISO sources. --- doc/gitian-building.md | 45 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 544bbc12c1..378a45eda5 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -34,19 +34,22 @@ Table of Contents - [Signing externally](#signing-externally) - [Uploading signatures](#uploading-signatures) +Preparing the Gitian builder host +--------------------------------- + +The first step is to prepare the host environment that will be used to perform the Gitian builds. +In this guide it is explained how to set up the environment, and how to get the builds started. + +Debian Linux was chosen as the host distribution because it has a lightweight install (in contrast to Ubuntu) and is readily available. +Any kind of virtualization can be used, for example: +- [VirtualBox](https://www.virtualbox.org/), covered by this guide +- [KVM](http://www.linux-kvm.org/page/Main_Page) +- [LXC](https://linuxcontainers.org/), see also [Gitian host docker container](https://github.com/gdm85/tenku/tree/master/docker/gitian-bitcoin-host/README.md). + +You can also install on actual hardware instead of using virtualization. + Create a new VirtualBox VM --------------------------- - -The first step is to create a new Virtual Machine, which will be explained in -this section. This VM will be used to do the Gitian builds. In this guide it -will be explained how to set up the environment, and how to get the builds -started. - -Debian Linux was chosen as the host distribution because it has a lightweight install (in -contrast to Ubuntu) and is readily available. We here show the steps for -VirtualBox [1], but any kind of virtualization can be used. You can also install -on actual hardware instead of using a VM, in this case you can skip this section. - In the VirtualBox GUI click "Create" and choose the following parameters in the wizard: ![](gitian-building/create_vm_page1.png) @@ -74,11 +77,11 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the - Disk size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side - Push the `Create` button -Get the [Debian 7.4 net installer](http://cdimage.debian.org/debian-cd/7.4.0/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso). +Get the [Debian 7.4 net installer](http://ftp.at.debian.org/debian-jigdo/current/amd64/iso-cd/debian-7.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)). This DVD image can be validated using a SHA256 hashing tool, for example on Unixy OSes by entering the following in a terminal: - echo "b712a141bc60269db217d3b3e456179bd6b181645f90e4aac9c42ed63de492e9 /home/orion/Downloads/debian-7.4.0-amd64-netinst.iso" | sha256sum -c + echo "b712a141bc60269db217d3b3e456179bd6b181645f90e4aac9c42ed63de492e9 debian-7.4.0-amd64-netinst.iso" | sha256sum -c # (must return OK) After creating the VM, we need to configure it. @@ -106,8 +109,6 @@ Then start the VM. On the first launch you will be asked for a CD or DVD image. ![](gitian-building/select_startup_disk.png) -[1] https://www.virtualbox.org/ - Installing Debian ------------------ @@ -279,11 +280,14 @@ cd .. **Note**: When sudo asks for a password, enter the password for the user *debian* not for *root*. -Clone the git repositories for bitcoin and gitian, +Clone the git repositories for bitcoin and gitian and then checkout the bitcoin version that you are willing to build. ```bash git clone https://github.com/devrandom/gitian-builder.git git clone https://github.com/bitcoin/bitcoin +cd bitcoin +git checkout v${VERSION} +cd .. ``` Setting up gitian images @@ -402,9 +406,6 @@ gitian build. Uploading signatures --------------------- -After building and signing you can push your signatures (both the `.assert` and -`.assert.sig` files) to the -[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or -if not possible create a pull request. You can also mail the files to me -(laanwj@gmail.com) and I'll commit them. - +After building and signing you can push your signatures (both the `.assert` and `.assert.sig` files) to the +[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or if not possible create a pull +request. You can also mail the files to me (laanwj@gmail.com) and I'll commit them. From d04fd3e2afaf9cdab21aa8f3abb5a5a2c48118cc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 3 Jun 2014 12:55:33 -0400 Subject: [PATCH 111/336] CWallet: fix nTimeFirstKey init, by making constructor init common code Don't repeat yourself etc. --- src/wallet.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/wallet.h b/src/wallet.h index d9d071c2b9..8e2917188a 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -142,6 +142,17 @@ public: unsigned int nMasterKeyMaxID; CWallet() + { + SetNull(); + } + CWallet(std::string strWalletFileIn) + { + SetNull(); + + strWalletFile = strWalletFileIn; + fFileBacked = true; + } + void SetNull() { nWalletVersion = FEATURE_BASE; nWalletMaxVersion = FEATURE_BASE; @@ -153,18 +164,6 @@ public: nLastResend = 0; nTimeFirstKey = 0; } - CWallet(std::string strWalletFileIn) - { - nWalletVersion = FEATURE_BASE; - nWalletMaxVersion = FEATURE_BASE; - strWalletFile = strWalletFileIn; - fFileBacked = true; - nMasterKeyMaxID = 0; - pwalletdbEncryption = NULL; - nOrderPosNext = 0; - nNextResend = 0; - nLastResend = 0; - } std::map mapWallet; From 4a09e1df51267c6d2dec219c6f96a24b716cc251 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Mon, 2 Jun 2014 16:21:03 -0700 Subject: [PATCH 112/336] key.cpp: fail with a friendlier message on missing ssl EC support Previously if bitcoind is linked with an OpenSSL which is compiled without EC support, this is seen as an assertion failure "pKey != NULL" at key.cpp:134, which occurs after several seconds. It is an esoteric piece of knowledge to interpret this as "oops, I linked with the wrong OpenSSL", and because of the delay it may not even be noticed. The new output is : OpenSSL appears to lack support for elliptic curve cryptography. For more information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries : Initialization sanity check failed. Bitcoin Core is shutting down. which occurs immediately after attempted startup. This also blocks in an InitSanityCheck() function which currently only checks for EC support but should eventually do more. See #4081. --- src/init.cpp | 21 +++++++++++++++++++++ src/key.cpp | 12 ++++++++++++ src/key.h | 3 +++ 3 files changed, 36 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index bc4924b48d..b66231ff2c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -11,6 +11,7 @@ #include "addrman.h" #include "checkpoints.h" +#include "key.h" #include "main.h" #include "miner.h" #include "net.h" @@ -385,6 +386,23 @@ void ThreadImport(std::vector vImportFiles) } } +/** Sanity checks + * Ensure that Bitcoin is running in a usable environment with all + * necessary library support. + */ +bool InitSanityCheck(void) +{ + if(!ECC_InitSanityCheck()) { + InitError("OpenSSL appears to lack support for elliptic curve cryptography. For more " + "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries"); + return false; + } + + // TODO: remaining sanity checks, see #4081 + + return true; +} + /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ @@ -586,6 +604,9 @@ bool AppInit2(boost::thread_group& threadGroup) strWalletFile = GetArg("-wallet", "wallet.dat"); #endif // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + // Sanity check + if (!InitSanityCheck()) + return InitError(_("Initialization sanity check failed. Bitcoin Core is shutting down.")); std::string strDataDir = GetDataDir().string(); #ifdef ENABLE_WALLET diff --git a/src/key.cpp b/src/key.cpp index aa24f0a622..4747beffb4 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -631,3 +631,15 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { out.nChild = nChild; return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode); } + +bool ECC_InitSanityCheck() { + EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); + if(pkey == NULL) + return false; + EC_KEY_free(pkey); + + // TODO Is there more EC functionality that could be missing? + return true; +} + + diff --git a/src/key.h b/src/key.h index 983775fd23..11dc65de8c 100644 --- a/src/key.h +++ b/src/key.h @@ -306,4 +306,7 @@ struct CExtKey { void SetMaster(const unsigned char *seed, unsigned int nSeedLen); }; +/** Check that required EC support is available at runtime */ +bool ECC_InitSanityCheck(void); + #endif From 71aaff393f06378150612fc618b6c3f84c1d2066 Mon Sep 17 00:00:00 2001 From: Kosta Zertsekel Date: Wed, 4 Jun 2014 07:36:45 +0300 Subject: [PATCH 113/336] Remove double-dash parameters from mapArgs Should be merged after pull request #4281 ("Add `-version` option to get just the version #4281"), because is changed "--help" to "-help". Checked that grep of 'mapArgs.count("--' returned only three places that are fixed by pull request #4281. --- src/util.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 205af738d5..752ebb7bf1 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -459,6 +459,7 @@ void ParseParameters(int argc, const char* const argv[]) { mapArgs.clear(); mapMultiArgs.clear(); + for (int i = 1; i < argc; i++) { std::string str(argv[i]); @@ -474,9 +475,15 @@ void ParseParameters(int argc, const char* const argv[]) if (boost::algorithm::starts_with(str, "/")) str = "-" + str.substr(1); #endif + if (str[0] != '-') break; + // Interpret --foo as -foo. + // If both --foo and -foo are set, the last takes effect. + if (str.length() > 1 && str[1] == '-') + str = str.substr(1); + mapArgs[str] = strValue; mapMultiArgs[str].push_back(strValue); } @@ -484,19 +491,8 @@ void ParseParameters(int argc, const char* const argv[]) // New 0.6 features: BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) { - string name = entry.first; - - // interpret --foo as -foo (as long as both are not set) - if (name.find("--") == 0) - { - std::string singleDash(name.begin()+1, name.end()); - if (mapArgs.count(singleDash) == 0) - mapArgs[singleDash] = entry.second; - name = singleDash; - } - // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set - InterpretNegativeSetting(name, mapArgs); + InterpretNegativeSetting(entry.first, mapArgs); } } From 1712adbe0b084b6907b82db350a51ab44f8c3117 Mon Sep 17 00:00:00 2001 From: jtimon Date: Fri, 7 Mar 2014 17:59:30 -0800 Subject: [PATCH 114/336] Add MiningRequiresPeers chain parameter --- src/chainparams.cpp | 1 + src/chainparams.h | 2 ++ src/miner.cpp | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f5cf846a01..ff104e7c84 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -246,6 +246,7 @@ public: } virtual bool RequireRPCPassword() const { return false; } + virtual bool MiningRequiresPeers() const { return false; } virtual Network NetworkID() const { return CChainParams::REGTEST; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index 5600b904cc..a73279fe67 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -59,6 +59,8 @@ public: int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; } virtual const CBlock& GenesisBlock() const = 0; virtual bool RequireRPCPassword() const { return true; } + /* Make miner wait to have peers to avoid wasting work */ + virtual bool MiningRequiresPeers() const { return true; } const string& DataDir() const { return strDataDir; } virtual Network NetworkID() const = 0; const vector& DNSSeeds() const { return vSeeds; } diff --git a/src/miner.cpp b/src/miner.cpp index 94fc8e3888..3d46a0d83e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -512,7 +512,7 @@ void static BitcoinMiner(CWallet *pwallet) unsigned int nExtraNonce = 0; try { while (true) { - if (Params().NetworkID() != CChainParams::REGTEST) { + if (Params().MiningRequiresPeers()) { // Busy-wait for the network to come online so we don't waste time mining // on an obsolete chain. In regtest mode we expect to fly solo. while (vNodes.empty()) @@ -620,7 +620,8 @@ void static BitcoinMiner(CWallet *pwallet) // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); - if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST) + // Regtest mode doesn't require peers + if (vNodes.empty() && Params().MiningRequiresPeers()) break; if (nBlockNonce >= 0xffff0000) break; From bfa9a1a638d69ec3edc2473eef5f2eee43af5a9d Mon Sep 17 00:00:00 2001 From: jtimon Date: Sun, 9 Mar 2014 13:36:55 -0700 Subject: [PATCH 115/336] Add MineBlocksOnDemand chain parameter --- src/chainparams.cpp | 1 + src/chainparams.h | 3 +++ src/miner.cpp | 5 ++--- src/rpcmining.cpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ff104e7c84..d7205fa5cb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -247,6 +247,7 @@ public: virtual bool RequireRPCPassword() const { return false; } virtual bool MiningRequiresPeers() const { return false; } + virtual bool MineBlocksOnDemand() const { return true; } virtual Network NetworkID() const { return CChainParams::REGTEST; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index a73279fe67..d76b1a2280 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -62,6 +62,9 @@ public: /* Make miner wait to have peers to avoid wasting work */ virtual bool MiningRequiresPeers() const { return true; } const string& DataDir() const { return strDataDir; } + /* Make miner stop after a block is found. In RPC, don't return + * until nGenProcLimit blocks are generated */ + virtual bool MineBlocksOnDemand() const { return false; } virtual Network NetworkID() const = 0; const vector& DNSSeeds() const { return vSeeds; } const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } diff --git a/src/miner.cpp b/src/miner.cpp index 3d46a0d83e..e980fdc42d 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -580,9 +580,8 @@ void static BitcoinMiner(CWallet *pwallet) CheckWork(pblock, *pwallet, reservekey); SetThreadPriority(THREAD_PRIORITY_LOWEST); - // In regression test mode, stop mining after a block is found. This - // allows developers to controllably generate a block on demand. - if (Params().NetworkID() == CChainParams::REGTEST) + // In regression test mode, stop mining after a block is found. + if (Params().MineBlocksOnDemand()) throw boost::thread_interrupted(); break; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 23876c603d..70adae1467 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -174,7 +174,7 @@ Value setgenerate(const Array& params, bool fHelp) } // -regtest mode: don't return until nGenProcLimit blocks are generated - if (fGenerate && Params().NetworkID() == CChainParams::REGTEST) + if (fGenerate && Params().MineBlocksOnDemand()) { int nHeightStart = 0; int nHeightEnd = 0; From 2595b9ac23735649f4601c27924821641611696e Mon Sep 17 00:00:00 2001 From: jtimon Date: Fri, 7 Mar 2014 22:47:56 -0800 Subject: [PATCH 116/336] Add DefaultMinerThreads chain parameter --- src/chainparams.cpp | 2 ++ src/chainparams.h | 3 +++ src/miner.cpp | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index d7205fa5cb..64723978bb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -112,6 +112,7 @@ public: nRPCPort = 8332; bnProofOfWorkLimit = ~uint256(0) >> 32; nSubsidyHalvingInterval = 210000; + nMinerThreads = 0; // Build the genesis block. Note that the output of the genesis coinbase cannot // be spent as it did not originally exist in the database. @@ -233,6 +234,7 @@ public: pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; nSubsidyHalvingInterval = 150; + nMinerThreads = 1; bnProofOfWorkLimit = ~uint256(0) >> 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; diff --git a/src/chainparams.h b/src/chainparams.h index d76b1a2280..f331d956fe 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -57,6 +57,8 @@ public: int GetDefaultPort() const { return nDefaultPort; } const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; } + /* Used if GenerateBitcoins is called with a negative number of threads */ + int DefaultMinerThreads() const { return nMinerThreads; } virtual const CBlock& GenesisBlock() const = 0; virtual bool RequireRPCPassword() const { return true; } /* Make miner wait to have peers to avoid wasting work */ @@ -82,6 +84,7 @@ protected: uint256 bnProofOfWorkLimit; int nSubsidyHalvingInterval; string strDataDir; + int nMinerThreads; vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; }; diff --git a/src/miner.cpp b/src/miner.cpp index e980fdc42d..44c2faaa4c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -652,8 +652,9 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) static boost::thread_group* minerThreads = NULL; if (nThreads < 0) { - if (Params().NetworkID() == CChainParams::REGTEST) - nThreads = 1; + // In regtest threads defaults to 1 + if (Params().DefaultMinerThreads()) + nThreads = Params().DefaultMinerThreads(); else nThreads = boost::thread::hardware_concurrency(); } From cb9bd83bba86e73e3720110ce47600b6f895573c Mon Sep 17 00:00:00 2001 From: jtimon Date: Sun, 9 Mar 2014 18:35:41 -0700 Subject: [PATCH 117/336] Add DefaultCheckMemPool chain parameter --- src/chainparams.cpp | 1 + src/chainparams.h | 2 ++ src/init.cpp | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 64723978bb..75a14c6013 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -250,6 +250,7 @@ public: virtual bool RequireRPCPassword() const { return false; } virtual bool MiningRequiresPeers() const { return false; } virtual bool MineBlocksOnDemand() const { return true; } + virtual bool DefaultCheckMemPool() const { return true; } virtual Network NetworkID() const { return CChainParams::REGTEST; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index f331d956fe..bc982ee040 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,6 +63,8 @@ public: virtual bool RequireRPCPassword() const { return true; } /* Make miner wait to have peers to avoid wasting work */ virtual bool MiningRequiresPeers() const { return true; } + /* Default value for -checkmempool argument */ + virtual bool DefaultCheckMemPool() const { return false; } const string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ diff --git a/src/init.cpp b/src/init.cpp index 840a07d610..a225c3f964 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -517,7 +517,8 @@ bool AppInit2(boost::thread_group& threadGroup) InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net")); fBenchmark = GetBoolArg("-benchmark", false); - mempool.setSanityCheck(GetBoolArg("-checkmempool", RegTest())); + // Checkmempool defaults to true in regtest mode + mempool.setSanityCheck(GetBoolArg("-checkmempool", Params().DefaultCheckMemPool())); Checkpoints::fEnabled = GetBoolArg("-checkpoints", true); // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency From 8d26721498eb608b1ee5fd4d10083739a77b5905 Mon Sep 17 00:00:00 2001 From: jtimon Date: Fri, 7 Mar 2014 23:06:22 -0800 Subject: [PATCH 118/336] Get rid of RegTest() --- src/chainparams.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/chainparams.h b/src/chainparams.h index bc982ee040..f0c90bf50f 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -111,8 +111,4 @@ inline bool TestNet() { return Params().NetworkID() == CChainParams::TESTNET; } -inline bool RegTest() { - return Params().NetworkID() == CChainParams::REGTEST; -} - #endif From d754f34e8d470d5d89e2bc31ff1ab60ae5889266 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 19:52:26 +0100 Subject: [PATCH 119/336] Move majority constants to chainparams --- src/chainparams.cpp | 9 +++++++++ src/chainparams.h | 8 ++++++++ src/main.cpp | 34 ++++++++++++++-------------------- src/main.h | 5 +++-- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 75a14c6013..86d80629eb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -112,6 +112,9 @@ public: nRPCPort = 8332; bnProofOfWorkLimit = ~uint256(0) >> 32; nSubsidyHalvingInterval = 210000; + nEnforceBlockUpgradeMajority = 750; + nRejectBlockOutdatedMajority = 950; + nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 0; // Build the genesis block. Note that the output of the genesis coinbase cannot @@ -199,6 +202,9 @@ public: vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; nRPCPort = 18332; + nEnforceBlockUpgradeMajority = 51; + nRejectBlockOutdatedMajority = 75; + nToCheckBlockUpgradeMajority = 100; strDataDir = "testnet3"; // Modify the testnet genesis block so the timestamp is valid for a later start. @@ -234,6 +240,9 @@ public: pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; nSubsidyHalvingInterval = 150; + nEnforceBlockUpgradeMajority = 750; + nRejectBlockOutdatedMajority = 950; + nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 1; bnProofOfWorkLimit = ~uint256(0) >> 1; genesis.nTime = 1296688602; diff --git a/src/chainparams.h b/src/chainparams.h index f0c90bf50f..f400907d73 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -57,6 +57,11 @@ public: int GetDefaultPort() const { return nDefaultPort; } const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; } + /* Used to check majorities for block version upgrade */ + int EnforceBlockUpgradeMajority() const { return nEnforceBlockUpgradeMajority; } + int RejectBlockOutdatedMajority() const { return nRejectBlockOutdatedMajority; } + int ToCheckBlockUpgradeMajority() const { return nToCheckBlockUpgradeMajority; } + /* Used if GenerateBitcoins is called with a negative number of threads */ int DefaultMinerThreads() const { return nMinerThreads; } virtual const CBlock& GenesisBlock() const = 0; @@ -85,6 +90,9 @@ protected: int nRPCPort; uint256 bnProofOfWorkLimit; int nSubsidyHalvingInterval; + int nEnforceBlockUpgradeMajority; + int nRejectBlockOutdatedMajority; + int nToCheckBlockUpgradeMajority; string strDataDir; int nMinerThreads; vector vSeeds; diff --git a/src/main.cpp b/src/main.cpp index 30fa9c6d70..e6519864d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2469,14 +2469,11 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.nVersion < 2) + if (block.nVersion < 2 && + CBlockIndex::IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) { - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100))) - { - return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), - REJECT_OBSOLETE, "bad-version"); - } + return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), + REJECT_OBSOLETE, "bad-version"); } } @@ -2517,19 +2514,15 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - if (block.nVersion >= 2) + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if (block.nVersion >= 2 && + CBlockIndex::IsSuperMajority(2, pindex->pprev, Params().EnforceBlockUpgradeMajority())) { - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) - { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || - !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { - pindex->nStatus |= BLOCK_FAILED_VALID; - return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), - REJECT_INVALID, "bad-cb-height"); - } + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), REJECT_INVALID, "bad-cb-height"); } } @@ -2563,8 +2556,9 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, return true; } -bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) +bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired) { + unsigned int nToCheck = Params().ToCheckBlockUpgradeMajority(); unsigned int nFound = 0; for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) { diff --git a/src/main.h b/src/main.h index 42cf4a0861..58515b44b9 100644 --- a/src/main.h +++ b/src/main.h @@ -848,10 +848,11 @@ public: /** * Returns true if there are nRequired or more blocks of minVersion or above - * in the last nToCheck blocks, starting at pstart and going backwards. + * in the last Params().ToCheckBlockUpgradeMajority() blocks, starting at pstart + * and going backwards. */ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, - unsigned int nRequired, unsigned int nToCheck); + unsigned int nRequired); std::string ToString() const { From 21913a9ac9525547ebe18619748abb18a2ca8cdf Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 20:09:12 +0100 Subject: [PATCH 120/336] Add AllowMinDifficultyBlocks chain parameter --- src/chainparams.cpp | 2 ++ src/chainparams.h | 2 ++ src/main.cpp | 6 +++--- src/miner.cpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 86d80629eb..c43de2e72d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -224,6 +224,8 @@ public: base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF); base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94); } + + virtual bool AllowMinDifficultyBlocks() const { return true; } virtual Network NetworkID() const { return CChainParams::TESTNET; } }; static CTestNetParams testNetParams; diff --git a/src/chainparams.h b/src/chainparams.h index f400907d73..e1ce86550c 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -70,6 +70,8 @@ public: virtual bool MiningRequiresPeers() const { return true; } /* Default value for -checkmempool argument */ virtual bool DefaultCheckMemPool() const { return false; } + /* Allow mining of a min-difficulty block */ + virtual bool AllowMinDifficultyBlocks() const { return false; } const string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ diff --git a/src/main.cpp b/src/main.cpp index e6519864d8..7d0a57657b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1210,7 +1210,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) const uint256 &bnLimit = Params().ProofOfWorkLimit(); // Testnet has min-difficulty blocks // after nTargetSpacing*2 time between blocks: - if (TestNet() && nTime > nTargetSpacing*2) + if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2) return bnLimit.GetCompact(); uint256 bnResult; @@ -1238,7 +1238,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // Only change once per interval if ((pindexLast->nHeight+1) % nInterval != 0) { - if (TestNet()) + if (Params().AllowMinDifficultyBlocks()) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes @@ -1468,7 +1468,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev) block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: - if (TestNet()) + if (Params().AllowMinDifficultyBlocks()) block.nBits = GetNextWorkRequired(pindexPrev, &block); } diff --git a/src/miner.cpp b/src/miner.cpp index 44c2faaa4c..708b9248f3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -632,7 +632,7 @@ void static BitcoinMiner(CWallet *pwallet) // Update nTime every few seconds UpdateTime(*pblock, pindexPrev); nBlockTime = ByteReverse(pblock->nTime); - if (TestNet()) + if (Params().AllowMinDifficultyBlocks()) { // Changing pblock->nTime can change work required on testnet: nBlockBits = ByteReverse(pblock->nBits); From cfeb8235fda44aa71fb99ce583c2c2049105ad5a Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 20:19:48 +0100 Subject: [PATCH 121/336] Add RequireStandard chain parameter --- src/chainparams.cpp | 2 ++ src/chainparams.h | 2 ++ src/main.cpp | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c43de2e72d..f10599690f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -226,6 +226,7 @@ public: } virtual bool AllowMinDifficultyBlocks() const { return true; } + virtual bool RequireStandard() const { return false; } virtual Network NetworkID() const { return CChainParams::TESTNET; } }; static CTestNetParams testNetParams; @@ -262,6 +263,7 @@ public: virtual bool MiningRequiresPeers() const { return false; } virtual bool MineBlocksOnDemand() const { return true; } virtual bool DefaultCheckMemPool() const { return true; } + virtual bool RequireStandard() const { return false; } virtual Network NetworkID() const { return CChainParams::REGTEST; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index e1ce86550c..881eb2294d 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -72,6 +72,8 @@ public: virtual bool DefaultCheckMemPool() const { return false; } /* Allow mining of a min-difficulty block */ virtual bool AllowMinDifficultyBlocks() const { return false; } + /* Make standard checks */ + virtual bool RequireStandard() const { return true; } const string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ diff --git a/src/main.cpp b/src/main.cpp index 7d0a57657b..2f24beecc6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -833,7 +833,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Rather not work on nonstandard transactions (unless -testnet/-regtest) string reason; - if (Params().NetworkID() == CChainParams::MAIN && !IsStandardTx(tx, reason)) + if (Params().RequireStandard() && !IsStandardTx(tx, reason)) return state.DoS(0, error("AcceptToMemoryPool : nonstandard transaction: %s", reason), REJECT_NONSTANDARD, reason); @@ -894,7 +894,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // Check for non-standard pay-to-script-hash in inputs - if (Params().NetworkID() == CChainParams::MAIN && !AreInputsStandard(tx, view)) + if (Params().RequireStandard() && !AreInputsStandard(tx, view)) return error("AcceptToMemoryPool: : nonstandard transaction input"); // Note: if you modify this code to accept non-standard transactions, then From 6fc0fa63d9eb6bdfcdfd2fd9792d23059c763534 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 20:20:43 +0100 Subject: [PATCH 122/336] Add RPCisTestNet chain parameter --- src/chainparams.cpp | 1 + src/chainparams.h | 2 ++ src/rpcmining.cpp | 2 +- src/rpcmisc.cpp | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f10599690f..109ee02b0a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -227,6 +227,7 @@ public: virtual bool AllowMinDifficultyBlocks() const { return true; } virtual bool RequireStandard() const { return false; } + virtual bool RPCisTestNet() const { return true; } virtual Network NetworkID() const { return CChainParams::TESTNET; } }; static CTestNetParams testNetParams; diff --git a/src/chainparams.h b/src/chainparams.h index 881eb2294d..3849d33aca 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -74,6 +74,8 @@ public: virtual bool AllowMinDifficultyBlocks() const { return false; } /* Make standard checks */ virtual bool RequireStandard() const { return true; } + /* Make standard checks */ + virtual bool RPCisTestNet() const { return false; } const string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 70adae1467..edf91023dc 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -265,7 +265,7 @@ Value getmininginfo(const Array& params, bool fHelp) obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", TestNet())); + obj.push_back(Pair("testnet", Params().RPCisTestNet())); #ifdef ENABLE_WALLET obj.push_back(Pair("generate", getgenerate(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 27d6d61a36..a1793e2e43 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -73,7 +73,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", TestNet())); + obj.push_back(Pair("testnet", Params().RPCisTestNet())); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); From a3d946ebdc2eebef9ccdc2c883f8abfebcf0f653 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 20:22:14 +0100 Subject: [PATCH 123/336] Get rid of TestNet() --- src/bitcoin-cli.cpp | 2 +- src/bitcoind.cpp | 2 +- src/chainparams.h | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index ce9e7a4027..29efdfa821 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -33,7 +33,7 @@ static bool AppInitRPC(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } - // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause) + // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) if (!SelectParamsFromCommandLine()) { fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 9b535c2e6b..704332c39b 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -77,7 +77,7 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } - // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause) + // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) if (!SelectParamsFromCommandLine()) { fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; diff --git a/src/chainparams.h b/src/chainparams.h index 3849d33aca..653ca20f01 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -120,9 +120,4 @@ void SelectParams(CChainParams::Network network); */ bool SelectParamsFromCommandLine(); -inline bool TestNet() { - // Note: it's deliberate that this returns "false" for regression test mode. - return Params().NetworkID() == CChainParams::TESTNET; -} - #endif From c8c52de3a05b617bc399e2dd45901e74237b7fc1 Mon Sep 17 00:00:00 2001 From: jtimon Date: Wed, 4 Jun 2014 12:51:29 +0200 Subject: [PATCH 124/336] Replace virtual methods with static attributes, chainparams.h depends on protocol.h instead of the other way around --- src/alert.cpp | 1 + src/chainparams.cpp | 51 +++++++++++++++++++++++---------------------- src/chainparams.h | 38 ++++++++++++++++++++------------- src/protocol.cpp | 1 + src/protocol.h | 3 ++- 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/src/alert.cpp b/src/alert.cpp index 99164d63e5..638f0d7a1c 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -5,6 +5,7 @@ #include "alert.h" +#include "chainparams.h" #include "key.h" #include "net.h" #include "ui_interface.h" diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 109ee02b0a..3f4d7f7064 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -6,8 +6,6 @@ #include "chainparams.h" #include "assert.h" -#include "core.h" -#include "protocol.h" #include "util.h" #include @@ -100,6 +98,7 @@ unsigned int pnSeed[] = class CMainParams : public CChainParams { public: CMainParams() { + networkID = CChainParams::MAIN; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. @@ -171,27 +170,25 @@ public: addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; vFixedSeeds.push_back(addr); } - } - virtual const CBlock& GenesisBlock() const { return genesis; } - virtual Network NetworkID() const { return CChainParams::MAIN; } - - virtual const vector& FixedSeeds() const { - return vFixedSeeds; + fRequireRPCPassword = true; + fMiningRequiresPeers = true; + fDefaultCheckMemPool = false; + fAllowMinDifficultyBlocks = false; + fRequireStandard = true; + fRPCisTestNet = false; + fMineBlocksOnDemand = false; } -protected: - CBlock genesis; - vector vFixedSeeds; }; static CMainParams mainParams; - // // Testnet (v3) // class CTestNetParams : public CMainParams { public: CTestNetParams() { + networkID = CChainParams::TESTNET; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. @@ -223,22 +220,25 @@ public: base58Prefixes[SECRET_KEY] = list_of(239); base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF); base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94); - } - virtual bool AllowMinDifficultyBlocks() const { return true; } - virtual bool RequireStandard() const { return false; } - virtual bool RPCisTestNet() const { return true; } - virtual Network NetworkID() const { return CChainParams::TESTNET; } + fRequireRPCPassword = true; + fMiningRequiresPeers = true; + fDefaultCheckMemPool = false; + fAllowMinDifficultyBlocks = true; + fRequireStandard = false; + fRPCisTestNet = true; + fMineBlocksOnDemand = false; + } }; static CTestNetParams testNetParams; - // // Regression test // class CRegTestParams : public CTestNetParams { public: CRegTestParams() { + networkID = CChainParams::REGTEST; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; pchMessageStart[2] = 0xb5; @@ -258,14 +258,15 @@ public: assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. - } - virtual bool RequireRPCPassword() const { return false; } - virtual bool MiningRequiresPeers() const { return false; } - virtual bool MineBlocksOnDemand() const { return true; } - virtual bool DefaultCheckMemPool() const { return true; } - virtual bool RequireStandard() const { return false; } - virtual Network NetworkID() const { return CChainParams::REGTEST; } + fRequireRPCPassword = false; + fMiningRequiresPeers = false; + fDefaultCheckMemPool = true; + fAllowMinDifficultyBlocks = true; + fRequireStandard = false; + fRPCisTestNet = true; + fMineBlocksOnDemand = true; + } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index 653ca20f01..988e3ac3a4 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -7,17 +7,15 @@ #define BITCOIN_CHAIN_PARAMS_H #include "uint256.h" +#include "core.h" +#include "protocol.h" #include using namespace std; -#define MESSAGE_START_SIZE 4 typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; -class CAddress; -class CBlock; - struct CDNSSeedData { string name, host; CDNSSeedData(const string &strName, const string &strHost) : name(strName), host(strHost) {} @@ -64,26 +62,26 @@ public: /* Used if GenerateBitcoins is called with a negative number of threads */ int DefaultMinerThreads() const { return nMinerThreads; } - virtual const CBlock& GenesisBlock() const = 0; - virtual bool RequireRPCPassword() const { return true; } + const CBlock& GenesisBlock() const { return genesis; }; + bool RequireRPCPassword() const { return fRequireRPCPassword; } /* Make miner wait to have peers to avoid wasting work */ - virtual bool MiningRequiresPeers() const { return true; } + bool MiningRequiresPeers() const { return fMiningRequiresPeers; } /* Default value for -checkmempool argument */ - virtual bool DefaultCheckMemPool() const { return false; } + bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; } /* Allow mining of a min-difficulty block */ - virtual bool AllowMinDifficultyBlocks() const { return false; } + bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } /* Make standard checks */ - virtual bool RequireStandard() const { return true; } + bool RequireStandard() const { return fRequireStandard; } /* Make standard checks */ - virtual bool RPCisTestNet() const { return false; } + bool RPCisTestNet() const { return fRPCisTestNet; } const string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ - virtual bool MineBlocksOnDemand() const { return false; } - virtual Network NetworkID() const = 0; + bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } + Network NetworkID() const { return networkID; } const vector& DNSSeeds() const { return vSeeds; } - const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } - virtual const vector& FixedSeeds() const = 0; + const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } + const vector& FixedSeeds() const { return vFixedSeeds; } int RPCPort() const { return nRPCPort; } protected: CChainParams() {} @@ -103,6 +101,16 @@ protected: int nMinerThreads; vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; + Network networkID; + CBlock genesis; + vector vFixedSeeds; + bool fRequireRPCPassword; + bool fMiningRequiresPeers; + bool fDefaultCheckMemPool; + bool fAllowMinDifficultyBlocks; + bool fRequireStandard; + bool fRPCisTestNet; + bool fMineBlocksOnDemand; }; /** diff --git a/src/protocol.cpp b/src/protocol.cpp index c77a92f020..87b2f23873 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -5,6 +5,7 @@ #include "protocol.h" +#include "chainparams.h" #include "util.h" #ifndef WIN32 diff --git a/src/protocol.h b/src/protocol.h index e6f105fe5c..6de5d05a72 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -10,7 +10,6 @@ #ifndef __INCLUDED_PROTOCOL_H__ #define __INCLUDED_PROTOCOL_H__ -#include "chainparams.h" #include "netbase.h" #include "serialize.h" #include "uint256.h" @@ -19,6 +18,8 @@ #include #include +#define MESSAGE_START_SIZE 4 + /** Message header. * (4) message start. * (12) command. From 2871889e834b664bcaa3fdb3ecb6c5cdc751afb1 Mon Sep 17 00:00:00 2001 From: jtimon Date: Wed, 4 Jun 2014 12:52:15 +0200 Subject: [PATCH 125/336] net.h was using std namespace through chainparams.h included in protocol.h --- src/net.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net.h b/src/net.h index d3346873bc..d50cd92dba 100644 --- a/src/net.h +++ b/src/net.h @@ -129,7 +129,7 @@ struct LocalServiceInfo { }; extern CCriticalSection cs_mapLocalHost; -extern map mapLocalHost; +extern std::map mapLocalHost; class CNodeStats { From 7b45d943b29a443f1ac808c9ee4eeed6df0db9cc Mon Sep 17 00:00:00 2001 From: shshshsh Date: Fri, 30 May 2014 12:35:23 +0000 Subject: [PATCH 126/336] Make max number of orphan blocks kept in memory a startup parameter (fixes #4253) --- src/init.cpp | 1 + src/main.cpp | 2 +- src/main.h | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index bc4924b48d..995f2700cf 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -206,6 +206,7 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -dbcache= " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n"; strUsage += " -keypool= " + _("Set key pool size to (default: 100)") + "\n"; strUsage += " -loadblock= " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n"; + strUsage += " -maxorphanblocks= " + strprintf(_("Keep at most unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; strUsage += " -par= " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n"; strUsage += " -pid= " + _("Specify pid file (default: bitcoind.pid)") + "\n"; strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n"; diff --git a/src/main.cpp b/src/main.cpp index 18c00d90ac..5cb6e706bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1160,7 +1160,7 @@ uint256 static GetOrphanRoot(const uint256& hash) // Remove a random orphan block (which does not have any dependent orphans). void static PruneOrphanBlocks() { - if (mapOrphanBlocksByPrev.size() <= MAX_ORPHAN_BLOCKS) + if (mapOrphanBlocksByPrev.size() <= (size_t)std::max((int64_t)0, GetArg("-maxorphanblocks", DEFAULT_MAX_ORPHAN_BLOCKS))) return; // Pick a random orphan block. diff --git a/src/main.h b/src/main.h index 8a05eb60d2..26f66630ae 100644 --- a/src/main.h +++ b/src/main.h @@ -45,8 +45,8 @@ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; /** The maximum number of orphan transactions kept in memory */ static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; -/** The maximum number of orphan blocks kept in memory */ -static const unsigned int MAX_ORPHAN_BLOCKS = 750; +/** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */ +static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750; /** The maximum size of a blk?????.dat file (since 0.8) */ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ From f0a83fc256023f68cc046bd096de69f16ce9d394 Mon Sep 17 00:00:00 2001 From: jtimon Date: Wed, 4 Jun 2014 15:25:58 +0200 Subject: [PATCH 127/336] Use Params().NetworkID() instead of TestNet() from the payment protocol --- src/qt/paymentserver.cpp | 14 ++++++++++++-- src/qt/paymentserver.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 4c45585685..20551591c3 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -490,6 +490,17 @@ bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPl return request.parse(data); } +std::string PaymentServer::mapNetworkIdToName(CChainParams::Network networkId) +{ + if (networkId == CChainParams::MAIN) + return "main"; + if (networkId == CChainParams::TESTNET) + return "test"; + if (networkId == CChainParams::REGTEST) + return "regtest"; + return ""; +} + bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient) { if (!optionsModel) @@ -499,8 +510,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins const payments::PaymentDetails& details = request.getDetails(); // Payment request network matches client network? - if ((details.network() == "main" && TestNet()) || - (details.network() == "test" && !TestNet())) + if (details.network() != mapNetworkIdToName(Params().NetworkID())) { emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), CClientUIInterface::MSG_ERROR); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index d84d09c57d..d6949a47ce 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -118,6 +118,7 @@ protected: private: static bool readPaymentRequest(const QString& filename, PaymentRequestPlus& request); + std::string mapNetworkIdToName(CChainParams::Network networkId); bool processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient); void fetchRequest(const QUrl& url); From 4a48a0671d2e02ba2a86af98282a452f23546b9e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 4 Jun 2014 12:27:44 +0200 Subject: [PATCH 128/336] Remove side effect in assertion in ProcessGetData A side-effect was introduced into an assertion in 7a0e84d. This commit fixes that. --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 30fa9c6d70..e71d2d0cbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3390,7 +3390,8 @@ void static ProcessGetData(CNode* pfrom) { // Send block from disk CBlock block; - assert(ReadBlockFromDisk(block, (*mi).second)); + if (!ReadBlockFromDisk(block, (*mi).second)) + assert(!"cannot load block from disk"); if (inv.type == MSG_BLOCK) pfrom->PushMessage("block", block); else // MSG_FILTERED_BLOCK) From 5bd02cf715dcb44cfc797c0d1fb94b80350b6489 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 4 Jun 2014 21:19:22 +0200 Subject: [PATCH 129/336] log used config file to debug.log on startup --- src/init.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/init.cpp b/src/init.cpp index 6a21dee634..96f7f7b3c8 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -614,6 +614,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", strDataDir); + LogPrintf("Using config file %s\n", GetConfigFile().string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); std::ostringstream strErrors; From fe6bff2eaec35c3dc292af883a6e82397e440c22 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 4 Jun 2014 22:00:59 +0200 Subject: [PATCH 130/336] [Qt] add BerkeleyDB version info to RPCConsole - to match info function between debug.log and RPCConsole --- src/qt/forms/rpcconsole.ui | 64 +++++++++++++++++++++++++++----------- src/qt/rpcconsole.cpp | 10 +++++- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index bf737d9b99..1e574e8527 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -113,14 +113,17 @@ - + - Build date + Using BerkeleyDB version + + + 10 - + IBeamCursor @@ -136,14 +139,14 @@ - + - Startup time + Build date - + IBeamCursor @@ -159,6 +162,29 @@ + + + Startup time + + + + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + @@ -171,14 +197,14 @@ - + Name - + IBeamCursor @@ -194,14 +220,14 @@ - + Number of connections - + IBeamCursor @@ -217,7 +243,7 @@ - + @@ -230,14 +256,14 @@ - + Current number of blocks - + IBeamCursor @@ -253,14 +279,14 @@ - + Last block time - + IBeamCursor @@ -276,7 +302,7 @@ - + Qt::Vertical @@ -289,7 +315,7 @@ - + @@ -302,7 +328,7 @@ - + Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files. @@ -315,7 +341,7 @@ - + Qt::Vertical diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 3b7d37ff39..6a8bce25d4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -15,7 +15,9 @@ #include "util.h" #include "json/json_spirit_value.h" +#include #include + #include #include #include @@ -216,8 +218,14 @@ RPCConsole::RPCConsole(QWidget *parent) : connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); - // set OpenSSL version label + // set library version labels ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); +#ifdef ENABLE_WALLET + ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); +#else + ui->label_berkeleyDBVersion->hide(); + ui->berkeleyDBVersion->hide(); +#endif startExecutor(); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); From a92aded70ec2346c3f07ff1cf8eb97101a76912f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 5 Jun 2014 07:00:16 +0200 Subject: [PATCH 131/336] Fix GUI build with `--disable-wallet` fe6bff2 and 65f78a1 broke it. Minor build changes. --- src/qt/Makefile.am | 2 +- src/qt/rpcconsole.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am index 1d85113d78..d527f790ef 100644 --- a/src/qt/Makefile.am +++ b/src/qt/Makefile.am @@ -276,6 +276,7 @@ BITCOIN_QT_CPP = \ notificator.cpp \ optionsdialog.cpp \ optionsmodel.cpp \ + peertablemodel.cpp \ qvalidatedlineedit.cpp \ qvaluecombobox.cpp \ rpcconsole.cpp \ @@ -296,7 +297,6 @@ BITCOIN_QT_CPP += \ overviewpage.cpp \ paymentrequestplus.cpp \ paymentserver.cpp \ - peertablemodel.cpp \ receivecoinsdialog.cpp \ receiverequestdialog.cpp \ recentrequeststablemodel.cpp \ diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 6a8bce25d4..0d3e11f4ac 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -15,7 +15,9 @@ #include "util.h" #include "json/json_spirit_value.h" +#ifdef ENABLE_WALLET #include +#endif #include #include From 7d4dda7630a67ae1aacfc799ed743e69562a41df Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 5 Jun 2014 14:52:07 +0200 Subject: [PATCH 132/336] Remove global strWalletFile As it says on the tin. There is no need to have this variable be global, it's only used in AppInit2. --- src/init.cpp | 3 +-- src/init.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 96f7f7b3c8..d924bd293b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -40,7 +40,6 @@ using namespace std; using namespace boost; #ifdef ENABLE_WALLET -std::string strWalletFile; CWallet* pwalletMain; #endif @@ -584,7 +583,7 @@ bool AppInit2(boost::thread_group& threadGroup) } bSpendZeroConfChange = GetArg("-spendzeroconfchange", true); - strWalletFile = GetArg("-wallet", "wallet.dat"); + std::string strWalletFile = GetArg("-wallet", "wallet.dat"); #endif // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log diff --git a/src/init.h b/src/init.h index 2f56923055..4a967bea37 100644 --- a/src/init.h +++ b/src/init.h @@ -14,7 +14,6 @@ namespace boost { class thread_group; }; -extern std::string strWalletFile; extern CWallet* pwalletMain; void StartShutdown(); From 6e7c4d17d8abb4b1c8b91504699ce6970e01a1fb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 5 Jun 2014 15:44:35 +0200 Subject: [PATCH 133/336] gitian: upgrade OpenSSL to 1.0.1h Upgrade for https://www.openssl.org/news/secadv_20140605.txt Just in case - there is no vulnerability that affects ecdsa signing or verification. The MITM attack vulnerability (CVE-2014-0224) may have some effect on our usage of SSL/TLS. As long as payment requests are signed (which is the common case), usage of the payment protocol should also not be affected. The TLS usage in RPC may be at risk for MITM attacks. If you have `-rpcssl` enabled, be sure to update OpenSSL as soon as possible. --- contrib/gitian-descriptors/deps-linux.yml | 10 +++++----- contrib/gitian-descriptors/deps-win.yml | 10 +++++----- contrib/gitian-descriptors/gitian-linux.yml | 6 +++--- contrib/gitian-descriptors/gitian-osx-bitcoin.yml | 8 ++++---- contrib/gitian-descriptors/gitian-osx-depends.yml | 10 +++++----- contrib/gitian-descriptors/gitian-osx-qt.yml | 6 +++--- contrib/gitian-descriptors/gitian-win.yml | 6 +++--- contrib/gitian-descriptors/qt-win.yml | 6 +++--- doc/release-process.md | 10 +++++----- 9 files changed, 36 insertions(+), 36 deletions(-) diff --git a/contrib/gitian-descriptors/deps-linux.yml b/contrib/gitian-descriptors/deps-linux.yml index af10461b83..8221222133 100644 --- a/contrib/gitian-descriptors/deps-linux.yml +++ b/contrib/gitian-descriptors/deps-linux.yml @@ -16,7 +16,7 @@ packages: reference_datetime: "2013-06-01 00:00:00" remotes: [] files: -- "openssl-1.0.1g.tar.gz" +- "openssl-1.0.1h.tar.gz" - "miniupnpc-1.9.tar.gz" - "qrencode-3.4.3.tar.bz2" - "protobuf-2.5.0.tar.bz2" @@ -30,15 +30,15 @@ script: | export TZ=UTC export LIBRARY_PATH="$STAGING/lib" # Integrity Check - echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c + echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c # - tar xzf openssl-1.0.1g.tar.gz - cd openssl-1.0.1g + tar xzf openssl-1.0.1h.tar.gz + cd openssl-1.0.1h # need -fPIC to avoid relocation error in 64 bit builds ./config no-shared no-zlib no-dso no-krb5 --openssldir=$STAGING -fPIC # need to build OpenSSL with faketime because a timestamp is embedded into cversion.o @@ -95,4 +95,4 @@ script: | done # cd $STAGING - find include lib bin host | sort | zip -X@ $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r5.zip + find include lib bin host | sort | zip -X@ $OUTDIR/bitcoin-deps-linux${GBUILD_BITS}-gitian-r6.zip diff --git a/contrib/gitian-descriptors/deps-win.yml b/contrib/gitian-descriptors/deps-win.yml index 17ac413d80..fabc2949eb 100644 --- a/contrib/gitian-descriptors/deps-win.yml +++ b/contrib/gitian-descriptors/deps-win.yml @@ -14,7 +14,7 @@ packages: reference_datetime: "2011-01-30 00:00:00" remotes: [] files: -- "openssl-1.0.1g.tar.gz" +- "openssl-1.0.1h.tar.gz" - "db-4.8.30.NC.tar.gz" - "miniupnpc-1.9.tar.gz" - "zlib-1.2.8.tar.gz" @@ -28,7 +28,7 @@ script: | INDIR=$HOME/build TEMPDIR=$HOME/tmp # Input Integrity Check - echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c + echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c echo "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d zlib-1.2.8.tar.gz" | sha256sum -c @@ -48,8 +48,8 @@ script: | mkdir -p $INSTALLPREFIX $BUILDDIR cd $BUILDDIR # - tar xzf $INDIR/openssl-1.0.1g.tar.gz - cd openssl-1.0.1g + tar xzf $INDIR/openssl-1.0.1h.tar.gz + cd openssl-1.0.1h if [ "$BITS" == "32" ]; then OPENSSL_TGT=mingw else @@ -124,5 +124,5 @@ script: | done # cd $INSTALLPREFIX - find include lib | sort | zip -X@ $OUTDIR/bitcoin-deps-win$BITS-gitian-r12.zip + find include lib | sort | zip -X@ $OUTDIR/bitcoin-deps-win$BITS-gitian-r13.zip done # for BITS in diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index bb59e1cecb..65a6c3c1e9 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -25,8 +25,8 @@ remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: -- "bitcoin-deps-linux32-gitian-r5.zip" -- "bitcoin-deps-linux64-gitian-r5.zip" +- "bitcoin-deps-linux32-gitian-r6.zip" +- "bitcoin-deps-linux64-gitian-r6.zip" - "boost-linux32-1.55.0-gitian-r1.zip" - "boost-linux64-1.55.0-gitian-r1.zip" - "qt-linux32-4.6.4-gitian-r1.tar.gz" @@ -43,7 +43,7 @@ script: | # mkdir -p $STAGING cd $STAGING - unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r5.zip + unzip ../build/bitcoin-deps-linux${GBUILD_BITS}-gitian-r6.zip unzip ../build/boost-linux${GBUILD_BITS}-1.55.0-gitian-r1.zip tar -zxf ../build/qt-linux${GBUILD_BITS}-4.6.4-gitian-r1.tar.gz cd ../build diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml index e29047d610..44b5de9be3 100644 --- a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml +++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml @@ -18,8 +18,8 @@ remotes: "dir": "bitcoin" files: - "osx-native-depends-r3.tar.gz" -- "osx-depends-r3.tar.gz" -- "osx-depends-qt-5.2.1-r3.tar.gz" +- "osx-depends-r4.tar.gz" +- "osx-depends-qt-5.2.1-r4.tar.gz" - "MacOSX10.7.sdk.tar.gz" script: | @@ -37,8 +37,8 @@ script: | tar -C osx-cross-depends/SDKs -xf ${SOURCES_PATH}/MacOSX10.7.sdk.tar.gz tar -C osx-cross-depends -xf osx-native-depends-r3.tar.gz - tar -C osx-cross-depends -xf osx-depends-r3.tar.gz - tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r3.tar.gz + tar -C osx-cross-depends -xf osx-depends-r4.tar.gz + tar -C osx-cross-depends -xf osx-depends-qt-5.2.1-r4.tar.gz export PATH=`pwd`/osx-cross-depends/native-prefix/bin:$PATH cd bitcoin diff --git a/contrib/gitian-descriptors/gitian-osx-depends.yml b/contrib/gitian-descriptors/gitian-osx-depends.yml index adc86e5cb4..07a021cf0c 100644 --- a/contrib/gitian-descriptors/gitian-osx-depends.yml +++ b/contrib/gitian-descriptors/gitian-osx-depends.yml @@ -15,7 +15,7 @@ files: - "boost_1_55_0.tar.bz2" - "db-4.8.30.NC.tar.gz" - "miniupnpc-1.9.tar.gz" -- "openssl-1.0.1g.tar.gz" +- "openssl-1.0.1h.tar.gz" - "protobuf-2.5.0.tar.bz2" - "qrencode-3.4.3.tar.bz2" - "MacOSX10.7.sdk.tar.gz" @@ -26,11 +26,11 @@ script: | echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | sha256sum -c echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c echo "2923e453e880bb949e3d4da9f83dd3cb6f08946d35de0b864d0339cf70934464 miniupnpc-1.9.tar.gz" | sha256sum -c - echo "53cb818c3b90e507a8348f4f5eaedb05d8bfe5358aabb508b7263cc670c3e028 openssl-1.0.1g.tar.gz" | sha256sum -c + echo "9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093 openssl-1.0.1h.tar.gz" | sha256sum -c echo "13bfc5ae543cf3aa180ac2485c0bc89495e3ae711fc6fab4f8ffe90dfb4bb677 protobuf-2.5.0.tar.bz2" | sha256sum -c echo "dfd71487513c871bad485806bfd1fdb304dedc84d2b01a8fb8e0940b50597a98 qrencode-3.4.3.tar.bz2" | sha256sum -c - REVISION=r3 + REVISION=r4 export SOURCES_PATH=`pwd` export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export PATH=$HOME:$PATH @@ -88,8 +88,8 @@ script: | popd # openssl - SOURCE_FILE=${SOURCES_PATH}/openssl-1.0.1g.tar.gz - BUILD_DIR=${BUILD_BASE}/openssl-1.0.1g + SOURCE_FILE=${SOURCES_PATH}/openssl-1.0.1h.tar.gz + BUILD_DIR=${BUILD_BASE}/openssl-1.0.1h tar -C ${BUILD_BASE} -xf ${SOURCE_FILE} pushd ${BUILD_DIR} diff --git a/contrib/gitian-descriptors/gitian-osx-qt.yml b/contrib/gitian-descriptors/gitian-osx-qt.yml index b57908dbd9..5e0ad9222a 100644 --- a/contrib/gitian-descriptors/gitian-osx-qt.yml +++ b/contrib/gitian-descriptors/gitian-osx-qt.yml @@ -14,14 +14,14 @@ remotes: [] files: - "qt-everywhere-opensource-src-5.2.1.tar.gz" - "osx-native-depends-r3.tar.gz" -- "osx-depends-r3.tar.gz" +- "osx-depends-r4.tar.gz" - "MacOSX10.7.sdk.tar.gz" script: | echo "84e924181d4ad6db00239d87250cc89868484a14841f77fb85ab1f1dbdcd7da1 qt-everywhere-opensource-src-5.2.1.tar.gz" | sha256sum -c - REVISION=r3 + REVISION=r4 export SOURCES_PATH=`pwd` export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export ZERO_AR_DATE=1 @@ -73,7 +73,7 @@ script: | tar xf /home/ubuntu/build/osx-native-depends-r3.tar.gz export PATH=`pwd`/native-prefix/bin:$PATH - tar xf /home/ubuntu/build/osx-depends-r3.tar.gz + tar xf /home/ubuntu/build/osx-depends-r4.tar.gz SOURCE_FILE=${SOURCES_PATH}/qt-everywhere-opensource-src-5.2.1.tar.gz BUILD_DIR=${BUILD_BASE}/qt-everywhere-opensource-src-5.2.1 diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 2191fb36c7..245f15ccab 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -26,8 +26,8 @@ files: - "qt-win64-5.2.0-gitian-r3.zip" - "boost-win32-1.55.0-gitian-r6.zip" - "boost-win64-1.55.0-gitian-r6.zip" -- "bitcoin-deps-win32-gitian-r12.zip" -- "bitcoin-deps-win64-gitian-r12.zip" +- "bitcoin-deps-win32-gitian-r13.zip" +- "bitcoin-deps-win64-gitian-r13.zip" - "protobuf-win32-2.5.0-gitian-r4.zip" - "protobuf-win64-2.5.0-gitian-r4.zip" script: | @@ -61,7 +61,7 @@ script: | cd $STAGING unzip $INDIR/qt-win${BITS}-5.2.0-gitian-r3.zip unzip $INDIR/boost-win${BITS}-1.55.0-gitian-r6.zip - unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r12.zip + unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r13.zip unzip $INDIR/protobuf-win${BITS}-2.5.0-gitian-r4.zip if [ "$NEEDDIST" == "1" ]; then # Make source code archive which is architecture independent so it only needs to be done once diff --git a/contrib/gitian-descriptors/qt-win.yml b/contrib/gitian-descriptors/qt-win.yml index 8f24492b53..7000c70051 100644 --- a/contrib/gitian-descriptors/qt-win.yml +++ b/contrib/gitian-descriptors/qt-win.yml @@ -15,8 +15,8 @@ reference_datetime: "2011-01-30 00:00:00" remotes: [] files: - "qt-everywhere-opensource-src-5.2.0.tar.gz" -- "bitcoin-deps-win32-gitian-r12.zip" -- "bitcoin-deps-win64-gitian-r12.zip" +- "bitcoin-deps-win32-gitian-r13.zip" +- "bitcoin-deps-win64-gitian-r13.zip" script: | # Defines export TZ=UTC @@ -48,7 +48,7 @@ script: | # # Need mingw-compiled openssl from bitcoin-deps: cd $DEPSDIR - unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r12.zip + unzip $INDIR/bitcoin-deps-win${BITS}-gitian-r13.zip # cd $BUILDDIR # diff --git a/doc/release-process.md b/doc/release-process.md index 60b93b7680..5b96e53753 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -44,7 +44,7 @@ Release Process Fetch and build inputs: (first time, or when dependency versions change) wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.9.tar.gz' -O miniupnpc-1.9.tar.gz - wget 'https://www.openssl.org/source/openssl-1.0.1g.tar.gz' + wget 'https://www.openssl.org/source/openssl-1.0.1h.tar.gz' wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' wget 'http://zlib.net/zlib-1.2.8.tar.gz' wget 'ftp://ftp.simplesystems.org/pub/png/src/history/libpng16/libpng-1.6.8.tar.gz' @@ -89,16 +89,16 @@ Release Process The expected SHA256 hashes of the intermediate inputs are: - 35c3dfd8b9362f59e81b51881b295232e3bc9e286f1add193b59d486d9ac4a5c bitcoin-deps-linux32-gitian-r5.zip - 571789867d172500fa96d63d0ba8c5b1e1a3d6f44f720eddf2f93665affc88b3 bitcoin-deps-linux64-gitian-r5.zip + 46710f673467e367738d8806e45b4cb5931aaeea61f4b6b55a68eea56d5006c5 bitcoin-deps-linux32-gitian-r6.zip + f03be39fb26670243d3a659e64d18e19d03dec5c11e9912011107768390b5268 bitcoin-deps-linux64-gitian-r6.zip f29b7d9577417333fb56e023c2977f5726a7c297f320b175a4108cf7cd4c2d29 boost-linux32-1.55.0-gitian-r1.zip 88232451c4104f7eb16e469ac6474fd1231bd485687253f7b2bdf46c0781d535 boost-linux64-1.55.0-gitian-r1.zip 57e57dbdadc818cd270e7e00500a5e1085b3bcbdef69a885f0fb7573a8d987e1 qt-linux32-4.6.4-gitian-r1.tar.gz 60eb4b9c5779580b7d66529efa5b2836ba1a70edde2a0f3f696d647906a826be qt-linux64-4.6.4-gitian-r1.tar.gz 60dc2d3b61e9c7d5dbe2f90d5955772ad748a47918ff2d8b74e8db9b1b91c909 boost-win32-1.55.0-gitian-r6.zip f65fcaf346bc7b73bc8db3a8614f4f6bee2f61fcbe495e9881133a7c2612a167 boost-win64-1.55.0-gitian-r6.zip - acd59690a49dfbad6b436379843fe4ad1857ad91c603d52506690bc55f2a01a4 bitcoin-deps-win32-gitian-r12.zip - a3e5a62fcdad81f758e41848035e6a27be390981a14d590f2cf2509f87417a42 bitcoin-deps-win64-gitian-r12.zip + 70de248cd0dd7e7476194129e818402e974ca9c5751cbf591644dc9f332d3b59 bitcoin-deps-win32-gitian-r13.zip + 9eace4c76f639f4f3580a478eee4f50246e1bbb5ccdcf37a158261a5a3fa3e65 bitcoin-deps-win64-gitian-r13.zip 963e3e5e85879010a91143c90a711a5d1d5aba992e38672cdf7b54e42c56b2f1 qt-win32-5.2.0-gitian-r3.zip 751c579830d173ef3e6f194e83d18b92ebef6df03289db13ab77a52b6bc86ef0 qt-win64-5.2.0-gitian-r3.zip e2e403e1a08869c7eed4d4293bce13d51ec6a63592918b90ae215a0eceb44cb4 protobuf-win32-2.5.0-gitian-r4.zip From 65e8ba4dbed519a3be6d497063c3441550c4b3d6 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 28 May 2014 13:38:41 -0400 Subject: [PATCH 134/336] build: Switch to non-recursive make Build logic moves from individual Makefile.am's to include files, which the main src/Makefile.am includes. This avoids having to manage a gigantic single Makefile. TODO: Move the rules from the old Makefile.include to where they actually belong and nuke the old file. --- configure.ac | 5 +- src/Makefile.am | 21 +- src/Makefile.include | 17 +- src/Makefile.qt.include | 387 ++++++++++++++++++++++++++++++++++++ src/Makefile.qttest.include | 52 +++++ src/Makefile.test.include | 87 ++++++++ 6 files changed, 550 insertions(+), 19 deletions(-) create mode 100644 src/Makefile.qt.include create mode 100644 src/Makefile.qttest.include create mode 100644 src/Makefile.test.include diff --git a/configure.ac b/configure.ac index 3a8d33a5a0..d8521ad3ad 100644 --- a/configure.ac +++ b/configure.ac @@ -666,6 +666,9 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet == xyes]) +AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests == xyes]) +AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt == xyes]) +AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes]) AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) @@ -695,7 +698,7 @@ AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(BUILD_TEST) AC_SUBST(BUILD_QT) AC_SUBST(BUILD_TEST_QT) -AC_CONFIG_FILES([Makefile src/Makefile src/test/Makefile src/qt/Makefile src/qt/test/Makefile share/setup.nsi share/qt/Info.plist]) +AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/build-tests.sh],[chmod +x qa/pull-tester/build-tests.sh]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index a49ad58716..e7d121b4d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ noinst_LIBRARIES += libbitcoin_wallet.a endif bin_PROGRAMS = +TESTS = if BUILD_BITCOIND bin_PROGRAMS += bitcoind @@ -20,8 +21,6 @@ if BUILD_BITCOIN_CLI bin_PROGRAMS += bitcoin-cli endif -SUBDIRS = . $(BUILD_QT) $(BUILD_TEST) -DIST_SUBDIRS = . qt test .PHONY: FORCE # bitcoin core # BITCOIN_CORE_H = \ @@ -188,16 +187,24 @@ leveldb/%.a: CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ OPT="$(CXXFLAGS) $(CPPFLAGS)" -qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES) - @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" - @cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py - CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb Makefile.include +EXTRA_DIST = leveldb clean-local: -$(MAKE) -C leveldb clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno + +if ENABLE_TESTS +include Makefile.test.include +endif + +if ENABLE_QT +include Makefile.qt.include +endif + +if ENABLE_QT_TESTS +include Makefile.qttest.include +endif diff --git a/src/Makefile.include b/src/Makefile.include index 2fc6cd7775..d3d3d6385a 100644 --- a/src/Makefile.include +++ b/src/Makefile.include @@ -12,23 +12,18 @@ AM_CPPFLAGS = $(INCLUDES) \ AM_CPPFLAGS += $(LEVELDB_CPPFLAGS) AM_LDFLAGS = $(PTHREAD_CFLAGS) -LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a -LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a -LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a -LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a -LIBBITCOINQT=$(top_builddir)/src/qt/libbitcoinqt.a - -$(LIBBITCOIN): - $(MAKE) -C $(top_builddir)/src $(@F) +LIBBITCOIN_SERVER=libbitcoin_server.a +LIBBITCOIN_WALLET=libbitcoin_wallet.a +LIBBITCOIN_COMMON=libbitcoin_common.a +LIBBITCOIN_CLI=libbitcoin_cli.a +LIBBITCOINQT=qt/libbitcoinqt.a if EMBEDDED_LEVELDB $(LIBLEVELDB) $(LIBMEMENV): $(MAKE) -C $(top_builddir)/src leveldb/$(@F) +$(LIBLEVELDB): $(LIBMEMENV) endif -$(LIBBITCOINQT): - $(MAKE) -C $(top_builddir)/src/qt $(@F) - .mm.o: $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $< diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include new file mode 100644 index 0000000000..dcb3f37f50 --- /dev/null +++ b/src/Makefile.qt.include @@ -0,0 +1,387 @@ +AM_CPPFLAGS += -I$(top_srcdir)/src \ + -I$(top_builddir)/src/qt \ + -I$(top_builddir)/src/qt/forms \ + $(PROTOBUF_CFLAGS) \ + $(QR_CFLAGS) +bin_PROGRAMS += qt/bitcoin-qt +noinst_LIBRARIES += qt/libbitcoinqt.a + +# bitcoin qt core # +QT_TS = \ + qt/locale/bitcoin_ach.ts \ + qt/locale/bitcoin_af_ZA.ts \ + qt/locale/bitcoin_ar.ts \ + qt/locale/bitcoin_be_BY.ts \ + qt/locale/bitcoin_bg.ts \ + qt/locale/bitcoin_bs.ts \ + qt/locale/bitcoin_ca_ES.ts \ + qt/locale/bitcoin_ca.ts \ + qt/locale/bitcoin_ca@valencia.ts \ + qt/locale/bitcoin_cmn.ts \ + qt/locale/bitcoin_cs.ts \ + qt/locale/bitcoin_cy.ts \ + qt/locale/bitcoin_da.ts \ + qt/locale/bitcoin_de.ts \ + qt/locale/bitcoin_el_GR.ts \ + qt/locale/bitcoin_en.ts \ + qt/locale/bitcoin_eo.ts \ + qt/locale/bitcoin_es_CL.ts \ + qt/locale/bitcoin_es_DO.ts \ + qt/locale/bitcoin_es_MX.ts \ + qt/locale/bitcoin_es.ts \ + qt/locale/bitcoin_es_UY.ts \ + qt/locale/bitcoin_et.ts \ + qt/locale/bitcoin_eu_ES.ts \ + qt/locale/bitcoin_fa_IR.ts \ + qt/locale/bitcoin_fa.ts \ + qt/locale/bitcoin_fi.ts \ + qt/locale/bitcoin_fr_CA.ts \ + qt/locale/bitcoin_fr.ts \ + qt/locale/bitcoin_gl.ts \ + qt/locale/bitcoin_gu_IN.ts \ + qt/locale/bitcoin_he.ts \ + qt/locale/bitcoin_hi_IN.ts \ + qt/locale/bitcoin_hr.ts \ + qt/locale/bitcoin_hu.ts \ + qt/locale/bitcoin_id_ID.ts \ + qt/locale/bitcoin_it.ts \ + qt/locale/bitcoin_ja.ts \ + qt/locale/bitcoin_ka.ts \ + qt/locale/bitcoin_kk_KZ.ts \ + qt/locale/bitcoin_ko_KR.ts \ + qt/locale/bitcoin_ky.ts \ + qt/locale/bitcoin_la.ts \ + qt/locale/bitcoin_lt.ts \ + qt/locale/bitcoin_lv_LV.ts \ + qt/locale/bitcoin_mn.ts \ + qt/locale/bitcoin_ms_MY.ts \ + qt/locale/bitcoin_nb.ts \ + qt/locale/bitcoin_nl.ts \ + qt/locale/bitcoin_pam.ts \ + qt/locale/bitcoin_pl.ts \ + qt/locale/bitcoin_pt_BR.ts \ + qt/locale/bitcoin_pt_PT.ts \ + qt/locale/bitcoin_ro_RO.ts \ + qt/locale/bitcoin_ru.ts \ + qt/locale/bitcoin_sah.ts \ + qt/locale/bitcoin_sk.ts \ + qt/locale/bitcoin_sl_SI.ts \ + qt/locale/bitcoin_sq.ts \ + qt/locale/bitcoin_sr.ts \ + qt/locale/bitcoin_sv.ts \ + qt/locale/bitcoin_th_TH.ts \ + qt/locale/bitcoin_tr.ts \ + qt/locale/bitcoin_uk.ts \ + qt/locale/bitcoin_ur_PK.ts \ + qt/locale/bitcoin_uz@Cyrl.ts \ + qt/locale/bitcoin_vi.ts \ + qt/locale/bitcoin_vi_VN.ts \ + qt/locale/bitcoin_zh_CN.ts \ + qt/locale/bitcoin_zh_HK.ts \ + qt/locale/bitcoin_zh_TW.ts + +QT_FORMS_UI = \ + qt/forms/aboutdialog.ui \ + qt/forms/addressbookpage.ui \ + qt/forms/askpassphrasedialog.ui \ + qt/forms/coincontroldialog.ui \ + qt/forms/editaddressdialog.ui \ + qt/forms/helpmessagedialog.ui \ + qt/forms/intro.ui \ + qt/forms/openuridialog.ui \ + qt/forms/optionsdialog.ui \ + qt/forms/overviewpage.ui \ + qt/forms/receivecoinsdialog.ui \ + qt/forms/receiverequestdialog.ui \ + qt/forms/rpcconsole.ui \ + qt/forms/sendcoinsdialog.ui \ + qt/forms/sendcoinsentry.ui \ + qt/forms/signverifymessagedialog.ui \ + qt/forms/transactiondescdialog.ui + +QT_MOC_CPP = \ + qt/moc_addressbookpage.cpp \ + qt/moc_addresstablemodel.cpp \ + qt/moc_askpassphrasedialog.cpp \ + qt/moc_bitcoinaddressvalidator.cpp \ + qt/moc_bitcoinamountfield.cpp \ + qt/moc_bitcoingui.cpp \ + qt/moc_bitcoinunits.cpp \ + qt/moc_clientmodel.cpp \ + qt/moc_coincontroldialog.cpp \ + qt/moc_coincontroltreewidget.cpp \ + qt/moc_csvmodelwriter.cpp \ + qt/moc_editaddressdialog.cpp \ + qt/moc_guiutil.cpp \ + qt/moc_intro.cpp \ + qt/moc_macdockiconhandler.cpp \ + qt/moc_macnotificationhandler.cpp \ + qt/moc_monitoreddatamapper.cpp \ + qt/moc_notificator.cpp \ + qt/moc_openuridialog.cpp \ + qt/moc_optionsdialog.cpp \ + qt/moc_optionsmodel.cpp \ + qt/moc_overviewpage.cpp \ + qt/moc_peertablemodel.cpp \ + qt/moc_paymentserver.cpp \ + qt/moc_qvalidatedlineedit.cpp \ + qt/moc_qvaluecombobox.cpp \ + qt/moc_receivecoinsdialog.cpp \ + qt/moc_receiverequestdialog.cpp \ + qt/moc_recentrequeststablemodel.cpp \ + qt/moc_rpcconsole.cpp \ + qt/moc_sendcoinsdialog.cpp \ + qt/moc_sendcoinsentry.cpp \ + qt/moc_signverifymessagedialog.cpp \ + qt/moc_splashscreen.cpp \ + qt/moc_trafficgraphwidget.cpp \ + qt/moc_transactiondesc.cpp \ + qt/moc_transactiondescdialog.cpp \ + qt/moc_transactionfilterproxy.cpp \ + qt/moc_transactiontablemodel.cpp \ + qt/moc_transactionview.cpp \ + qt/moc_utilitydialog.cpp \ + qt/moc_walletframe.cpp \ + qt/moc_walletmodel.cpp \ + qt/moc_walletview.cpp + +BITCOIN_MM = \ + qt/macdockiconhandler.mm \ + qt/macnotificationhandler.mm + +QT_MOC = \ + qt/bitcoin.moc \ + qt/intro.moc \ + qt/overviewpage.moc \ + qt/rpcconsole.moc + +QT_QRC_CPP = qt/qrc_bitcoin.cpp +QT_QRC = qt/bitcoin.qrc + +PROTOBUF_CC = qt/paymentrequest.pb.cc +PROTOBUF_H = qt/paymentrequest.pb.h +PROTOBUF_PROTO = qt/paymentrequest.proto + +BITCOIN_QT_H = \ + qt/addressbookpage.h \ + qt/addresstablemodel.h \ + qt/askpassphrasedialog.h \ + qt/bitcoinaddressvalidator.h \ + qt/bitcoinamountfield.h \ + qt/bitcoingui.h \ + qt/bitcoinunits.h \ + qt/clientmodel.h \ + qt/coincontroldialog.h \ + qt/coincontroltreewidget.h \ + qt/csvmodelwriter.h \ + qt/editaddressdialog.h \ + qt/guiconstants.h \ + qt/guiutil.h \ + qt/intro.h \ + qt/macdockiconhandler.h \ + qt/macnotificationhandler.h \ + qt/monitoreddatamapper.h \ + qt/notificator.h \ + qt/openuridialog.h \ + qt/optionsdialog.h \ + qt/optionsmodel.h \ + qt/overviewpage.h \ + qt/paymentrequestplus.h \ + qt/paymentserver.h \ + qt/peertablemodel.h \ + qt/qvalidatedlineedit.h \ + qt/qvaluecombobox.h \ + qt/receivecoinsdialog.h \ + qt/receiverequestdialog.h \ + qt/recentrequeststablemodel.h \ + qt/rpcconsole.h \ + qt/sendcoinsdialog.h \ + qt/sendcoinsentry.h \ + qt/signverifymessagedialog.h \ + qt/splashscreen.h \ + qt/trafficgraphwidget.h \ + qt/transactiondesc.h \ + qt/transactiondescdialog.h \ + qt/transactionfilterproxy.h \ + qt/transactionrecord.h \ + qt/transactiontablemodel.h \ + qt/transactionview.h \ + qt/utilitydialog.h \ + qt/walletframe.h \ + qt/walletmodel.h \ + qt/walletmodeltransaction.h \ + qt/walletview.h \ + qt/winshutdownmonitor.h + +RES_ICONS = \ + qt/res/icons/add.png \ + qt/res/icons/address-book.png \ + qt/res/icons/bitcoin.ico \ + qt/res/icons/bitcoin.png \ + qt/res/icons/bitcoin_testnet.ico \ + qt/res/icons/bitcoin_testnet.png \ + qt/res/icons/clock1.png \ + qt/res/icons/clock2.png \ + qt/res/icons/clock3.png \ + qt/res/icons/clock4.png \ + qt/res/icons/clock5.png \ + qt/res/icons/configure.png \ + qt/res/icons/connect0_16.png \ + qt/res/icons/connect1_16.png \ + qt/res/icons/connect2_16.png \ + qt/res/icons/connect3_16.png \ + qt/res/icons/connect4_16.png \ + qt/res/icons/debugwindow.png \ + qt/res/icons/edit.png \ + qt/res/icons/editcopy.png \ + qt/res/icons/editpaste.png \ + qt/res/icons/export.png \ + qt/res/icons/filesave.png \ + qt/res/icons/history.png \ + qt/res/icons/key.png \ + qt/res/icons/lock_closed.png \ + qt/res/icons/lock_open.png \ + qt/res/icons/overview.png \ + qt/res/icons/qrcode.png \ + qt/res/icons/quit.png \ + qt/res/icons/receive.png \ + qt/res/icons/remove.png \ + qt/res/icons/send.png \ + qt/res/icons/synced.png \ + qt/res/icons/toolbar.png \ + qt/res/icons/toolbar_testnet.png \ + qt/res/icons/transaction0.png \ + qt/res/icons/transaction2.png \ + qt/res/icons/transaction_conflicted.png \ + qt/res/icons/tx_inout.png \ + qt/res/icons/tx_input.png \ + qt/res/icons/tx_output.png \ + qt/res/icons/tx_mined.png + +BITCOIN_QT_CPP = \ + qt/bitcoinaddressvalidator.cpp \ + qt/bitcoinamountfield.cpp \ + qt/bitcoingui.cpp \ + qt/bitcoinunits.cpp \ + qt/clientmodel.cpp \ + qt/csvmodelwriter.cpp \ + qt/guiutil.cpp \ + qt/intro.cpp \ + qt/monitoreddatamapper.cpp \ + qt/notificator.cpp \ + qt/optionsdialog.cpp \ + qt/optionsmodel.cpp \ + qt/peertablemodel.cpp \ + qt/qvalidatedlineedit.cpp \ + qt/qvaluecombobox.cpp \ + qt/rpcconsole.cpp \ + qt/splashscreen.cpp \ + qt/trafficgraphwidget.cpp \ + qt/utilitydialog.cpp \ + qt/winshutdownmonitor.cpp + +if ENABLE_WALLET +BITCOIN_QT_CPP += \ + qt/addressbookpage.cpp \ + qt/addresstablemodel.cpp \ + qt/askpassphrasedialog.cpp \ + qt/coincontroldialog.cpp \ + qt/coincontroltreewidget.cpp \ + qt/editaddressdialog.cpp \ + qt/openuridialog.cpp \ + qt/overviewpage.cpp \ + qt/paymentrequestplus.cpp \ + qt/paymentserver.cpp \ + qt/receivecoinsdialog.cpp \ + qt/receiverequestdialog.cpp \ + qt/recentrequeststablemodel.cpp \ + qt/sendcoinsdialog.cpp \ + qt/sendcoinsentry.cpp \ + qt/signverifymessagedialog.cpp \ + qt/transactiondesc.cpp \ + qt/transactiondescdialog.cpp \ + qt/transactionfilterproxy.cpp \ + qt/transactionrecord.cpp \ + qt/transactiontablemodel.cpp \ + qt/transactionview.cpp \ + qt/walletframe.cpp \ + qt/walletmodel.cpp \ + qt/walletmodeltransaction.cpp \ + qt/walletview.cpp +endif + +RES_IMAGES = \ + qt/res/images/about.png \ + qt/res/images/splash.png \ + qt/res/images/splash_testnet.png + +RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png) + +BITCOIN_RC = qt/res/bitcoin-qt-res.rc + +qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ + -I$(top_srcdir)/src/qt/forms $(QT_DBUS_INCLUDES) +qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ + $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) + +nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ + $(PROTOBUF_H) $(QT_QRC_CPP) + +# forms/foo.h -> forms/ui_foo.h +QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h)))) + +# Most files will depend on the forms and moc files as includes. Generate them +# before anything else. +$(QT_MOC): $(QT_FORMS_H) +$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC) + +#Generating these with a half-written protobuf header leads to wacky results. +#This makes sure it's done. +$(QT_MOC): $(PROTOBUF_H) +$(QT_MOC_CPP): $(PROTOBUF_H) + +# bitcoin-qt binary # +qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ + -I$(top_srcdir)/src/qt/forms +qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp +if TARGET_DARWIN + qt_bitcoin_qt_SOURCES += $(BITCOIN_MM) +endif +if TARGET_WINDOWS + qt_bitcoin_qt_SOURCES += $(BITCOIN_RC) +endif +qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER) +if ENABLE_WALLET +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) +endif +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) + +#locale/foo.ts -> locale/foo.qm +QT_QM=$(QT_TS:.ts=.qm) + +.SECONDARY: $(QT_QM) + +qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES) + @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" + @cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py + +translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) + @test -n $(LUPDATE) || echo "lupdate is required for updating translations" + @QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/bitcoin_en.ts + +$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H) + @cd $(abs_srcdir); test -f $(RCC) && QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin -o $(abs_builddir)/$@ $< || \ + echo error: could not build $@ + $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} + $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + +CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno + +CLEANFILES += $(CLEAN_QT) + +bitcoin_qt_clean: FORCE + rm -f $(CLEAN_QT) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) qt/bitcoin-qt$(EXEEXT) $(LIBBITCOINQT) + +bitcoin_qt : qt/bitcoin-qt$(EXEEXT) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include new file mode 100644 index 0000000000..0d08a636e9 --- /dev/null +++ b/src/Makefile.qttest.include @@ -0,0 +1,52 @@ +AM_CPPFLAGS += -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/qt \ + -I$(top_builddir)/src/qt \ + $(PROTOBUF_CFLAGS) \ + $(QR_CFLAGS) +bin_PROGRAMS += qt/test/test_bitcoin-qt +TESTS += qt/test/test_bitcoin-qt + +TEST_QT_MOC_CPP = qt/test/moc_uritests.cpp + +if ENABLE_WALLET +TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp +endif + +TEST_QT_H = \ + qt/test/uritests.h \ + qt/test/paymentrequestdata.h \ + qt/test/paymentservertests.h + +qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES) + +qt_test_test_bitcoin_qt_SOURCES = \ + qt/test/test_main.cpp \ + qt/test/uritests.cpp \ + $(TEST_QT_H) +if ENABLE_WALLET +qt_test_test_bitcoin_qt_SOURCES += \ + qt/test/paymentservertests.cpp +endif + +nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) + +qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) +if ENABLE_WALLET +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) +endif +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \ + $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ + $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) + +CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno + +CLEANFILES += $(CLEAN_BITCOIN_QT_TEST) + +test_bitcoin_qt : qt/test/test_bitcoin-qt$(EXEEXT) + +test_bitcoin_qt_check : qt/test/test_bitcoin-qt$(EXEEXT) FORCE + $(MAKE) check-TESTS TESTS=$^ + +test_bitcoin_qt_clean: FORCE + rm -f $(CLEAN_BITCOIN_QT_TEST) $(qt_test_test_bitcoin_qt_OBJECTS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include new file mode 100644 index 0000000000..4a70b0f9e9 --- /dev/null +++ b/src/Makefile.test.include @@ -0,0 +1,87 @@ +AM_CPPFLAGS += -I$(top_builddir)/src/test/ + +TESTS += test/test_bitcoin +bin_PROGRAMS += test/test_bitcoin +TEST_SRCDIR = test +TEST_BINARY=test/test_bitcoin$(EXEEXT) + +JSON_TEST_FILES = \ + test/data/script_valid.json \ + test/data/base58_keys_valid.json \ + test/data/sig_canonical.json \ + test/data/sig_noncanonical.json \ + test/data/base58_encode_decode.json \ + test/data/base58_keys_invalid.json \ + test/data/script_invalid.json \ + test/data/tx_invalid.json \ + test/data/tx_valid.json \ + test/data/sighash.json + +RAW_TEST_FILES = test/data/alertTests.raw + +GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) + +BITCOIN_TESTS =\ + test/bignum.h \ + test/alert_tests.cpp \ + test/allocator_tests.cpp \ + test/base32_tests.cpp \ + test/base58_tests.cpp \ + test/base64_tests.cpp \ + test/bloom_tests.cpp \ + test/canonical_tests.cpp \ + test/checkblock_tests.cpp \ + test/Checkpoints_tests.cpp \ + test/compress_tests.cpp \ + test/DoS_tests.cpp \ + test/getarg_tests.cpp \ + test/key_tests.cpp \ + test/main_tests.cpp \ + test/miner_tests.cpp \ + test/mruset_tests.cpp \ + test/multisig_tests.cpp \ + test/netbase_tests.cpp \ + test/pmt_tests.cpp \ + test/rpc_tests.cpp \ + test/script_P2SH_tests.cpp \ + test/script_tests.cpp \ + test/serialize_tests.cpp \ + test/sigopcount_tests.cpp \ + test/test_bitcoin.cpp \ + test/transaction_tests.cpp \ + test/uint256_tests.cpp \ + test/util_tests.cpp \ + test/scriptnum_tests.cpp \ + test/sighash_tests.cpp + +if ENABLE_WALLET +BITCOIN_TESTS += \ + test/accounting_tests.cpp \ + test/wallet_tests.cpp \ + test/rpc_wallet_tests.cpp +endif + +test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) +test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS) +test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ + $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) +if ENABLE_WALLET +test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) +endif +test_test_bitcoin_LDADD += $(BDB_LIBS) + +nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) + +$(BITCOIN_TESTS): $(GENERATED_TEST_FILES) + +CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) + +CLEANFILES += $(CLEAN_BITCOIN_TEST) + +bitcoin_test: $(TEST_BINARY) + +bitcoin_test_check: $(TEST_BINARY) FORCE + $(MAKE) check-TESTS TESTS=$^ + +bitcoin_test_clean : FORCE + rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) From be4e9aeb148420317109d173d7fb3bc56b37f434 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 28 May 2014 13:40:35 -0400 Subject: [PATCH 135/336] build: delete old Makefile.am's --- src/qt/Makefile.am | 382 ---------------------------------------- src/qt/test/Makefile.am | 46 ----- src/test/Makefile.am | 77 -------- 3 files changed, 505 deletions(-) delete mode 100644 src/qt/Makefile.am delete mode 100644 src/qt/test/Makefile.am delete mode 100644 src/test/Makefile.am diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am deleted file mode 100644 index d527f790ef..0000000000 --- a/src/qt/Makefile.am +++ /dev/null @@ -1,382 +0,0 @@ -include $(top_srcdir)/src/Makefile.include - -AM_CPPFLAGS += -I$(top_srcdir)/src \ - -I$(top_builddir)/src/qt \ - -I$(top_builddir)/src/qt/forms \ - $(PROTOBUF_CFLAGS) \ - $(QR_CFLAGS) -bin_PROGRAMS = bitcoin-qt -noinst_LIBRARIES = libbitcoinqt.a -SUBDIRS = . $(BUILD_TEST_QT) -DIST_SUBDIRS = . test - -# bitcoin qt core # -QT_TS = \ - locale/bitcoin_ach.ts \ - locale/bitcoin_af_ZA.ts \ - locale/bitcoin_ar.ts \ - locale/bitcoin_be_BY.ts \ - locale/bitcoin_bg.ts \ - locale/bitcoin_bs.ts \ - locale/bitcoin_ca_ES.ts \ - locale/bitcoin_ca.ts \ - locale/bitcoin_ca@valencia.ts \ - locale/bitcoin_cmn.ts \ - locale/bitcoin_cs.ts \ - locale/bitcoin_cy.ts \ - locale/bitcoin_da.ts \ - locale/bitcoin_de.ts \ - locale/bitcoin_el_GR.ts \ - locale/bitcoin_en.ts \ - locale/bitcoin_eo.ts \ - locale/bitcoin_es_CL.ts \ - locale/bitcoin_es_DO.ts \ - locale/bitcoin_es_MX.ts \ - locale/bitcoin_es.ts \ - locale/bitcoin_es_UY.ts \ - locale/bitcoin_et.ts \ - locale/bitcoin_eu_ES.ts \ - locale/bitcoin_fa_IR.ts \ - locale/bitcoin_fa.ts \ - locale/bitcoin_fi.ts \ - locale/bitcoin_fr_CA.ts \ - locale/bitcoin_fr.ts \ - locale/bitcoin_gl.ts \ - locale/bitcoin_gu_IN.ts \ - locale/bitcoin_he.ts \ - locale/bitcoin_hi_IN.ts \ - locale/bitcoin_hr.ts \ - locale/bitcoin_hu.ts \ - locale/bitcoin_id_ID.ts \ - locale/bitcoin_it.ts \ - locale/bitcoin_ja.ts \ - locale/bitcoin_ka.ts \ - locale/bitcoin_kk_KZ.ts \ - locale/bitcoin_ko_KR.ts \ - locale/bitcoin_ky.ts \ - locale/bitcoin_la.ts \ - locale/bitcoin_lt.ts \ - locale/bitcoin_lv_LV.ts \ - locale/bitcoin_mn.ts \ - locale/bitcoin_ms_MY.ts \ - locale/bitcoin_nb.ts \ - locale/bitcoin_nl.ts \ - locale/bitcoin_pam.ts \ - locale/bitcoin_pl.ts \ - locale/bitcoin_pt_BR.ts \ - locale/bitcoin_pt_PT.ts \ - locale/bitcoin_ro_RO.ts \ - locale/bitcoin_ru.ts \ - locale/bitcoin_sah.ts \ - locale/bitcoin_sk.ts \ - locale/bitcoin_sl_SI.ts \ - locale/bitcoin_sq.ts \ - locale/bitcoin_sr.ts \ - locale/bitcoin_sv.ts \ - locale/bitcoin_th_TH.ts \ - locale/bitcoin_tr.ts \ - locale/bitcoin_uk.ts \ - locale/bitcoin_ur_PK.ts \ - locale/bitcoin_uz@Cyrl.ts \ - locale/bitcoin_vi.ts \ - locale/bitcoin_vi_VN.ts \ - locale/bitcoin_zh_CN.ts \ - locale/bitcoin_zh_HK.ts \ - locale/bitcoin_zh_TW.ts - -QT_FORMS_UI = \ - forms/aboutdialog.ui \ - forms/addressbookpage.ui \ - forms/askpassphrasedialog.ui \ - forms/coincontroldialog.ui \ - forms/editaddressdialog.ui \ - forms/helpmessagedialog.ui \ - forms/intro.ui \ - forms/openuridialog.ui \ - forms/optionsdialog.ui \ - forms/overviewpage.ui \ - forms/receivecoinsdialog.ui \ - forms/receiverequestdialog.ui \ - forms/rpcconsole.ui \ - forms/sendcoinsdialog.ui \ - forms/sendcoinsentry.ui \ - forms/signverifymessagedialog.ui \ - forms/transactiondescdialog.ui - -QT_MOC_CPP = \ - moc_addressbookpage.cpp \ - moc_addresstablemodel.cpp \ - moc_askpassphrasedialog.cpp \ - moc_bitcoinaddressvalidator.cpp \ - moc_bitcoinamountfield.cpp \ - moc_bitcoingui.cpp \ - moc_bitcoinunits.cpp \ - moc_clientmodel.cpp \ - moc_coincontroldialog.cpp \ - moc_coincontroltreewidget.cpp \ - moc_csvmodelwriter.cpp \ - moc_editaddressdialog.cpp \ - moc_guiutil.cpp \ - moc_intro.cpp \ - moc_macdockiconhandler.cpp \ - moc_macnotificationhandler.cpp \ - moc_monitoreddatamapper.cpp \ - moc_notificator.cpp \ - moc_openuridialog.cpp \ - moc_optionsdialog.cpp \ - moc_optionsmodel.cpp \ - moc_overviewpage.cpp \ - moc_peertablemodel.cpp \ - moc_paymentserver.cpp \ - moc_qvalidatedlineedit.cpp \ - moc_qvaluecombobox.cpp \ - moc_receivecoinsdialog.cpp \ - moc_receiverequestdialog.cpp \ - moc_recentrequeststablemodel.cpp \ - moc_rpcconsole.cpp \ - moc_sendcoinsdialog.cpp \ - moc_sendcoinsentry.cpp \ - moc_signverifymessagedialog.cpp \ - moc_splashscreen.cpp \ - moc_trafficgraphwidget.cpp \ - moc_transactiondesc.cpp \ - moc_transactiondescdialog.cpp \ - moc_transactionfilterproxy.cpp \ - moc_transactiontablemodel.cpp \ - moc_transactionview.cpp \ - moc_utilitydialog.cpp \ - moc_walletframe.cpp \ - moc_walletmodel.cpp \ - moc_walletview.cpp - -BITCOIN_MM = \ - macdockiconhandler.mm \ - macnotificationhandler.mm - -QT_MOC = \ - bitcoin.moc \ - intro.moc \ - overviewpage.moc \ - rpcconsole.moc - -QT_QRC_CPP = qrc_bitcoin.cpp -QT_QRC = bitcoin.qrc - -PROTOBUF_CC = paymentrequest.pb.cc -PROTOBUF_H = paymentrequest.pb.h -PROTOBUF_PROTO = paymentrequest.proto - -BITCOIN_QT_H = \ - addressbookpage.h \ - addresstablemodel.h \ - askpassphrasedialog.h \ - bitcoinaddressvalidator.h \ - bitcoinamountfield.h \ - bitcoingui.h \ - bitcoinunits.h \ - clientmodel.h \ - coincontroldialog.h \ - coincontroltreewidget.h \ - csvmodelwriter.h \ - editaddressdialog.h \ - guiconstants.h \ - guiutil.h \ - intro.h \ - macdockiconhandler.h \ - macnotificationhandler.h \ - monitoreddatamapper.h \ - notificator.h \ - openuridialog.h \ - optionsdialog.h \ - optionsmodel.h \ - overviewpage.h \ - paymentrequestplus.h \ - paymentserver.h \ - peertablemodel.h \ - qvalidatedlineedit.h \ - qvaluecombobox.h \ - receivecoinsdialog.h \ - receiverequestdialog.h \ - recentrequeststablemodel.h \ - rpcconsole.h \ - sendcoinsdialog.h \ - sendcoinsentry.h \ - signverifymessagedialog.h \ - splashscreen.h \ - trafficgraphwidget.h \ - transactiondesc.h \ - transactiondescdialog.h \ - transactionfilterproxy.h \ - transactionrecord.h \ - transactiontablemodel.h \ - transactionview.h \ - utilitydialog.h \ - walletframe.h \ - walletmodel.h \ - walletmodeltransaction.h \ - walletview.h \ - winshutdownmonitor.h - -RES_ICONS = \ - res/icons/add.png \ - res/icons/address-book.png \ - res/icons/bitcoin.ico \ - res/icons/bitcoin.png \ - res/icons/bitcoin_testnet.ico \ - res/icons/bitcoin_testnet.png \ - res/icons/clock1.png \ - res/icons/clock2.png \ - res/icons/clock3.png \ - res/icons/clock4.png \ - res/icons/clock5.png \ - res/icons/configure.png \ - res/icons/connect0_16.png \ - res/icons/connect1_16.png \ - res/icons/connect2_16.png \ - res/icons/connect3_16.png \ - res/icons/connect4_16.png \ - res/icons/debugwindow.png \ - res/icons/edit.png \ - res/icons/editcopy.png \ - res/icons/editpaste.png \ - res/icons/export.png \ - res/icons/filesave.png \ - res/icons/history.png \ - res/icons/key.png \ - res/icons/lock_closed.png \ - res/icons/lock_open.png \ - res/icons/overview.png \ - res/icons/qrcode.png \ - res/icons/quit.png \ - res/icons/receive.png \ - res/icons/remove.png \ - res/icons/send.png \ - res/icons/synced.png \ - res/icons/toolbar.png \ - res/icons/toolbar_testnet.png \ - res/icons/transaction0.png \ - res/icons/transaction2.png \ - res/icons/transaction_conflicted.png \ - res/icons/tx_inout.png \ - res/icons/tx_input.png \ - res/icons/tx_output.png \ - res/icons/tx_mined.png - -BITCOIN_QT_CPP = \ - bitcoin.cpp \ - bitcoinaddressvalidator.cpp \ - bitcoinamountfield.cpp \ - bitcoingui.cpp \ - bitcoinunits.cpp \ - clientmodel.cpp \ - csvmodelwriter.cpp \ - guiutil.cpp \ - intro.cpp \ - monitoreddatamapper.cpp \ - notificator.cpp \ - optionsdialog.cpp \ - optionsmodel.cpp \ - peertablemodel.cpp \ - qvalidatedlineedit.cpp \ - qvaluecombobox.cpp \ - rpcconsole.cpp \ - splashscreen.cpp \ - trafficgraphwidget.cpp \ - utilitydialog.cpp \ - winshutdownmonitor.cpp - -if ENABLE_WALLET -BITCOIN_QT_CPP += \ - addressbookpage.cpp \ - addresstablemodel.cpp \ - askpassphrasedialog.cpp \ - coincontroldialog.cpp \ - coincontroltreewidget.cpp \ - editaddressdialog.cpp \ - openuridialog.cpp \ - overviewpage.cpp \ - paymentrequestplus.cpp \ - paymentserver.cpp \ - receivecoinsdialog.cpp \ - receiverequestdialog.cpp \ - recentrequeststablemodel.cpp \ - sendcoinsdialog.cpp \ - sendcoinsentry.cpp \ - signverifymessagedialog.cpp \ - transactiondesc.cpp \ - transactiondescdialog.cpp \ - transactionfilterproxy.cpp \ - transactionrecord.cpp \ - transactiontablemodel.cpp \ - transactionview.cpp \ - walletframe.cpp \ - walletmodel.cpp \ - walletmodeltransaction.cpp \ - walletview.cpp -endif - -RES_IMAGES = \ - res/images/about.png \ - res/images/splash.png \ - res/images/splash_testnet.png - -RES_MOVIES = $(wildcard res/movies/spinner-*.png) - -BITCOIN_RC = res/bitcoin-qt-res.rc - -libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(top_srcdir)/src/qt/forms $(QT_DBUS_INCLUDES) -libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ - $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) - -nodist_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ - $(PROTOBUF_H) $(QT_QRC_CPP) - -BUILT_SOURCES = $(nodist_libbitcoinqt_a_SOURCES) - -#Generating these with a half-written protobuf header leads to wacky results. -#This makes sure it's done. -$(QT_MOC): $(PROTOBUF_H) -$(QT_MOC_CPP): $(PROTOBUF_H) - -# bitcoin-qt binary # -bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(top_srcdir)/src/qt/forms -bitcoin_qt_SOURCES = bitcoin.cpp -if TARGET_DARWIN - bitcoin_qt_SOURCES += $(BITCOIN_MM) -endif -if TARGET_WINDOWS - bitcoin_qt_SOURCES += $(BITCOIN_RC) -endif -bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER) -if ENABLE_WALLET -bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) -endif -bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) -bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) - -# forms/foo.h -> forms/ui_foo.h -QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h)))) - -#locale/foo.ts -> locale/foo.qm -QT_QM=$(QT_TS:.ts=.qm) - -.PHONY: FORCE -.SECONDARY: $(QT_QM) - -bitcoinstrings.cpp: FORCE - $(MAKE) -C $(top_srcdir)/src qt/bitcoinstrings.cpp - -translate: bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) - @test -n $(LUPDATE) || echo "lupdate is required for updating translations" - @QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts locale/bitcoin_en.ts - -$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H) - @cd $(abs_srcdir); test -f $(RCC) && QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin -o $(abs_builddir)/$@ $< || \ - echo error: could not build $@ - $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} - -CLEANFILES = $(BUILT_SOURCES) $(QT_QM) $(QT_FORMS_H) *.gcda *.gcno diff --git a/src/qt/test/Makefile.am b/src/qt/test/Makefile.am deleted file mode 100644 index 2461b5ff4d..0000000000 --- a/src/qt/test/Makefile.am +++ /dev/null @@ -1,46 +0,0 @@ -include $(top_srcdir)/src/Makefile.include - -AM_CPPFLAGS += -I$(top_srcdir)/src \ - -I$(top_srcdir)/src/qt \ - -I$(top_builddir)/src/qt \ - $(PROTOBUF_CFLAGS) \ - $(QR_CFLAGS) -bin_PROGRAMS = test_bitcoin-qt -TESTS = test_bitcoin-qt - -TEST_QT_MOC_CPP = moc_uritests.cpp - -if ENABLE_WALLET -TEST_QT_MOC_CPP += moc_paymentservertests.cpp -endif - -TEST_QT_H = \ - uritests.h \ - paymentrequestdata.h \ - paymentservertests.h - -BUILT_SOURCES = $(TEST_QT_MOC_CPP) - -test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES) - -test_bitcoin_qt_SOURCES = \ - test_main.cpp \ - uritests.cpp \ - $(TEST_QT_H) -if ENABLE_WALLET -test_bitcoin_qt_SOURCES += \ - paymentservertests.cpp -endif - -nodist_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) - -test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) -if ENABLE_WALLET -test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) -endif -test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \ - $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ - $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) -test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) - -CLEANFILES = $(BUILT_SOURCES) *.gcda *.gcno diff --git a/src/test/Makefile.am b/src/test/Makefile.am deleted file mode 100644 index cde3a31e2f..0000000000 --- a/src/test/Makefile.am +++ /dev/null @@ -1,77 +0,0 @@ -include $(top_srcdir)/src/Makefile.include - -AM_CPPFLAGS += -I$(top_srcdir)/src - -bin_PROGRAMS = test_bitcoin - -TESTS = test_bitcoin - -JSON_TEST_FILES = \ - data/script_valid.json \ - data/base58_keys_valid.json \ - data/sig_canonical.json \ - data/sig_noncanonical.json \ - data/base58_encode_decode.json \ - data/base58_keys_invalid.json \ - data/script_invalid.json \ - data/tx_invalid.json \ - data/tx_valid.json \ - data/sighash.json - -RAW_TEST_FILES = data/alertTests.raw - -BUILT_SOURCES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) - -# test_bitcoin binary # -test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS) -test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) -if ENABLE_WALLET -test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) -endif -test_bitcoin_LDADD += $(BDB_LIBS) - -test_bitcoin_SOURCES = \ - bignum.h \ - alert_tests.cpp \ - allocator_tests.cpp \ - base32_tests.cpp \ - base58_tests.cpp \ - base64_tests.cpp \ - bloom_tests.cpp \ - canonical_tests.cpp \ - checkblock_tests.cpp \ - Checkpoints_tests.cpp \ - compress_tests.cpp \ - DoS_tests.cpp \ - getarg_tests.cpp \ - key_tests.cpp \ - main_tests.cpp \ - miner_tests.cpp \ - mruset_tests.cpp \ - multisig_tests.cpp \ - netbase_tests.cpp \ - pmt_tests.cpp \ - rpc_tests.cpp \ - script_P2SH_tests.cpp \ - script_tests.cpp \ - serialize_tests.cpp \ - sigopcount_tests.cpp \ - test_bitcoin.cpp \ - transaction_tests.cpp \ - uint256_tests.cpp \ - util_tests.cpp \ - scriptnum_tests.cpp \ - sighash_tests.cpp \ - $(JSON_TEST_FILES) $(RAW_TEST_FILES) - -if ENABLE_WALLET -test_bitcoin_SOURCES += \ - accounting_tests.cpp \ - wallet_tests.cpp \ - rpc_wallet_tests.cpp -endif - -nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES) - -CLEANFILES = *.gcda *.gcno $(BUILT_SOURCES) From 8b09ef7b6370800a1a9fd6f067abf1aaab5d6cfa Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 28 May 2014 13:41:35 -0400 Subject: [PATCH 136/336] build: add stub makefiles for easier subdir builds --- src/qt/Makefile | 9 +++++++++ src/qt/test/Makefile | 6 ++++++ src/test/Makefile | 6 ++++++ 3 files changed, 21 insertions(+) create mode 100644 src/qt/Makefile create mode 100644 src/qt/test/Makefile create mode 100644 src/test/Makefile diff --git a/src/qt/Makefile b/src/qt/Makefile new file mode 100644 index 0000000000..b9dcf0c599 --- /dev/null +++ b/src/qt/Makefile @@ -0,0 +1,9 @@ +.PHONY: FORCE +all: FORCE + $(MAKE) -C .. bitcoin_qt test_bitcoin_qt +clean: FORCE + $(MAKE) -C .. bitcoin_qt_clean test_bitcoin_qt_clean +check: FORCE + $(MAKE) -C .. test_bitcoin_qt_check +bitcoin-qt bitcoin-qt.exe: FORCE + $(MAKE) -C .. bitcoin_qt diff --git a/src/qt/test/Makefile b/src/qt/test/Makefile new file mode 100644 index 0000000000..a02f86b62a --- /dev/null +++ b/src/qt/test/Makefile @@ -0,0 +1,6 @@ +all: + $(MAKE) -C ../../ test_bitcoin_qt +clean: + $(MAKE) -C ../../ test_bitcoin_qt_clean +check: + $(MAKE) -C ../../ test_bitcoin_qt_check diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 0000000000..87bf73fec9 --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,6 @@ +all: + $(MAKE) -C .. bitcoin_test +clean: + $(MAKE) -C .. bitcoin_test_clean +check: + $(MAKE) -C .. bitcoin_test_check From 6b9f0d5554b75fcc24cbce10e16872df3e103226 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 4 Jun 2014 17:13:03 -0400 Subject: [PATCH 137/336] build: nuke Makefile.include from orbit Rules and targets no longer need to be shared between subdirectories, so this is no longer needed. --- src/Makefile.am | 48 ++++++++++++++++++++----- src/Makefile.include | 74 --------------------------------------- src/Makefile.qt.include | 21 +++++++++++ src/Makefile.test.include | 16 +++++++++ 4 files changed, 76 insertions(+), 83 deletions(-) delete mode 100644 src/Makefile.include diff --git a/src/Makefile.am b/src/Makefile.am index e7d121b4d6..b3e713b9ad 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,27 @@ -include Makefile.include +AM_CPPFLAGS = $(INCLUDES) \ + -I$(top_builddir)/src/obj \ + $(BDB_CPPFLAGS) \ + $(BOOST_CPPFLAGS) $(BOOST_INCLUDES) +AM_CPPFLAGS += $(LEVELDB_CPPFLAGS) +AM_LDFLAGS = $(PTHREAD_CFLAGS) AM_CPPFLAGS += -I$(builddir) +if EMBEDDED_LEVELDB +LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/include +LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv +LIBLEVELDB += $(top_builddir)/src/leveldb/libleveldb.a +LIBMEMENV += $(top_builddir)/src/leveldb/libmemenv.a + +# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race +$(LIBLEVELDB): $(LIBMEMENV) + +$(LIBLEVELDB) $(LIBMEMENV): + @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ + CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ + OPT="$(CXXFLAGS) $(CPPFLAGS)" +endif + noinst_LIBRARIES = \ libbitcoin_server.a \ libbitcoin_common.a \ @@ -179,14 +199,6 @@ if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif -# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race -leveldb/libleveldb.a: leveldb/libmemenv.a - -leveldb/%.a: - @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ - CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ - OPT="$(CXXFLAGS) $(CPPFLAGS)" - CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h @@ -197,6 +209,24 @@ clean-local: -$(MAKE) -C leveldb clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno +.rc.o: + @test -f $(WINDRES) && $(WINDRES) -i $< -o $@ || \ + echo error: could not build $@ + +.mm.o: + $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $< + +%.pb.cc %.pb.h: %.proto + test -f $(PROTOC) && $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} - $(SED) -e '/^\*\*.*by:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} - -%.moc: %.cpp - QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< - $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} - -moc_%.cpp: %.h - QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< - $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} - -%.qm: %.ts - @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D) - @test -f $(LRELEASE) && QT_SELECT=$(QT_SELECT) $(LRELEASE) $(abs_srcdir)/$< -qm $(abs_builddir)/$@ || \ - echo error: could not build $(abs_builddir)/$@ - -%.pb.cc %.pb.h: %.proto - test -f $(PROTOC) && $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( $@ - @echo "static unsigned const char $(*F)[] = {" >> $@ - @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@ - @echo "};};" >> $@ - @echo "Generated $@" - -%.raw.h: %.raw - @$(MKDIR_P) $(@D) - @echo "namespace alert_tests{" > $@ - @echo "static unsigned const char $(*F)[] = {" >> $@ - @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@ - @echo "};};" >> $@ - @echo "Generated $@" diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index dcb3f37f50..0cef2d2e6f 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -385,3 +385,24 @@ bitcoin_qt_clean: FORCE rm -f $(CLEAN_QT) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) qt/bitcoin-qt$(EXEEXT) $(LIBBITCOINQT) bitcoin_qt : qt/bitcoin-qt$(EXEEXT) + +ui_%.h: %.ui + @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D) + @test -f $(UIC) && QT_SELECT=$(QT_SELECT) $(UIC) -o $(abs_builddir)/$@ $(abs_srcdir)/$< || echo error: could not build $(abs_builddir)/$@ + $(SED) -e '/^\*\*.*Created:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} + $(SED) -e '/^\*\*.*by:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} + +%.moc: %.cpp + QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< + $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} + $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + +moc_%.cpp: %.h + QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< + $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} + $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + +%.qm: %.ts + @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D) + @test -f $(LRELEASE) && QT_SELECT=$(QT_SELECT) $(LRELEASE) $(abs_srcdir)/$< -qm $(abs_builddir)/$@ || \ + echo error: could not build $(abs_builddir)/$@ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 4a70b0f9e9..14288ee218 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -85,3 +85,19 @@ bitcoin_test_check: $(TEST_BINARY) FORCE bitcoin_test_clean : FORCE rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) + +%.json.h: %.json + @$(MKDIR_P) $(@D) + @echo "namespace json_tests{" > $@ + @echo "static unsigned const char $(*F)[] = {" >> $@ + @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@ + @echo "};};" >> $@ + @echo "Generated $@" + +%.raw.h: %.raw + @$(MKDIR_P) $(@D) + @echo "namespace alert_tests{" > $@ + @echo "static unsigned const char $(*F)[] = {" >> $@ + @$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@ + @echo "};};" >> $@ + @echo "Generated $@" From 70c71c50ce552c0358679653c04d7cc72a40222c Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 5 Jun 2014 14:17:50 -0400 Subject: [PATCH 138/336] build: Tidy up file generation output - Some file generation was still noisy, silence it. - AM_V_GEN is used rather than @ so that 'make V=1' works as intended - Cut down on file copies and moves when using sed, use pipes instead - Avoid the use of top_ and abs_ dirs where possible --- src/Makefile.am | 10 +++++----- src/Makefile.qt.include | 34 +++++++++++++++------------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index b3e713b9ad..ce12ddcdbd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -210,16 +210,16 @@ clean-local: rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno .rc.o: - @test -f $(WINDRES) && $(WINDRES) -i $< -o $@ || \ - echo error: could not build $@ + @test -f $(WINDRES) + $(AM_V_GEN) $(WINDRES) -i $< -o $@ .mm.o: - $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(CXXFLAGS) -c -o $@ $< %.pb.cc %.pb.h: %.proto - test -f $(PROTOC) && $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + @test -f $(RCC) + $(AM_V_GEN) cd $(srcdir); QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ + $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $(abs_builddir)/$@ CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno @@ -387,22 +386,19 @@ bitcoin_qt_clean: FORCE bitcoin_qt : qt/bitcoin-qt$(EXEEXT) ui_%.h: %.ui - @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D) - @test -f $(UIC) && QT_SELECT=$(QT_SELECT) $(UIC) -o $(abs_builddir)/$@ $(abs_srcdir)/$< || echo error: could not build $(abs_builddir)/$@ - $(SED) -e '/^\*\*.*Created:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} - $(SED) -e '/^\*\*.*by:/d' $(abs_builddir)/$@ > $(abs_builddir)/$@.n && mv $(abs_builddir)/$@{.n,} + @test -f $(UIC) + @$(MKDIR_P) $(@D) + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false) %.moc: %.cpp - QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< - $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \ + $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ moc_%.cpp: %.h - QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) -o $@ $< - $(SED) -e '/^\*\*.*Created:/d' $@ > $@.n && mv $@{.n,} - $(SED) -e '/^\*\*.*by:/d' $@ > $@.n && mv $@{.n,} + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \ + $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ %.qm: %.ts - @test -d $(abs_builddir)/$(@D) || $(MKDIR_P) $(abs_builddir)/$(@D) - @test -f $(LRELEASE) && QT_SELECT=$(QT_SELECT) $(LRELEASE) $(abs_srcdir)/$< -qm $(abs_builddir)/$@ || \ - echo error: could not build $(abs_builddir)/$@ + @test -f $(LRELEASE) + @$(MKDIR_P) $(@D) + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LRELEASE) -silent $< -qm $@ From 56c157d5e087e3976ae05cad2dc08a1fcd9a2400 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 5 Jun 2014 14:22:54 -0400 Subject: [PATCH 139/336] build: avoid the use of top_ and abs_ dir paths Using them has the side effect of confusing the dependency-tracking logic. --- src/Makefile.am | 14 +++++++------- src/Makefile.qt.include | 10 +++++----- src/Makefile.qttest.include | 6 +++--- src/Makefile.test.include | 2 +- src/m4/bitcoin_qt.m4 | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ce12ddcdbd..cb1c88883b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = $(INCLUDES) \ - -I$(top_builddir)/src/obj \ + -I$(builddir)/obj \ $(BDB_CPPFLAGS) \ $(BOOST_CPPFLAGS) $(BOOST_INCLUDES) AM_CPPFLAGS += $(LEVELDB_CPPFLAGS) @@ -8,10 +8,10 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS) AM_CPPFLAGS += -I$(builddir) if EMBEDDED_LEVELDB -LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/include -LEVELDB_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv -LIBLEVELDB += $(top_builddir)/src/leveldb/libleveldb.a -LIBMEMENV += $(top_builddir)/src/leveldb/libmemenv.a +LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include +LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv +LIBLEVELDB += $(builddir)/leveldb/libleveldb.a +LIBMEMENV += $(builddir)/leveldb/libmemenv.a # NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race $(LIBLEVELDB): $(LIBMEMENV) @@ -101,7 +101,7 @@ JSON_H = \ json/json_spirit_writer_template.h obj/build.h: FORCE - @$(MKDIR_P) $(abs_top_builddir)/src/obj + @$(MKDIR_P) $(builddir)/obj @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ $(abs_top_srcdir) version.o: obj/build.h @@ -164,7 +164,7 @@ libbitcoin_cli_a_SOURCES = \ rpcclient.cpp \ $(BITCOIN_CORE_H) -nodist_libbitcoin_common_a_SOURCES = $(top_srcdir)/src/obj/build.h +nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index a25699e392..f434118abb 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -1,6 +1,6 @@ -AM_CPPFLAGS += -I$(top_srcdir)/src \ - -I$(top_builddir)/src/qt \ - -I$(top_builddir)/src/qt/forms \ +AM_CPPFLAGS += -I$(srcdir) \ + -I$(builddir)/qt \ + -I$(builddir)/qt/forms \ $(PROTOBUF_CFLAGS) \ $(QR_CFLAGS) bin_PROGRAMS += qt/bitcoin-qt @@ -320,7 +320,7 @@ RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(top_srcdir)/src/qt/forms $(QT_DBUS_INCLUDES) + -I$(srcdir)/qt/forms $(QT_DBUS_INCLUDES) qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) @@ -342,7 +342,7 @@ $(QT_MOC_CPP): $(PROTOBUF_H) # bitcoin-qt binary # qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(top_srcdir)/src/qt/forms + -I$(srcdir)/qt/forms qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp if TARGET_DARWIN qt_bitcoin_qt_SOURCES += $(BITCOIN_MM) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 0d08a636e9..09e61cf57c 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,6 +1,6 @@ -AM_CPPFLAGS += -I$(top_srcdir)/src \ - -I$(top_srcdir)/src/qt \ - -I$(top_builddir)/src/qt \ +AM_CPPFLAGS += -I$(srcdir) \ + -I$(srcdir)/qt \ + -I$(builddir)/qt \ $(PROTOBUF_CFLAGS) \ $(QR_CFLAGS) bin_PROGRAMS += qt/test/test_bitcoin-qt diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 14288ee218..1e4bd4ca8c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,4 +1,4 @@ -AM_CPPFLAGS += -I$(top_builddir)/src/test/ +AM_CPPFLAGS += -I$(builddir)/test/ TESTS += test/test_bitcoin bin_PROGRAMS += test/test_bitcoin diff --git a/src/m4/bitcoin_qt.m4 b/src/m4/bitcoin_qt.m4 index e71ecd7172..244b03a5c2 100644 --- a/src/m4/bitcoin_qt.m4 +++ b/src/m4/bitcoin_qt.m4 @@ -100,7 +100,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ BITCOIN_QT_PATH_PROGS([LRELEASE], [lrelease-qt${bitcoin_qt_got_major_vers} lrelease${bitcoin_qt_got_major_vers} lrelease], $qt_bin_path) BITCOIN_QT_PATH_PROGS([LUPDATE], [lupdate-qt${bitcoin_qt_got_major_vers} lupdate${bitcoin_qt_got_major_vers} lupdate],$qt_bin_path, yes) - MOC_DEFS='-DHAVE_CONFIG_H -I$(top_srcdir)/src' + MOC_DEFS='-DHAVE_CONFIG_H -I$(srcdir)' case $host in *darwin*) BITCOIN_QT_CHECK([ From f4d81129f0858685c33e79f74084f2931b8c21b4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 5 Jun 2014 15:24:48 -0400 Subject: [PATCH 140/336] build: quit abusing AM_CPPFLAGS Now that the build is non-recursive, adding to AM_CPPFLAGS means adding to _all_ cppflags. Logical groups of includes have been added instead, and are used individually by various targets. --- src/Makefile.am | 16 +++++++++------- src/Makefile.qt.include | 18 +++++++++--------- src/Makefile.qttest.include | 8 ++------ src/Makefile.test.include | 4 +--- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index cb1c88883b..58a50adec6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,6 @@ -AM_CPPFLAGS = $(INCLUDES) \ - -I$(builddir)/obj \ - $(BDB_CPPFLAGS) \ - $(BOOST_CPPFLAGS) $(BOOST_INCLUDES) -AM_CPPFLAGS += $(LEVELDB_CPPFLAGS) +AM_CPPFLAGS = $(INCLUDES) AM_LDFLAGS = $(PTHREAD_CFLAGS) -AM_CPPFLAGS += -I$(builddir) if EMBEDDED_LEVELDB LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include @@ -22,11 +17,14 @@ $(LIBLEVELDB) $(LIBMEMENV): OPT="$(CXXFLAGS) $(CPPFLAGS)" endif +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) + noinst_LIBRARIES = \ libbitcoin_server.a \ libbitcoin_common.a \ libbitcoin_cli.a if ENABLE_WALLET +BITCOIN_INCLUDES += $(BDB_CPPFLAGS) noinst_LIBRARIES += libbitcoin_wallet.a endif @@ -106,6 +104,7 @@ obj/build.h: FORCE $(abs_top_srcdir) version.o: obj/build.h +libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_server_a_SOURCES = \ addrman.cpp \ alert.cpp \ @@ -130,6 +129,7 @@ libbitcoin_server_a_SOURCES = \ $(JSON_H) \ $(BITCOIN_CORE_H) +libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_wallet_a_SOURCES = \ db.cpp \ crypter.cpp \ @@ -139,6 +139,7 @@ libbitcoin_wallet_a_SOURCES = \ walletdb.cpp \ $(BITCOIN_CORE_H) +libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ base58.cpp \ allocators.cpp \ @@ -184,8 +185,8 @@ if TARGET_WINDOWS bitcoind_SOURCES += bitcoind-res.rc endif -AM_CPPFLAGS += $(BDB_CPPFLAGS) bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) +bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES) # bitcoin-cli binary # bitcoin_cli_LDADD = \ @@ -193,6 +194,7 @@ bitcoin_cli_LDADD = \ libbitcoin_common.a \ $(BOOST_LIBS) bitcoin_cli_SOURCES = bitcoin-cli.cpp +bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # if TARGET_WINDOWS diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index f434118abb..749b976c44 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -1,8 +1,3 @@ -AM_CPPFLAGS += -I$(srcdir) \ - -I$(builddir)/qt \ - -I$(builddir)/qt/forms \ - $(PROTOBUF_CFLAGS) \ - $(QR_CFLAGS) bin_PROGRAMS += qt/bitcoin-qt noinst_LIBRARIES += qt/libbitcoinqt.a @@ -319,8 +314,12 @@ RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc -qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(srcdir)/qt/forms $(QT_DBUS_INCLUDES) +BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \ + -I$(builddir)/qt/forms + +qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ + $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) + qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) @@ -341,8 +340,9 @@ $(QT_MOC): $(PROTOBUF_H) $(QT_MOC_CPP): $(PROTOBUF_H) # bitcoin-qt binary # -qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \ - -I$(srcdir)/qt/forms +qt_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ + $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) + qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp if TARGET_DARWIN qt_bitcoin_qt_SOURCES += $(BITCOIN_MM) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 09e61cf57c..e0b49d0240 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,8 +1,3 @@ -AM_CPPFLAGS += -I$(srcdir) \ - -I$(srcdir)/qt \ - -I$(builddir)/qt \ - $(PROTOBUF_CFLAGS) \ - $(QR_CFLAGS) bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt @@ -17,7 +12,8 @@ TEST_QT_H = \ qt/test/paymentrequestdata.h \ qt/test/paymentservertests.h -qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES) +qt_test_test_bitcoin_qt_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ + $(QT_INCLUDES) $(QT_TEST_INCLUDES) qt_test_test_bitcoin_qt_SOURCES = \ qt/test/test_main.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1e4bd4ca8c..988830260c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,5 +1,3 @@ -AM_CPPFLAGS += -I$(builddir)/test/ - TESTS += test/test_bitcoin bin_PROGRAMS += test/test_bitcoin TEST_SRCDIR = test @@ -62,7 +60,7 @@ BITCOIN_TESTS += \ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) -test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS) +test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) if ENABLE_WALLET From efe6888407186b8a468f357fa7084c0a8c3de503 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 5 Jun 2014 15:51:05 -0400 Subject: [PATCH 141/336] build: fix version dependency --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 58a50adec6..3016be47b9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,7 +102,7 @@ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ $(abs_top_srcdir) -version.o: obj/build.h +libbitcoin_common_a-version.$(OBJEXT): obj/build.h libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_server_a_SOURCES = \ From b917555b04b501efe22990eedadc59ae8baa2519 Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Fri, 6 Jun 2014 02:24:59 -0500 Subject: [PATCH 142/336] qt: PeerTableModel: Fix potential deadlock. #4296 --- src/qt/peertablemodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index fba9d84e77..859d82f40c 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -49,8 +49,8 @@ public: /** Pull a full list of peers from vNodes into our cache */ void refreshPeers() { - TRY_LOCK(cs_vNodes, lockNodes); { + TRY_LOCK(cs_vNodes, lockNodes); if (!lockNodes) { // skip the refresh if we can't immediately get the lock @@ -70,8 +70,8 @@ public: } // if we can, retrieve the CNodeStateStats for each node. - TRY_LOCK(cs_main, lockMain); { + TRY_LOCK(cs_main, lockMain); if (lockMain) { BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats) From c6cb21d17ab8097b6a425d37e48c955fbb0e9f0c Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Thu, 10 Apr 2014 14:14:18 -0400 Subject: [PATCH 143/336] Type-safe CFeeRate class Use CFeeRate instead of an int64_t for quantities that are fee-per-size. Helps prevent unit-conversion mismatches between the wallet, relaying, and mining code. --- src/core.cpp | 19 ++++++++++++++++ src/core.h | 37 +++++++++++++++++++++++++------ src/init.cpp | 14 ++++++------ src/main.cpp | 30 +++++++++----------------- src/miner.cpp | 42 +++++++++++++++++++----------------- src/qt/coincontroldialog.cpp | 29 ++++++------------------- src/qt/guiutil.cpp | 2 +- src/qt/optionsdialog.cpp | 4 ++-- src/qt/optionsmodel.cpp | 21 ++++++++++-------- src/qt/paymentserver.cpp | 2 +- src/qt/walletmodel.cpp | 6 ------ src/rpcmisc.cpp | 4 ++-- src/rpcnet.cpp | 2 +- src/rpcwallet.cpp | 2 +- src/wallet.cpp | 22 ++++++------------- src/wallet.h | 2 +- 16 files changed, 123 insertions(+), 115 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index aadcb44b98..6039986e6c 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -72,6 +72,25 @@ void CTxOut::print() const LogPrintf("%s\n", ToString()); } +CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) +{ + if (nSize > 0) + nSatoshisPerK = nFeePaid*1000/nSize; + else + nSatoshisPerK = 0; +} + +int64_t CFeeRate::GetFee(size_t nSize) +{ + return nSatoshisPerK*nSize / 1000; +} + +std::string CFeeRate::ToString() const +{ + std::string result = FormatMoney(nSatoshisPerK) + " BTC/kB"; + return result; +} + uint256 CTransaction::GetHash() const { return SerializeHash(*this); diff --git a/src/core.h b/src/core.h index ba7f691119..9fccffc4b2 100644 --- a/src/core.h +++ b/src/core.h @@ -112,6 +112,28 @@ public: +/** Type-safe wrapper class to for fee rates + * (how much to pay based on transaction size) + */ +class CFeeRate +{ +private: + int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes +public: + explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } + CFeeRate(int64_t nFeePaid, size_t nSize); + CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } + + int64_t GetFee(size_t size); // unit returned is satoshis + int64_t GetFeePerK() { return GetFee(1000); } // satoshis-per-1000-bytes + + friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } + friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } + friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } + + std::string ToString() const; +}; + /** An output of a transaction. It contains the public key that the next input * must be able to sign with to claim it. @@ -148,17 +170,18 @@ public: uint256 GetHash() const; - bool IsDust(int64_t nMinRelayTxFee) const + bool IsDust(CFeeRate minRelayTxFee) const { - // "Dust" is defined in terms of CTransaction::nMinRelayTxFee, + // "Dust" is defined in terms of CTransaction::minRelayTxFee, // which has units satoshis-per-kilobyte. // If you'd pay more than 1/3 in fees // to spend something, then we consider it dust. // A typical txout is 34 bytes big, and will - // need a CTxIn of at least 148 bytes to spend, + // need a CTxIn of at least 148 bytes to spend: // so dust is a txout less than 546 satoshis - // with default nMinRelayTxFee. - return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee); + // with default minRelayTxFee. + size_t nSize = GetSerializeSize(SER_DISK,0)+148u; + return (nValue < 3*minRelayTxFee.GetFee(nSize)); } friend bool operator==(const CTxOut& a, const CTxOut& b) @@ -183,8 +206,8 @@ public: class CTransaction { public: - static int64_t nMinTxFee; - static int64_t nMinRelayTxFee; + static CFeeRate minTxFee; + static CFeeRate minRelayTxFee; static const int CURRENT_VERSION=1; int nVersion; std::vector vin; diff --git a/src/init.cpp b/src/init.cpp index d924bd293b..1aad679b3b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -281,8 +281,8 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -limitfreerelay= " + _("Continuously rate-limit free transactions to *1000 bytes per minute (default:15)") + "\n"; strUsage += " -maxsigcachesize= " + _("Limit size of signature cache to entries (default: 50000)") + "\n"; } - strUsage += " -mintxfee= " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::nMinTxFee) + ")" + "\n"; - strUsage += " -minrelaytxfee= " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::nMinRelayTxFee) + ")" + "\n"; + strUsage += " -mintxfee= " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::minTxFee.GetFeePerK()) + ")" + "\n"; + strUsage += " -minrelaytxfee= " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::minRelayTxFee.GetFeePerK()) + ")" + "\n"; strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { @@ -560,7 +560,7 @@ bool AppInit2(boost::thread_group& threadGroup) { int64_t n = 0; if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CTransaction::nMinTxFee = n; + CTransaction::minTxFee = CFeeRate(n); else return InitError(strprintf(_("Invalid amount for -mintxfee=: '%s'"), mapArgs["-mintxfee"])); } @@ -568,7 +568,7 @@ bool AppInit2(boost::thread_group& threadGroup) { int64_t n = 0; if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) - CTransaction::nMinRelayTxFee = n; + CTransaction::minRelayTxFee = CFeeRate(n); else return InitError(strprintf(_("Invalid amount for -minrelaytxfee=: '%s'"), mapArgs["-minrelaytxfee"])); } @@ -576,10 +576,12 @@ bool AppInit2(boost::thread_group& threadGroup) #ifdef ENABLE_WALLET if (mapArgs.count("-paytxfee")) { - if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) + int64_t nFeePerK = 0; + if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s'"), mapArgs["-paytxfee"])); - if (nTransactionFee > nHighTransactionFeeWarning) + if (nFeePerK > nHighTransactionFeeWarning) InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + payTxFee = CFeeRate(nFeePerK, 1000); } bSpendZeroConfChange = GetArg("-spendzeroconfchange", true); diff --git a/src/main.cpp b/src/main.cpp index 8e63e4213f..9d6c01d64e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,9 +50,9 @@ bool fTxIndex = false; unsigned int nCoinCacheSize = 5000; /** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ -int64_t CTransaction::nMinTxFee = 10000; // Override with -mintxfee +CFeeRate CTransaction::minTxFee = CFeeRate(10000); // Override with -mintxfee /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ -int64_t CTransaction::nMinRelayTxFee = 1000; +CFeeRate CTransaction::minRelayTxFee = CFeeRate(1000); struct COrphanBlock { uint256 hashBlock; @@ -543,7 +543,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason) } if (whichType == TX_NULL_DATA) nDataOut++; - else if (txout.IsDust(CTransaction::nMinRelayTxFee)) { + else if (txout.IsDust(CTransaction::minRelayTxFee)) { reason = "dust"; return false; } @@ -783,10 +783,10 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode) { - // Base fee is either nMinTxFee or nMinRelayTxFee - int64_t nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee; + // Base fee is either minTxFee or minRelayTxFee + CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee; - int64_t nMinFee = (1 + (int64_t)nBytes / 1000) * nBaseFee; + int64_t nMinFee = baseFeeRate.GetFee(nBytes); if (fAllowFree) { @@ -800,16 +800,6 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, nMinFee = 0; } - // This code can be removed after enough miners have upgraded to version 0.9. - // Until then, be safe when sending and require a fee if any output - // is less than CENT: - if (nMinFee < nBaseFee && mode == GMF_SEND) - { - BOOST_FOREACH(const CTxOut& txout, tx.vout) - if (txout.nValue < CENT) - nMinFee = nBaseFee; - } - if (!MoneyRange(nMinFee)) nMinFee = MAX_MONEY; return nMinFee; @@ -916,10 +906,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa hash.ToString(), nFees, txMinFee), REJECT_INSUFFICIENTFEE, "insufficient fee"); - // Continuously rate-limit free transactions + // Continuously rate-limit free (really, very-low-fee)transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (fLimitFree && nFees < CTransaction::nMinRelayTxFee) + if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize)) { static CCriticalSection csFreeLimiter; static double dFreeCount; @@ -940,10 +930,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa dFreeCount += nSize; } - if (fRejectInsaneFee && nFees > CTransaction::nMinRelayTxFee * 10000) + if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000) return error("AcceptToMemoryPool: : insane fees %s, %d > %d", hash.ToString(), - nFees, CTransaction::nMinRelayTxFee * 10000); + nFees, CTransaction::minRelayTxFee.GetFee(nSize) * 10000); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. diff --git a/src/miner.cpp b/src/miner.cpp index 94fc8e3888..4e131c088b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -52,25 +52,30 @@ void SHA256Transform(void* pstate, void* pinput, const void* pinit) ((uint32_t*)pstate)[i] = ctx.h[i]; } -// Some explaining would be appreciated +// +// Unconfirmed transactions in the memory pool often depend on other +// transactions in the memory pool. When we select transactions from the +// pool, we select by highest priority or fee rate, so we might consider +// transactions that depend on transactions that aren't yet in the block. +// The COrphan class keeps track of these 'temporary orphans' while +// CreateBlock is figuring out which transactions to include. +// class COrphan { public: const CTransaction* ptx; set setDependsOn; double dPriority; - double dFeePerKb; + CFeeRate feeRate; - COrphan(const CTransaction* ptxIn) + COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) { - ptx = ptxIn; - dPriority = dFeePerKb = 0; } void print() const { - LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n", - ptx->GetHash().ToString(), dPriority, dFeePerKb); + LogPrintf("COrphan(hash=%s, dPriority=%.1f, fee=%s)\n", + ptx->GetHash().ToString(), dPriority, feeRate.ToString()); BOOST_FOREACH(uint256 hash, setDependsOn) LogPrintf(" setDependsOn %s\n", hash.ToString()); } @@ -80,8 +85,8 @@ public: uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; -// We want to sort transactions by priority and fee, so: -typedef boost::tuple TxPriority; +// We want to sort transactions by priority and fee rate, so: +typedef boost::tuple TxPriority; class TxPriorityCompare { bool byFee; @@ -210,18 +215,15 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); dPriority = tx.ComputePriority(dPriority, nTxSize); - // This is a more accurate fee-per-kilobyte than is used by the client code, because the - // client code rounds up the size to the nearest 1K. That's good, because it gives an - // incentive to create smaller transactions. - double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0); + CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); if (porphan) { porphan->dPriority = dPriority; - porphan->dFeePerKb = dFeePerKb; + porphan->feeRate = feeRate; } else - vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &mi->second.GetTx())); + vecPriority.push_back(TxPriority(dPriority, feeRate, &mi->second.GetTx())); } // Collect transactions into block @@ -237,7 +239,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) { // Take highest priority transaction off the priority queue: double dPriority = vecPriority.front().get<0>(); - double dFeePerKb = vecPriority.front().get<1>(); + CFeeRate feeRate = vecPriority.front().get<1>(); const CTransaction& tx = *(vecPriority.front().get<2>()); std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer); @@ -254,7 +256,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; // Skip free transactions if we're past the minimum block size: - if (fSortedByFee && (dFeePerKb < CTransaction::nMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + if (fSortedByFee && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; // Prioritize by fee once past the priority size or we run out of high-priority @@ -298,8 +300,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (fPrintPriority) { - LogPrintf("priority %.1f feeperkb %.1f txid %s\n", - dPriority, dFeePerKb, tx.GetHash().ToString()); + LogPrintf("priority %.1f fee %s txid %s\n", + dPriority, feeRate.ToString(), tx.GetHash().ToString()); } // Add transactions that depend on this one to the priority queue @@ -312,7 +314,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) porphan->setDependsOn.erase(hash); if (porphan->setDependsOn.empty()) { - vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx)); + vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx)); std::push_heap(vecPriority.begin(), vecPriority.end(), comparer); } } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index dc9d2afe27..e27f1bff97 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -453,7 +453,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) CTxOut txout(amount, (CScript)vector(24, 0)); txDummy.vout.push_back(txout); - if (txout.IsDust(CTransaction::nMinRelayTxFee)) + if (txout.IsDust(CTransaction::minRelayTxFee)) fDust = true; } } @@ -525,7 +525,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); // Fee - int64_t nFee = nTransactionFee * (1 + (int64_t)nBytes / 1000); + int64_t nFee = payTxFee.GetFee(nBytes); // Min Fee int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND); @@ -536,26 +536,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { nChange = nAmount - nPayFee - nPayAmount; - // if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee - if (nPayFee < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT) - { - if (nChange < CTransaction::nMinTxFee) // change < 0.0001 => simply move all change to fees - { - nPayFee += nChange; - nChange = 0; - } - else - { - nChange = nChange + nPayFee - CTransaction::nMinTxFee; - nPayFee = CTransaction::nMinTxFee; - } - } - // Never create dust outputs; if we would, just add the dust to the fee. if (nChange > 0 && nChange < CENT) { CTxOut txout(nChange, (CScript)vector(24, 0)); - if (txout.IsDust(CTransaction::nMinRelayTxFee)) + if (txout.IsDust(CTransaction::minRelayTxFee)) { nPayFee += nChange; nChange = 0; @@ -610,19 +595,19 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // tool tips QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "

"; - toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "

"; + toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "

"; toolTip1 += tr("Can vary +/- 1 byte per input."); QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "

"; toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "

"; - toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)); + toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())); QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "

"; - toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)) + "

"; + toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "

"; toolTip3 += tr("Amounts below 0.546 times the minimum relay fee are shown as dust."); QString toolTip4 = tr("This label turns red, if the change is smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "

"; - toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee)); + toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())); l5->setToolTip(toolTip1); l6->setToolTip(toolTip2); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 1922d228c5..4fe98251d9 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -210,7 +210,7 @@ bool isDust(const QString& address, qint64 amount) CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script; script.SetDestination(dest); CTxOut txOut(amount, script); - return txOut.IsDust(CTransaction::nMinRelayTxFee); + return txOut.IsDust(CTransaction::minRelayTxFee); } QString HtmlEscape(const QString& str, bool fMultiLine) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 96464d2cc0..1cbf5f8810 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -14,7 +14,7 @@ #include "monitoreddatamapper.h" #include "optionsmodel.h" -#include "main.h" // for CTransaction::nMinTxFee and MAX_SCRIPTCHECK_THREADS +#include "main.h" // for CTransaction::minTxFee and MAX_SCRIPTCHECK_THREADS #include "netbase.h" #include "txdb.h" // for -dbcache defaults @@ -101,7 +101,7 @@ OptionsDialog::OptionsDialog(QWidget *parent) : #endif ui->unit->setModel(new BitcoinUnits(this)); - ui->transactionFee->setSingleStep(CTransaction::nMinTxFee); + ui->transactionFee->setSingleStep(CTransaction::minTxFee.GetFeePerK()); /* Widget-to-option mapper */ mapper = new MonitoredDataMapper(this); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 051098315d..f3a5f37bb3 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -94,7 +94,7 @@ void OptionsModel::Init() #ifdef ENABLE_WALLET if (!settings.contains("nTransactionFee")) settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE); - nTransactionFee = settings.value("nTransactionFee").toLongLong(); // if -paytxfee is set, this will be overridden later in init.cpp + payTxFee = CFeeRate(settings.value("nTransactionFee").toLongLong()); // if -paytxfee is set, this will be overridden later in init.cpp if (mapArgs.count("-paytxfee")) addOverriddenOption("-paytxfee"); @@ -187,15 +187,16 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return settings.value("nSocksVersion", 5); #ifdef ENABLE_WALLET - case Fee: - // Attention: Init() is called before nTransactionFee is set in AppInit2()! + case Fee: { + // Attention: Init() is called before payTxFee is set in AppInit2()! // To ensure we can change the fee on-the-fly update our QSetting when // opening OptionsDialog, which queries Fee via the mapper. - if (nTransactionFee != settings.value("nTransactionFee").toLongLong()) - settings.setValue("nTransactionFee", (qint64)nTransactionFee); - // Todo: Consider to revert back to use just nTransactionFee here, if we don't want + if (!(payTxFee == CFeeRate(settings.value("nTransactionFee").toLongLong(), 1000))) + settings.setValue("nTransactionFee", (qint64)payTxFee.GetFeePerK()); + // Todo: Consider to revert back to use just payTxFee here, if we don't want // -paytxfee to update our QSettings! return settings.value("nTransactionFee"); + } case SpendZeroConfChange: return settings.value("bSpendZeroConfChange"); #endif @@ -284,12 +285,14 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; #ifdef ENABLE_WALLET - case Fee: // core option - can be changed on-the-fly + case Fee: { // core option - can be changed on-the-fly // Todo: Add is valid check and warn via message, if not - nTransactionFee = value.toLongLong(); - settings.setValue("nTransactionFee", (qint64)nTransactionFee); + qint64 nTransactionFee = value.toLongLong(); + payTxFee = CFeeRate(nTransactionFee, 1000); + settings.setValue("nTransactionFee", nTransactionFee); emit transactionFeeChanged(nTransactionFee); break; + } case SpendZeroConfChange: if (settings.value("bSpendZeroConfChange") != value) { settings.setValue("bSpendZeroConfChange", value); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 4c45585685..6165731d22 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -551,7 +551,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); - if (txOut.IsDust(CTransaction::nMinRelayTxFee)) { + if (txOut.IsDust(CTransaction::minRelayTxFee)) { emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 37d82ec063..87ff3db584 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -231,12 +231,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return AmountExceedsBalance; } - if((total + nTransactionFee) > nBalance) - { - transaction.setTransactionFee(nTransactionFee); - return SendCoinsReturn(AmountWithFeeExceedsBalance); - } - { LOCK2(cs_main, wallet->cs_wallet); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 27d6d61a36..9802445fcb 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -81,9 +81,9 @@ Value getinfo(const Array& params, bool fHelp) } if (pwalletMain && pwalletMain->IsCrypted()) obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); - obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); + obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); #endif - obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); + obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK()))); obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 63eed09b64..0eca55a472 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -368,7 +368,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); - obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); + obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK()))); Array localAddresses; { LOCK(cs_mapLocalHost); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index e3b35dbb04..f376ab6b63 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1883,7 +1883,7 @@ Value settxfee(const Array& params, bool fHelp) if (params[0].get_real() != 0.0) nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts - nTransactionFee = nAmount; + payTxFee = CFeeRate(nAmount, 1000); return true; } diff --git a/src/wallet.cpp b/src/wallet.cpp index 89604f96ac..ef0b442e1a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -16,7 +16,7 @@ using namespace std; // Settings -int64_t nTransactionFee = DEFAULT_TRANSACTION_FEE; +CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); bool bSpendZeroConfChange = true; ////////////////////////////////////////////////////////////////////////////// @@ -1233,7 +1233,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, { LOCK2(cs_main, cs_wallet); { - nFeeRet = nTransactionFee; + nFeeRet = payTxFee.GetFeePerK(); while (true) { wtxNew.vin.clear(); @@ -1246,7 +1246,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) { CTxOut txout(s.second, s.first); - if (txout.IsDust(CTransaction::nMinRelayTxFee)) + if (txout.IsDust(CTransaction::minRelayTxFee)) { strFailReason = _("Transaction amount too small"); return false; @@ -1272,16 +1272,6 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } int64_t nChange = nValueIn - nValue - nFeeRet; - // The following if statement should be removed once enough miners - // have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids - // creating free transactions that have change outputs less than - // CENT bitcoins. - if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT) - { - int64_t nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet); - nChange -= nMoveToFee; - nFeeRet += nMoveToFee; - } if (nChange > 0) { @@ -1317,7 +1307,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, // Never create dust outputs; if we would, just // add the dust to the fee. - if (newTxOut.IsDust(CTransaction::nMinRelayTxFee)) + if (newTxOut.IsDust(CTransaction::minRelayTxFee)) { nFeeRet += nChange; reservekey.ReturnKey(); @@ -1355,7 +1345,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, dPriority = wtxNew.ComputePriority(dPriority, nBytes); // Check that enough fee is included - int64_t nPayFee = nTransactionFee * (1 + (int64_t)nBytes / 1000); + int64_t nPayFee = payTxFee.GetFee(nBytes); bool fAllowFree = AllowFree(dPriority); int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND); if (nFeeRet < max(nPayFee, nMinFee)) @@ -1464,7 +1454,7 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV // Check amount if (nValue <= 0) return _("Invalid amount"); - if (nValue + nTransactionFee > GetBalance()) + if (nValue > GetBalance()) return _("Insufficient funds"); // Parse Bitcoin address diff --git a/src/wallet.h b/src/wallet.h index 8e2917188a..274c31157c 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -24,7 +24,7 @@ #include // Settings -extern int64_t nTransactionFee; +extern CFeeRate payTxFee; extern bool bSpendZeroConfChange; // -paytxfee default From 0193fb82a6fe443e5434f2c2af3b252409c19b25 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Fri, 14 Mar 2014 12:19:52 -0400 Subject: [PATCH 144/336] Allow multiple regression tests to run at once Choose ports at startup based on PID, so multiple regression tests can run on the same system at the same time. --- qa/rpc-tests/util.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index 40f4a1458f..eab526daf3 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -20,8 +20,10 @@ import re from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException from util import * -START_P2P_PORT=11000 -START_RPC_PORT=11100 +def p2p_port(n): + return 11000 + n + os.getpid()%999 +def rpc_port(n): + return 12000 + n + os.getpid()%999 def check_json_precision(): """Make sure json library being used does not lose precision converting BTC values""" @@ -58,6 +60,17 @@ def sync_mempools(rpc_connections): bitcoind_processes = [] +def initialize_datadir(dir, n): + datadir = os.path.join(dir, "node"+str(n)) + if not os.path.isdir(datadir): + os.makedirs(datadir) + with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f: + f.write("regtest=1\n"); + f.write("rpcuser=rt\n"); + f.write("rpcpassword=rt\n"); + f.write("port="+str(p2p_port(n))+"\n"); + f.write("rpcport="+str(rpc_port(n))+"\n"); + def initialize_chain(test_dir): """ Create (or copy from cache) a 200-block-long chain and @@ -69,17 +82,10 @@ def initialize_chain(test_dir): devnull = open("/dev/null", "w+") # Create cache directories, run bitcoinds: for i in range(4): - datadir = os.path.join("cache", "node"+str(i)) - os.makedirs(datadir) - with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f: - f.write("regtest=1\n"); - f.write("rpcuser=rt\n"); - f.write("rpcpassword=rt\n"); - f.write("port="+str(START_P2P_PORT+i)+"\n"); - f.write("rpcport="+str(START_RPC_PORT+i)+"\n"); + initialize_datadir("cache", i) args = [ "bitcoind", "-keypool=1", "-datadir="+datadir ] if i > 0: - args.append("-connect=127.0.0.1:"+str(START_P2P_PORT)) + args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes.append(subprocess.Popen(args)) subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir, "-rpcwait", "getblockcount"], stdout=devnull) @@ -87,7 +93,7 @@ def initialize_chain(test_dir): rpcs = [] for i in range(4): try: - url = "http://rt:rt@127.0.0.1:%d"%(START_RPC_PORT+i,) + url = "http://rt:rt@127.0.0.1:%d"%(rpc_port(i),) rpcs.append(AuthServiceProxy(url)) except: sys.stderr.write("Error connecting to "+url+"\n") @@ -112,6 +118,7 @@ def initialize_chain(test_dir): from_dir = os.path.join("cache", "node"+str(i)) to_dir = os.path.join(test_dir, "node"+str(i)) shutil.copytree(from_dir, to_dir) + initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf def _rpchost_to_args(rpchost): '''Convert optional IP:port spec to rpcconnect/rpcport args''' @@ -138,7 +145,7 @@ def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): devnull = open("/dev/null", "w+") for i in range(num_nodes): datadir = os.path.join(dir, "node"+str(i)) - args = [ "bitcoind", "-datadir="+datadir ] + args = [ "bitcoind", "-datadir="+datadir, "-keypool=1" ] if extra_args is not None: args += extra_args[i] bitcoind_processes.append(subprocess.Popen(args)) @@ -149,7 +156,7 @@ def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): # Create&return JSON-RPC connections rpc_connections = [] for i in range(num_nodes): - url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', START_RPC_PORT+i,) + url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) rpc_connections.append(AuthServiceProxy(url)) return rpc_connections @@ -168,7 +175,7 @@ def wait_bitcoinds(): del bitcoind_processes[:] def connect_nodes(from_connection, node_num): - ip_port = "127.0.0.1:"+str(START_P2P_PORT+node_num) + ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") def assert_equal(thing1, thing2): From 171ca7745e77c9f78f26556457fe64e5b2004a75 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Mon, 17 Mar 2014 08:19:54 -0400 Subject: [PATCH 145/336] estimatefee / estimatepriority RPC methods New RPC methods: return an estimate of the fee (or priority) a transaction needs to be likely to confirm in a given number of blocks. Mike Hearn created the first version of this method for estimating fees. It works as follows: For transactions that took 1 to N (I picked N=25) blocks to confirm, keep N buckets with at most 100 entries in each recording the fees-per-kilobyte paid by those transactions. (separate buckets are kept for transactions that confirmed because they are high-priority) The buckets are filled as blocks are found, and are saved/restored in a new fee_estiamtes.dat file in the data directory. A few variations on Mike's initial scheme: To estimate the fee needed for a transaction to confirm in X buckets, all of the samples in all of the buckets are used and a median of all of the data is used to make the estimate. For example, imagine 25 buckets each containing the full 100 entries. Those 2,500 samples are sorted, and the estimate of the fee needed to confirm in the very next block is the 50'th-highest-fee-entry in that sorted list; the estimate of the fee needed to confirm in the next two blocks is the 150'th-highest-fee-entry, etc. That algorithm has the nice property that estimates of how much fee you need to pay to get confirmed in block N will always be greater than or equal to the estimate for block N+1. It would clearly be wrong to say "pay 11 uBTC and you'll get confirmed in 3 blocks, but pay 12 uBTC and it will take LONGER". A single block will not contribute more than 10 entries to any one bucket, so a single miner and a large block cannot overwhelm the estimates. --- doc/release-notes.md | 19 ++ qa/rpc-tests/smartfees.py | 142 +++++++++++++++ qa/rpc-tests/util.py | 143 +++++++++++++-- src/core.h | 3 + src/init.cpp | 14 ++ src/main.cpp | 10 +- src/main.h | 7 - src/rpcclient.cpp | 2 + src/rpcmining.cpp | 61 +++++++ src/rpcserver.cpp | 2 + src/rpcserver.h | 2 + src/txmempool.cpp | 370 ++++++++++++++++++++++++++++++++++++++ src/txmempool.h | 23 +++ 13 files changed, 767 insertions(+), 31 deletions(-) create mode 100755 qa/rpc-tests/smartfees.py diff --git a/doc/release-notes.md b/doc/release-notes.md index f16eec32a2..9272d427cd 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,2 +1,21 @@ (note: this is a temporary file, to be added-to by anybody, and moved to release-notes at release time) + +New RPC methods +=============== + +Fee/Priority estimation +----------------------- + +estimatefee nblocks : Returns approximate fee-per-1,000-bytes needed for +a transaction to be confirmed within nblocks. Returns -1 if not enough +transactions have been observed to compute a good estimate. + +estimatepriority nblocks : Returns approximate priority needed for +a zero-fee transaction to confirm within nblocks. Returns -1 if not +enough free transactions have been observed to compute a good +estimate. + +Statistics used to estimate fees and priorities are saved in the +data directory in the 'fee_estimates.dat' file just before +program shutdown, and are read in at startup. diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py new file mode 100755 index 0000000000..e8abbfba19 --- /dev/null +++ b/qa/rpc-tests/smartfees.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python + +# +# Test fee estimation code +# + +# Add python-bitcoinrpc to module search path: +import os +import sys +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc")) + +import json +import random +import shutil +import subprocess +import tempfile +import traceback + +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * + + +def run_test(nodes, test_dir): + nodes.append(start_node(0, test_dir, + ["-debug=mempool", "-debug=estimatefee"])) + # Node1 mines small-but-not-tiny blocks, and allows free transactions. + # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, + # so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for + # 6 or 7 transactions) + nodes.append(start_node(1, test_dir, + ["-blockprioritysize=1500", "-blockmaxsize=2000", + "-debug=mempool", "-debug=estimatefee"])) + connect_nodes(nodes[1], 0) + + # Node2 is a stingy miner, that + # produces very small blocks (room for only 3 or so transactions) + node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500", + "-debug=mempool", "-debug=estimatefee"] + nodes.append(start_node(2, test_dir, node2args)) + connect_nodes(nodes[2], 0) + + sync_blocks(nodes) + + # Prime the memory pool with pairs of transactions + # (high-priority, random fee and zero-priority, random fee) + min_fee = Decimal("0.001") + fees_per_kb = []; + for i in range(12): + (txid, txhex, fee) = random_zeropri_transaction(nodes, Decimal("1.1"), + min_fee, min_fee, 20) + tx_kbytes = (len(txhex)/2)/1000.0 + fees_per_kb.append(float(fee)/tx_kbytes) + + # Mine blocks with node2 until the memory pool clears: + count_start = nodes[2].getblockcount() + while len(nodes[2].getrawmempool()) > 0: + nodes[2].setgenerate(True, 1) + sync_blocks(nodes) + + all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ] + print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates])) + + # Estimates should be within the bounds of what transactions fees actually were: + delta = 1.0e-6 # account for rounding error + for e in filter(lambda x: x >= 0, all_estimates): + if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb): + raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb)) + + # Generate transactions while mining 30 more blocks, this time with node1: + for i in range(30): + for j in range(random.randrange(6-4,6+4)): + (txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"), + Decimal("0.0"), min_fee, 20) + tx_kbytes = (len(txhex)/2)/1000.0 + fees_per_kb.append(float(fee)/tx_kbytes) + nodes[1].setgenerate(True, 1) + sync_blocks(nodes) + + all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ] + print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates])) + for e in filter(lambda x: x >= 0, all_estimates): + if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb): + raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb)) + + # Finish by mining a normal-sized block: + while len(nodes[0].getrawmempool()) > 0: + nodes[0].setgenerate(True, 1) + sync_blocks(nodes) + + final_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ] + print("Final fee estimates: "+str([ str(e) for e in final_estimates])) + +def main(): + import optparse + + parser = optparse.OptionParser(usage="%prog [options]") + parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", + help="Leave bitcoinds and test.* datadir on exit or error") + parser.add_option("--srcdir", dest="srcdir", default="../../src", + help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") + parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), + help="Root directory for datadirs") + (options, args) = parser.parse_args() + + os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] + + check_json_precision() + + success = False + nodes = [] + try: + print("Initializing test directory "+options.tmpdir) + print(" node0 running at: 127.0.0.1:%d"%(p2p_port(0))) + if not os.path.isdir(options.tmpdir): + os.makedirs(options.tmpdir) + initialize_chain(options.tmpdir) + + run_test(nodes, options.tmpdir) + + success = True + + except AssertionError as e: + print("Assertion failed: "+e.message) + except Exception as e: + print("Unexpected exception caught during testing: "+str(e)) + traceback.print_tb(sys.exc_info()[2]) + + if not options.nocleanup: + print("Cleaning up") + stop_nodes(nodes) + wait_bitcoinds() + shutil.rmtree(options.tmpdir) + + if success: + print("Tests successful") + sys.exit(0) + else: + print("Failed") + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index eab526daf3..eded098c7c 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -12,6 +12,7 @@ sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python from decimal import Decimal import json +import random import shutil import subprocess import time @@ -70,6 +71,7 @@ def initialize_datadir(dir, n): f.write("rpcpassword=rt\n"); f.write("port="+str(p2p_port(n))+"\n"); f.write("rpcport="+str(rpc_port(n))+"\n"); + return datadir def initialize_chain(test_dir): """ @@ -82,7 +84,7 @@ def initialize_chain(test_dir): devnull = open("/dev/null", "w+") # Create cache directories, run bitcoinds: for i in range(4): - initialize_datadir("cache", i) + datadir=initialize_datadir("cache", i) args = [ "bitcoind", "-keypool=1", "-datadir="+datadir ] if i > 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) @@ -140,25 +142,28 @@ def _rpchost_to_args(rpchost): rv += ['-rpcport=' + rpcport] return rv -def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): - # Start bitcoinds, and wait for RPC interface to be up and running: +def start_node(i, dir, extra_args=None, rpchost=None): + """ + Start a bitcoind and return RPC connection to it + """ + datadir = os.path.join(dir, "node"+str(i)) + args = [ "bitcoind", "-datadir="+datadir, "-keypool=1" ] + if extra_args is not None: args.extend(extra_args) + bitcoind_processes.append(subprocess.Popen(args)) devnull = open("/dev/null", "w+") - for i in range(num_nodes): - datadir = os.path.join(dir, "node"+str(i)) - args = [ "bitcoind", "-datadir="+datadir, "-keypool=1" ] - if extra_args is not None: - args += extra_args[i] - bitcoind_processes.append(subprocess.Popen(args)) - subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] + - _rpchost_to_args(rpchost) + - ["-rpcwait", "getblockcount"], stdout=devnull) + subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] + + _rpchost_to_args(rpchost) + + ["-rpcwait", "getblockcount"], stdout=devnull) devnull.close() - # Create&return JSON-RPC connections - rpc_connections = [] - for i in range(num_nodes): - url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) - rpc_connections.append(AuthServiceProxy(url)) - return rpc_connections + url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + return AuthServiceProxy(url) + +def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): + """ + Start multiple bitcoinds, return RPC connections to them + """ + if extra_args is None: extra_args = [ None for i in range(num_nodes) ] + return [ start_node(i, dir, extra_args[i], rpchost) for i in range(num_nodes) ] def debug_log(dir, n_node): return os.path.join(dir, "node"+str(n_node), "regtest", "debug.log") @@ -178,6 +183,108 @@ def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") +def find_output(node, txid, amount): + """ + Return index to output of txid with value amount + Raises exception if there is none. + """ + txdata = node.getrawtransaction(txid, 1) + for i in range(len(txdata["vout"])): + if txdata["vout"][i]["value"] == amount: + return i + raise RuntimeError("find_output txid %s : %s not found"%(txid,str(amount))) + +def gather_inputs(from_node, amount_needed): + """ + Return a random set of unspent txouts that are enough to pay amount_needed + """ + utxo = from_node.listunspent(1) + random.shuffle(utxo) + inputs = [] + total_in = Decimal("0.00000000") + while total_in < amount_needed and len(utxo) > 0: + t = utxo.pop() + total_in += t["amount"] + inputs.append({ "txid" : t["txid"], "vout" : t["vout"], "address" : t["address"] } ) + if total_in < amount_needed: + raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee*2, total_in)) + return (total_in, inputs) + +def make_change(from_node, amount_in, amount_out, fee): + """ + Create change output(s), return them + """ + outputs = {} + amount = amount_out+fee + change = amount_in - amount + if change > amount*2: + # Create an extra change output to break up big inputs + outputs[from_node.getnewaddress()] = float(change/2) + change = change/2 + if change > 0: + outputs[from_node.getnewaddress()] = float(change) + return outputs + +def send_zeropri_transaction(from_node, to_node, amount, fee): + """ + Create&broadcast a zero-priority transaction. + Returns (txid, hex-encoded-txdata) + Ensures transaction is zero-priority by first creating a send-to-self, + then using it's output + """ + + # Create a send-to-self with confirmed inputs: + self_address = from_node.getnewaddress() + (total_in, inputs) = gather_inputs(from_node, amount+fee*2) + outputs = make_change(from_node, total_in, amount+fee, fee) + outputs[self_address] = float(amount+fee) + + self_rawtx = from_node.createrawtransaction(inputs, outputs) + self_signresult = from_node.signrawtransaction(self_rawtx) + self_txid = from_node.sendrawtransaction(self_signresult["hex"], True) + + vout = find_output(from_node, self_txid, amount+fee) + # Now immediately spend the output to create a 1-input, 1-output + # zero-priority transaction: + inputs = [ { "txid" : self_txid, "vout" : vout } ] + outputs = { to_node.getnewaddress() : float(amount) } + + rawtx = from_node.createrawtransaction(inputs, outputs) + signresult = from_node.signrawtransaction(rawtx) + txid = from_node.sendrawtransaction(signresult["hex"], True) + + return (txid, signresult["hex"]) + +def random_zeropri_transaction(nodes, amount, min_fee, fee_increment, fee_variants): + """ + Create a random zero-priority transaction. + Returns (txid, hex-encoded-transaction-data, fee) + """ + from_node = random.choice(nodes) + to_node = random.choice(nodes) + fee = min_fee + fee_increment*random.randint(0,fee_variants) + (txid, txhex) = send_zeropri_transaction(from_node, to_node, amount, fee) + return (txid, txhex, fee) + +def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants): + """ + Create a random transaction. + Returns (txid, hex-encoded-transaction-data, fee) + """ + from_node = random.choice(nodes) + to_node = random.choice(nodes) + fee = min_fee + fee_increment*random.randint(0,fee_variants) + + (total_in, inputs) = gather_inputs(from_node, amount+fee) + outputs = make_change(from_node, total_in, amount, fee) + outputs[to_node.getnewaddress()] = float(amount) + + rawtx = from_node.createrawtransaction(inputs, outputs) + signresult = from_node.signrawtransaction(rawtx) + txid = from_node.sendrawtransaction(signresult["hex"], True) + + return (txid, signresult["hex"], fee) + def assert_equal(thing1, thing2): if thing1 != thing2: raise AssertionError("%s != %s"%(str(thing1),str(thing2))) diff --git a/src/core.h b/src/core.h index 9fccffc4b2..0e59129349 100644 --- a/src/core.h +++ b/src/core.h @@ -120,6 +120,7 @@ class CFeeRate private: int64_t nSatoshisPerK; // unit is satoshis-per-1,000-bytes public: + CFeeRate() : nSatoshisPerK(0) { } explicit CFeeRate(int64_t _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } CFeeRate(int64_t nFeePaid, size_t nSize); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } @@ -132,6 +133,8 @@ public: friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } std::string ToString() const; + + IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); ) }; diff --git a/src/init.cpp b/src/init.cpp index 1aad679b3b..aca5e0c9aa 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -59,6 +59,7 @@ enum BindFlags { BF_REPORT_ERROR = (1U << 1) }; +static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; ////////////////////////////////////////////////////////////////////////////// // @@ -121,6 +122,14 @@ void Shutdown() #endif StopNode(); UnregisterNodeSignals(GetNodeSignals()); + + boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; + CAutoFile est_fileout = CAutoFile(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION); + if (est_fileout) + mempool.WriteFeeEstimates(est_fileout); + else + LogPrintf("failed to write fee estimates"); + { LOCK(cs_main); #ifdef ENABLE_WALLET @@ -933,6 +942,11 @@ bool AppInit2(boost::thread_group& threadGroup) return false; } + boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; + CAutoFile est_filein = CAutoFile(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); + if (est_filein) + mempool.ReadFeeEstimates(est_filein); + // ********************************************************* Step 8: load wallet #ifdef ENABLE_WALLET if (fDisableWallet) { diff --git a/src/main.cpp b/src/main.cpp index 9d6c01d64e..429473d8f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -851,6 +851,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa CCoinsView dummy; CCoinsViewCache view(dummy); + int64_t nValueIn = 0; { LOCK(pool.cs); CCoinsViewMemPool viewMemPool(*pcoinsTip, pool); @@ -879,6 +880,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Bring the best block into scope view.GetBestBlock(); + nValueIn = view.GetValueIn(tx); + // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool view.SetBackend(dummy); } @@ -891,7 +894,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // you should add code here to check that the transaction does a // reasonable number of ECDSA signature verifications. - int64_t nValueIn = view.GetValueIn(tx); int64_t nValueOut = tx.GetValueOut(); int64_t nFees = nValueIn-nValueOut; double dPriority = view.GetPriority(tx, chainActive.Height()); @@ -2017,11 +2019,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) { return false; // Remove conflicting transactions from the mempool. list txConflicted; - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - list unused; - mempool.remove(tx, unused); - mempool.removeConflicts(tx, txConflicted); - } + mempool.removeForBlock(block.vtx, pindexNew->nHeight, txConflicted); mempool.check(pcoinsTip); // Update chainActive & related variables. UpdateTip(pindexNew); diff --git a/src/main.h b/src/main.h index 3fccd32a29..23c8660376 100644 --- a/src/main.h +++ b/src/main.h @@ -292,13 +292,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx); unsigned int GetP2SHSigOpCount(const CTransaction& tx, CCoinsViewCache& mapInputs); -inline bool AllowFree(double dPriority) -{ - // Large (in bytes) low-priority (new, small-coin) transactions - // need a fee. - return dPriority > COIN * 144 / 250; -} - // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline. diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 4f3c39ce9b..b89a95ad11 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -176,6 +176,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "keypoolrefill" && n > 0) ConvertTo(params[0]); if (strMethod == "getrawmempool" && n > 0) ConvertTo(params[0]); + if (strMethod == "estimatefee" && n > 0) ConvertTo(params[0]); + if (strMethod == "estimatepriority" && n > 0) ConvertTo(params[0]); return params; } diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 23876c603d..dd148c6af1 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -15,6 +15,7 @@ #endif #include +#include #include "json/json_spirit_utils.h" #include "json/json_spirit_value.h" @@ -626,3 +627,63 @@ Value submitblock(const Array& params, bool fHelp) return Value::null; } + +Value estimatefee(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "estimatefee nblocks\n" + "\nEstimates the approximate fee per kilobyte\n" + "needed for a transaction to get confirmed\n" + "within nblocks blocks.\n" + "\nArguments:\n" + "1. nblocks (numeric)\n" + "\nResult:\n" + "n : (numeric) estimated fee-per-kilobyte\n" + "\n" + "-1.0 is returned if not enough transactions and\n" + "blocks have been observed to make an estimate.\n" + "\nExample:\n" + + HelpExampleCli("estimatefee", "6") + ); + + RPCTypeCheck(params, boost::assign::list_of(int_type)); + + int nBlocks = params[0].get_int(); + if (nBlocks < 1) + nBlocks = 1; + + CFeeRate feeRate = mempool.estimateFee(nBlocks); + if (feeRate == CFeeRate(0)) + return -1.0; + + return ValueFromAmount(feeRate.GetFeePerK()); +} + +Value estimatepriority(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "estimatepriority nblocks\n" + "\nEstimates the approximate priority\n" + "a zero-fee transaction needs to get confirmed\n" + "within nblocks blocks.\n" + "\nArguments:\n" + "1. nblocks (numeric)\n" + "\nResult:\n" + "n : (numeric) estimated priority\n" + "\n" + "-1.0 is returned if not enough transactions and\n" + "blocks have been observed to make an estimate.\n" + "\nExample:\n" + + HelpExampleCli("estimatepriority", "6") + ); + + RPCTypeCheck(params, boost::assign::list_of(int_type)); + + int nBlocks = params[0].get_int(); + if (nBlocks < 1) + nBlocks = 1; + + return mempool.estimatePriority(nBlocks); +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2534a9dcf4..72a7fe83ef 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -268,6 +268,8 @@ static const CRPCCommand vRPCCommands[] = { "createmultisig", &createmultisig, true, true , false }, { "validateaddress", &validateaddress, true, false, false }, /* uses wallet if enabled */ { "verifymessage", &verifymessage, false, false, false }, + { "estimatefee", &estimatefee, true, true, false }, + { "estimatepriority", &estimatepriority, true, true, false }, #ifdef ENABLE_WALLET /* Wallet */ diff --git a/src/rpcserver.h b/src/rpcserver.h index e8cd2cd0fc..73e8b9426c 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -133,6 +133,8 @@ extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool f extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value estimatepriority(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 64c9eac73d..4bf01d4848 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -6,6 +6,8 @@ #include "core.h" #include "txmempool.h" +#include + using namespace std; CTxMemPoolEntry::CTxMemPoolEntry() @@ -35,12 +37,311 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const return dResult; } +// +// Keep track of fee/priority for transactions confirmed within N blocks +// +class CBlockAverage +{ +private: + boost::circular_buffer feeSamples; + boost::circular_buffer prioritySamples; + + template std::vector buf2vec(boost::circular_buffer buf) const + { + std::vector vec(buf.begin(), buf.end()); + return vec; + } + +public: + CBlockAverage() : feeSamples(100), prioritySamples(100) { } + + void RecordFee(const CFeeRate& feeRate) { + feeSamples.push_back(feeRate); + } + + void RecordPriority(double priority) { + prioritySamples.push_back(priority); + } + + size_t FeeSamples() const { return feeSamples.size(); } + size_t GetFeeSamples(std::vector& insertInto) const + { + BOOST_FOREACH(const CFeeRate& f, feeSamples) + insertInto.push_back(f); + return feeSamples.size(); + } + size_t PrioritySamples() const { return prioritySamples.size(); } + size_t GetPrioritySamples(std::vector& insertInto) const + { + BOOST_FOREACH(double d, prioritySamples) + insertInto.push_back(d); + return prioritySamples.size(); + } + + // Used as belt-and-suspenders check when reading to detect + // file corruption + bool AreSane(const std::vector& vecFee) + { + BOOST_FOREACH(CFeeRate fee, vecFee) + { + if (fee < CFeeRate(0)) + return false; + if (fee.GetFee(1000) > CTransaction::minRelayTxFee.GetFee(1000) * 10000) + return false; + } + return true; + } + bool AreSane(const std::vector vecPriority) + { + BOOST_FOREACH(double priority, vecPriority) + { + if (priority < 0) + return false; + } + return true; + } + + void Write(CAutoFile& fileout) const + { + std::vector vecFee = buf2vec(feeSamples); + fileout << vecFee; + std::vector vecPriority = buf2vec(prioritySamples); + fileout << vecPriority; + } + + void Read(CAutoFile& filein) { + std::vector vecFee; + filein >> vecFee; + if (AreSane(vecFee)) + feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end()); + else + throw runtime_error("Corrupt fee value in estimates file."); + std::vector vecPriority; + filein >> vecPriority; + if (AreSane(vecPriority)) + prioritySamples.insert(prioritySamples.end(), vecPriority.begin(), vecPriority.end()); + else + throw runtime_error("Corrupt priority value in estimates file."); + if (feeSamples.size() + prioritySamples.size() > 0) + LogPrint("estimatefee", "Read %d fee samples and %d priority samples\n", + feeSamples.size(), prioritySamples.size()); + } +}; + +class CMinerPolicyEstimator +{ +private: + // Records observed averages transactions that confirmed within one block, two blocks, + // three blocks etc. + std::vector history; + std::vector sortedFeeSamples; + std::vector sortedPrioritySamples; + + int nBestSeenHeight; + + // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are + // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc. + void seenTxConfirm(CFeeRate feeRate, double dPriority, int nBlocksAgo) + { + // Last entry records "everything else". + int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1); + assert(nBlocksTruncated >= 0); + + // We need to guess why the transaction was included in a block-- either + // because it is high-priority or because it has sufficient fees. + bool sufficientFee = (feeRate > CTransaction::minRelayTxFee); + bool sufficientPriority = AllowFree(dPriority); + const char* assignedTo = "unassigned"; + if (sufficientFee && !sufficientPriority) + { + history[nBlocksTruncated].RecordFee(feeRate); + assignedTo = "fee"; + } + else if (sufficientPriority && !sufficientFee) + { + history[nBlocksTruncated].RecordPriority(dPriority); + assignedTo = "priority"; + } + else + { + // Neither or both fee and priority sufficient to get confirmed: + // don't know why they got confirmed. + } + LogPrint("estimatefee", "Seen TX confirm: %s : %s fee/%g priority, took %d blocks\n", + assignedTo, feeRate.ToString(), dPriority, nBlocksAgo); + } + +public: + CMinerPolicyEstimator(int nEntries) : nBestSeenHeight(0) + { + history.resize(nEntries); + } + + void seenBlock(const std::vector& entries, int nBlockHeight) + { + if (nBlockHeight <= nBestSeenHeight) + { + // Ignore side chains and re-orgs; assuming they are random + // they don't affect the estimate. + // And if an attacker can re-org the chain at will, then + // you've got much bigger problems than "attacker can influence + // transaction fees." + return; + } + nBestSeenHeight = nBlockHeight; + + // Fill up the history buckets based on how long transactions took + // to confirm. + std::vector > entriesByConfirmations; + entriesByConfirmations.resize(history.size()); + BOOST_FOREACH(const CTxMemPoolEntry& entry, entries) + { + // How many blocks did it take for miners to include this transaction? + int delta = nBlockHeight - entry.GetHeight(); + if (delta <= 0) + { + // Re-org made us lose height, this should only happen if we happen + // to re-org on a difficulty transition point: very rare! + continue; + } + if ((delta-1) >= (int)history.size()) + delta = history.size(); // Last bucket is catch-all + entriesByConfirmations[delta-1].push_back(&entry); + } + for (size_t i = 0; i < entriesByConfirmations.size(); i++) + { + std::vector &e = entriesByConfirmations.at(i); + // Insert at most 10 random entries per bucket, otherwise a single block + // can dominate an estimate: + if (e.size() > 10) { + std::random_shuffle(e.begin(), e.end()); + e.resize(10); + } + BOOST_FOREACH(const CTxMemPoolEntry* entry, e) + { + // Fees are stored and reported as BTC-per-kb: + CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); + double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN + seenTxConfirm(feeRate, dPriority, i); + } + } + for (size_t i = 0; i < history.size(); i++) { + if (history[i].FeeSamples() + history[i].PrioritySamples() > 0) + LogPrint("estimatefee", "estimates: for confirming within %d blocks based on %d/%d samples, fee=%s, prio=%g\n", + i, + history[i].FeeSamples(), history[i].PrioritySamples(), + estimateFee(i+1).ToString(), estimatePriority(i+1)); + } + sortedFeeSamples.clear(); + sortedPrioritySamples.clear(); + } + + // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based. + CFeeRate estimateFee(int nBlocksToConfirm) + { + nBlocksToConfirm--; + + if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size()) + return CFeeRate(0); + + if (sortedFeeSamples.size() == 0) + { + for (size_t i = 0; i < history.size(); i++) + history.at(i).GetFeeSamples(sortedFeeSamples); + std::sort(sortedFeeSamples.begin(), sortedFeeSamples.end(), + std::greater()); + } + if (sortedFeeSamples.size() == 0) + return CFeeRate(0); + + int nBucketSize = history.at(nBlocksToConfirm).FeeSamples(); + + // Estimates should not increase as number of confirmations goes up, + // but the estimates are noisy because confirmations happen discretely + // in blocks. To smooth out the estimates, use all samples in the history + // and use the nth highest where n is (number of samples in previous bucket + + // half the samples in nBlocksToConfirm bucket): + size_t nPrevSize = 0; + for (int i = 0; i < nBlocksToConfirm; i++) + nPrevSize += history.at(i).FeeSamples(); + size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1); + return sortedFeeSamples[index]; + } + double estimatePriority(int nBlocksToConfirm) + { + nBlocksToConfirm--; + + if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size()) + return -1; + + if (sortedPrioritySamples.size() == 0) + { + for (size_t i = 0; i < history.size(); i++) + history.at(i).GetPrioritySamples(sortedPrioritySamples); + std::sort(sortedPrioritySamples.begin(), sortedPrioritySamples.end(), + std::greater()); + } + if (sortedPrioritySamples.size() == 0) + return -1.0; + + int nBucketSize = history.at(nBlocksToConfirm).PrioritySamples(); + + // Estimates should not increase as number of confirmations needed goes up, + // but the estimates are noisy because confirmations happen discretely + // in blocks. To smooth out the estimates, use all samples in the history + // and use the nth highest where n is (number of samples in previous buckets + + // half the samples in nBlocksToConfirm bucket). + size_t nPrevSize = 0; + for (int i = 0; i < nBlocksToConfirm; i++) + nPrevSize += history.at(i).PrioritySamples(); + size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1); + return sortedPrioritySamples[index]; + } + + void Write(CAutoFile& fileout) const + { + fileout << nBestSeenHeight; + fileout << history.size(); + BOOST_FOREACH(const CBlockAverage& entry, history) + { + entry.Write(fileout); + } + } + + void Read(CAutoFile& filein) + { + filein >> nBestSeenHeight; + size_t numEntries; + filein >> numEntries; + history.clear(); + for (size_t i = 0; i < numEntries; i++) + { + CBlockAverage entry; + entry.Read(filein); + history.push_back(entry); + } + } +}; + + CTxMemPool::CTxMemPool() { // Sanity checks off by default for performance, because otherwise // accepting transactions becomes O(N^2) where N is the number // of transactions in the pool fSanityCheck = false; + + // 25 blocks is a compromise between using a lot of disk/memory and + // trying to give accurate estimates to people who might be willing + // to wait a day or two to save a fraction of a penny in fees. + // Confirmation times for very-low-fee transactions that take more + // than an hour or three to confirm are highly variable. + minerPolicyEstimator = new CMinerPolicyEstimator(25); +} + +CTxMemPool::~CTxMemPool() +{ + delete minerPolicyEstimator; } void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins) @@ -128,6 +429,28 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list } } +// Called when a block is connected. Removes from mempool and updates the miner fee estimator. +void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, + std::list& conflicts) +{ + LOCK(cs); + std::vector entries; + BOOST_FOREACH(const CTransaction& tx, vtx) + { + uint256 hash = tx.GetHash(); + if (mapTx.count(hash)) + entries.push_back(mapTx[hash]); + } + minerPolicyEstimator->seenBlock(entries, nBlockHeight); + BOOST_FOREACH(const CTransaction& tx, vtx) + { + std::list dummy; + remove(tx, dummy, false); + removeConflicts(tx, conflicts); + } +} + + void CTxMemPool::clear() { LOCK(cs); @@ -195,6 +518,53 @@ bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const return true; } +CFeeRate CTxMemPool::estimateFee(int nBlocks) const +{ + LOCK(cs); + return minerPolicyEstimator->estimateFee(nBlocks); +} +double CTxMemPool::estimatePriority(int nBlocks) const +{ + LOCK(cs); + return minerPolicyEstimator->estimatePriority(nBlocks); +} + +bool +CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const +{ + try { + LOCK(cs); + fileout << 99900; // version required to read: 0.9.99 or later + fileout << CLIENT_VERSION; // version that wrote the file + minerPolicyEstimator->Write(fileout); + } + catch (std::exception &e) { + LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)"); + return false; + } + return true; +} + +bool +CTxMemPool::ReadFeeEstimates(CAutoFile& filein) +{ + try { + int nVersionRequired, nVersionThatWrote; + filein >> nVersionRequired >> nVersionThatWrote; + if (nVersionRequired > CLIENT_VERSION) + return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired); + + LOCK(cs); + minerPolicyEstimator->Read(filein); + } + catch (std::exception &e) { + LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)"); + return false; + } + return true; +} + + CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) { diff --git a/src/txmempool.h b/src/txmempool.h index 4509e95778..b2915aa842 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -11,6 +11,13 @@ #include "core.h" #include "sync.h" +inline bool AllowFree(double dPriority) +{ + // Large (in bytes) low-priority (new, small-coin) transactions + // need a fee. + return dPriority > COIN * 144 / 250; +} + /** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */ static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF; @@ -41,6 +48,8 @@ public: unsigned int GetHeight() const { return nHeight; } }; +class CMinerPolicyEstimator; + /* * CTxMemPool stores valid-according-to-the-current-best-chain * transactions that may be included in the next block. @@ -56,6 +65,7 @@ class CTxMemPool private: bool fSanityCheck; // Normally false, true if -checkmempool or -regtest unsigned int nTransactionsUpdated; + CMinerPolicyEstimator* minerPolicyEstimator; public: mutable CCriticalSection cs; @@ -63,6 +73,7 @@ public: std::map mapNextTx; CTxMemPool(); + ~CTxMemPool(); /* * If sanity-checking is turned on, check makes sure the pool is @@ -76,6 +87,8 @@ public: bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry); void remove(const CTransaction &tx, std::list& removed, bool fRecursive = false); void removeConflicts(const CTransaction &tx, std::list& removed); + void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, + std::list& conflicts); void clear(); void queryHashes(std::vector& vtxid); void pruneSpent(const uint256& hash, CCoins &coins); @@ -95,6 +108,16 @@ public: } bool lookup(uint256 hash, CTransaction& result) const; + + // Estimate fee rate needed to get into the next + // nBlocks + CFeeRate estimateFee(int nBlocks) const; + // Estimate priority needed to get into the next + // nBlocks + double estimatePriority(int nBlocks) const; + // Write/Read estimates to disk + bool WriteFeeEstimates(CAutoFile& fileout) const; + bool ReadFeeEstimates(CAutoFile& filein); }; /** CCoinsView that brings transactions from a memorypool into view. From db41541bc2e679a5c98ab380837c985e0252ab43 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 6 Jun 2014 19:28:34 +0200 Subject: [PATCH 146/336] qt: Periodic translation update --- src/qt/locale/bitcoin_el_GR.ts | 147 +++++++++++++++++---------------- src/qt/locale/bitcoin_sl_SI.ts | 38 +++++---- src/qt/locale/bitcoin_th_TH.ts | 96 ++++++++++----------- 3 files changed, 142 insertions(+), 139 deletions(-) diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index 687947e3b9..e957a0088e 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -3,11 +3,11 @@ AboutDialog About Bitcoin Core - + Σχετικά με το Bitcoin Core <b>Bitcoin Core</b> version - + <b>Bitcoin Core</b> έκδοση @@ -29,11 +29,11 @@ This product includes software developed by the OpenSSL Project for use in the O The Bitcoin Core developers - + Οι προγραμματιστές του Bitcoin Core (%1-bit) - + (%1-bit) @@ -128,11 +128,11 @@ This product includes software developed by the OpenSSL Project for use in the O Exporting Failed - + Η εξαγωγή απέτυχε There was an error trying to save the address list to %1. - + Παρουσιάστηκε σφάλμα κατά την αποθήκευση της λίστας πορτοφολιών στο %1. @@ -438,7 +438,7 @@ This product includes software developed by the OpenSSL Project for use in the O &About Bitcoin Core - + &Σχετικά με το Bitcoin Core Show the list of used sending addresses and labels @@ -494,11 +494,11 @@ This product includes software developed by the OpenSSL Project for use in the O %1 and %2 - + %1 και %2 %n year(s) - + %n έτος%n έτη %1 behind @@ -608,11 +608,11 @@ Address: %4 Change: - + Ρέστα: (un)select all - + (από)επιλογή όλων Tree mode @@ -672,7 +672,7 @@ Address: %4 Copy quantity - + Αντιγραφή ποσότητας Copy fee @@ -684,11 +684,11 @@ Address: %4 Copy bytes - + Αντιγραφή των byte Copy priority - + Αντιγραφή προτεραιότητας Copy low output @@ -696,51 +696,51 @@ Address: %4 Copy change - + Αντιγραφή των ρέστων highest - + ύψιστη higher - + υψηλότερη high - + ψηλή medium-high - + μεσαία-ψηλή medium - + μεσαία low-medium - + μεσαία-χαμηλή low - + χαμηλή lower - + χαμηλότερη lowest - + χαμηλότατη (%1 locked) - + (%1 κλειδωμένο) none - + κανένα Dust @@ -796,11 +796,12 @@ Address: %4 change from %1 (%2) - + ρέστα από %1 (%2) (change) - + (ρέστα) + @@ -815,7 +816,7 @@ Address: %4 The label associated with this address list entry - + Η ετικέτα που συνδέεται με αυτήν την καταχώρηση στο βιβλίο διευθύνσεων The address associated with this address list entry. This can only be modified for sending addresses. @@ -936,11 +937,11 @@ Address: %4 Welcome to Bitcoin Core. - + Καλώς ήρθατε στο Bitcoin Core. As this is the first time the program is launched, you can choose where Bitcoin Core will store its data. - + Καθώς αυτή είναι η πρώτη φορά που εκκινείται το πρόγραμμα, μπορείτε να διαλέξετε πού θα αποθηκεύει το Bitcoin Core τα δεδομένα του. Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory. @@ -1030,7 +1031,7 @@ Address: %4 MB - + MB Number of script &verification threads @@ -1082,7 +1083,7 @@ Address: %4 Expert - + Έμπειρος Enable coin &control features @@ -1190,7 +1191,7 @@ Address: %4 none - + κανένα Confirm options reset @@ -1198,7 +1199,7 @@ Address: %4 Client restart required to activate changes. - + Χρειάζεται επανεκκίνηση του προγράμματος για να ενεργοποιηθούν οι αλλαγές. Client will be shutdown, do you want to proceed? @@ -1229,7 +1230,7 @@ Address: %4 Available: - + Διαθέσιμο: Your current spendable balance @@ -1370,11 +1371,11 @@ Address: %4 QRImageWidget &Save Image... - + &Αποθήκευση εικόνας... &Copy Image - + &Αντιγραφή εικόνας Save QR Code @@ -1409,7 +1410,7 @@ Address: %4 General - + Γενικά Using OpenSSL version @@ -1425,7 +1426,7 @@ Address: %4 Name - + Όνομα Number of connections @@ -1457,11 +1458,11 @@ Address: %4 &Network Traffic - + &Κίνηση δικτύου &Clear - + &Εκκαθάριση Totals @@ -1536,7 +1537,7 @@ Address: %4 ReceiveCoinsDialog &Amount: - + &Ποσό: &Label: @@ -1544,7 +1545,7 @@ Address: %4 &Message: - + &Μήνυμα: Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before. @@ -1584,7 +1585,7 @@ Address: %4 &Request payment - + &Αίτηση πληρωμής Show the selected request (does the same as double clicking an entry) @@ -1608,7 +1609,7 @@ Address: %4 Copy message - + Αντιγραφή μηνύματος Copy amount @@ -1631,7 +1632,7 @@ Address: %4 &Save Image... - + &Αποθήκευση εικόνας... Request payment to %1 @@ -1698,7 +1699,7 @@ Address: %4 (no amount) - + (κανένα ποσό) @@ -1717,7 +1718,7 @@ Address: %4 automatically selected - + επιλεγμένο αυτόματα Insufficient funds! @@ -1753,7 +1754,7 @@ Address: %4 Change: - + Ρέστα: If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. @@ -1801,7 +1802,7 @@ Address: %4 Copy quantity - + Αντιγραφή ποσότητας Copy amount @@ -1817,11 +1818,11 @@ Address: %4 Copy bytes - + Αντιγραφή των byte Copy priority - + Αντιγραφή προτεραιότητας Copy low output @@ -1829,15 +1830,15 @@ Address: %4 Copy change - + Αντιγραφή των ρέστων Total Amount %1 (= %2) - + Ολικό Ποσό %1 (= %2) or - + ή The recipient address is not valid, please recheck. @@ -1940,7 +1941,7 @@ Address: %4 Remove this entry - + Αφαίρεση αυτής της καταχώρησης Message: @@ -1975,11 +1976,11 @@ Address: %4 ShutdownWindow Bitcoin Core is shutting down... - + Το Bitcoin Core τερματίζεται... Do not shut down the computer until this window disappears. - + Μην απενεργοποιήσετε τον υπολογιστή μέχρι να κλείσει αυτό το παράθυρο. @@ -2133,7 +2134,7 @@ Address: %4 The Bitcoin Core developers - + Οι προγραμματιστές του Bitcoin Core [testnet] @@ -2341,11 +2342,11 @@ Address: %4 Offline - + Offline Unconfirmed - + Ανεπιβεβαίωτες Confirming (%1 of %2 recommended confirmations) @@ -2484,19 +2485,19 @@ Address: %4 Export Transaction History - + Εξαγωγή Ιστορικού Συναλλαγών Exporting Failed - + Η Εξαγωγή Απέτυχε There was an error trying to save the transaction history to %1. - + Yπήρξε σφάλμα κατά την προσπάθεια αποθήκευσης του ιστορικού συναλλαγών στο %1. Exporting Successful - + Επιτυχής εξαγωγή The transaction history was successfully saved to %1. @@ -2547,7 +2548,7 @@ Address: %4 WalletFrame No wallet has been loaded. - + Δεν έχει φορτωθεί πορτοφόλι @@ -2585,7 +2586,7 @@ Address: %4 The wallet data was successfully saved to %1. - + Τα δεδομένα πορτοφολιού αποθηκεύτηκαν με επιτυχία στο %1. Backup Successful @@ -2801,11 +2802,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. (default: 1) - + (προεπιλογή: 1) (default: wallet.dat) - + (προεπιλογή: wallet.dat) <category> can be: @@ -2841,7 +2842,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Connection options: - + Επιλογές σύνδεσης: Corrupted block database detected @@ -3045,7 +3046,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Wallet options: - + Επιλογές πορτοφολιού: Warning: Deprecated argument -debugnet ignored, use -debug=net @@ -3229,7 +3230,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. on startup - + κατά την εκκίνηση version diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index 1a46c6ae6c..2ad31e911b 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -344,7 +344,7 @@ This product includes software developed by the OpenSSL Project for use in the O Modify configuration options for Bitcoin - + Spremeni konfiguracijo nastavitev za Bitcoin Backup wallet to another location @@ -1144,7 +1144,7 @@ Naslov: %4 User Interface &language: - + Vmesnik uporabnika &jezik: The user interface language can be set here. This setting will take effect after restarting Bitcoin. @@ -1487,11 +1487,11 @@ Naslov: %4 Welcome to the Bitcoin RPC console. - + Dobrodošli na Bitcoin RPC konzoli. Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen. - + Uporabi puščice za gor in dol za navigacijo po zgodovini in <b>Ctrl-L</b> za izbris izpisa na ekranu. Type <b>help</b> for an overview of available commands. @@ -1847,7 +1847,7 @@ Naslov: %4 The total exceeds your balance when the %1 transaction fee is included. - + Celotni znesek presega vaše stanje, ko je zaračunana 1% provizija. Duplicate address found, can only send to each address once per send operation. @@ -2626,7 +2626,7 @@ Naslov: %4 Connect to a node to retrieve peer addresses, and disconnect - + Povežite se z vozliščem za pridobitev naslovov uporabnikov in nato prekinite povezavo. Specify your own public address @@ -2638,7 +2638,7 @@ Naslov: %4 Number of seconds to keep misbehaving peers from reconnecting (default: 86400) - + Število sekund za težavo pri vzpostavitvi povezave med uporabniki (privzeto: 86400) An error occurred while setting up the RPC port %u for listening on IPv4: %s @@ -3268,11 +3268,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Unable to bind to %s on this computer (bind returned error %d, %s) - + Nemogoče je povezati s/z %s na tem računalniku (povezava je vrnila napaka %d, %s) Allow DNS lookups for -addnode, -seednode and -connect - + Omogoči DNS poizvedbe za -addnode, -seednode in -connect. Loading addresses... @@ -3296,27 +3296,27 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Invalid -proxy address: '%s' - + Neveljaven -proxy naslov: '%s' Unknown network specified in -onlynet: '%s' - + Neznano omrežje določeno v -onlynet: '%s'. Unknown -socks proxy version requested: %i - + Neznano -socks zahtevan zastopnik različice: %i Cannot resolve -bind address: '%s' - + Nemogoče rešiti -bind naslova: '%s' Cannot resolve -externalip address: '%s' - + Nemogoče rešiti -externalip naslova: '%s' Invalid amount for -paytxfee=<amount>: '%s' - + Neveljavna količina za -paytxfee=<amount>: '%s' Invalid amount @@ -3344,7 +3344,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. Cannot write default address - + Ni mogoče zapisati privzetega naslova Rescanning... @@ -3356,7 +3356,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. To use the %s option - + Za uporabo %s opcije Error @@ -3366,7 +3366,9 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. You must set rpcpassword=<password> in the configuration file: %s If the file does not exist, create it with owner-readable-only file permissions. - + Potrebno je nastaviti rpcpassword=<password> v nastavitveni datoteki: +%s +Če datoteka ne obstaja jo ustvarite z dovoljenjem, da jo lahko bere samo uporabnik. \ No newline at end of file diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index 96c49b12d0..54e15a75e0 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -35,7 +35,7 @@ This product includes software developed by the OpenSSL Project for use in the O AddressBookPage Double-click to edit address or label - ดับเบิลคลิก เพื่อแก้ไขที่อยู่ หรือชื่อ + ดับเบิ้ลคลิก เพื่อแก้ไขที่อยู่ หรือชื่อ Create a new address @@ -75,7 +75,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Delete - ลบ + &ลบ Choose the address to send coins to @@ -119,7 +119,7 @@ This product includes software developed by the OpenSSL Project for use in the O Comma separated file (*.csv) - + คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) Exporting Failed @@ -165,7 +165,7 @@ This product includes software developed by the OpenSSL Project for use in the O Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>10 or more random characters</b>, or <b>eight or more words</b>. - + ใส่รหัสผ่านใหม่ให้กับกระเป๋าเงิน. <br/> กรุณาใช้รหัสผ่านของ <b> 10 หรือแบบสุ่มมากกว่าตัวอักษร </ b> หรือ <b> แปดหรือมากกว่าคำ </ b> Encrypt wallet @@ -173,7 +173,7 @@ This product includes software developed by the OpenSSL Project for use in the O This operation needs your wallet passphrase to unlock the wallet. - + การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณเพื่อปลดล็อคกระเป๋าเงิน Unlock wallet @@ -181,7 +181,7 @@ This product includes software developed by the OpenSSL Project for use in the O This operation needs your wallet passphrase to decrypt the wallet. - + การดำเนินการนี้ต้องมีรหัสผ่านกระเป๋าเงินของคุณในการถอดรหัสกระเป๋าเงิน Decrypt wallet @@ -229,7 +229,7 @@ This product includes software developed by the OpenSSL Project for use in the O Wallet encryption failed due to an internal error. Your wallet was not encrypted. - + กระเป๋าเงินเข้ารหัสล้มเหลวเนื่องจากข้อผิดพลาดภายใน กระเป๋าเงินของคุณไม่ได้เข้ารหัส The supplied passphrases do not match. @@ -237,15 +237,15 @@ This product includes software developed by the OpenSSL Project for use in the O Wallet unlock failed - + ปลดล็อคกระเป๋าเงินล้มเหลว The passphrase entered for the wallet decryption was incorrect. - + ป้อนรหัสผ่านสำหรับการถอดรหัสกระเป๋าเงินไม่ถูกต้อง Wallet decryption failed - + ถอดรหัสกระเป๋าเงินล้มเหลว Wallet passphrase was successfully changed. @@ -260,11 +260,11 @@ This product includes software developed by the OpenSSL Project for use in the O Synchronizing with network... - + กำลังทำข้อมูลให้ตรงกันกับเครือข่าย ... &Overview - + &ภาพรวม Node @@ -272,15 +272,15 @@ This product includes software developed by the OpenSSL Project for use in the O Show general overview of wallet - + แสดงภาพรวมทั่วไปของกระเป๋าเงิน &Transactions - + &การทำรายการ Browse transaction history - + เรียกดูประวัติการทำธุรกรรม E&xit @@ -288,11 +288,11 @@ This product includes software developed by the OpenSSL Project for use in the O Quit application - + ออกจากโปรแกรม Show information about Bitcoin - + แสดงข้อมูลเกี่ยวกับ Bitcoin About &Qt @@ -304,7 +304,7 @@ This product includes software developed by the OpenSSL Project for use in the O &Options... - + &ตัวเลือก... &Encrypt Wallet... @@ -352,7 +352,7 @@ This product includes software developed by the OpenSSL Project for use in the O Change the passphrase used for wallet encryption - + เปลี่ยนรหัสผ่านที่ใช้สำหรับการเข้ารหัสกระเป๋าเงิน &Debug window @@ -404,23 +404,23 @@ This product includes software developed by the OpenSSL Project for use in the O &File - + &ไฟล์ &Settings - + &การตั้งค่า &Help - + &ช่วยเหลือ Tabs toolbar - + แถบเครื่องมือ [testnet] - + [testnet] Bitcoin Core @@ -460,7 +460,7 @@ This product includes software developed by the OpenSSL Project for use in the O %n active connection(s) to Bitcoin network - + %n ที่ใช้งานการเชื่อมต่อกับเครือข่าย Bitcoin No block source available... @@ -520,19 +520,19 @@ This product includes software developed by the OpenSSL Project for use in the O Up to date - + ทันสมัย Catching up... - + จับได้... Sent transaction - + รายการที่ส่ง Incoming transaction - + การทำรายการขาเข้า Date: %1 @@ -544,11 +544,11 @@ Address: %4 Wallet is <b>encrypted</b> and currently <b>unlocked</b> - + ระเป๋าเงินถูก <b>เข้ารหัส</b> และในขณะนี้ <b>ปลดล็อคแล้ว</b> Wallet is <b>encrypted</b> and currently <b>locked</b> - + กระเป๋าเงินถูก <b>เข้ารหัส</b> และในปัจจุบัน <b>ล็อค </b> A fatal error occurred. Bitcoin can no longer continue safely and will quit. @@ -797,11 +797,11 @@ Address: %4 EditAddressDialog Edit Address - + แก้ไขที่อยู่ &Label - + &ชื่อ The label associated with this address list entry @@ -813,27 +813,27 @@ Address: %4 &Address - + &ที่อยู่ New receiving address - + ที่อยู่ผู้รับใหม่ New sending address - + ที่อยู่ผู้ส่งใหม่ Edit receiving address - + แก้ไขที่อยู่ผู้รับ Edit sending address - + แก้ไขที่อยู่ผู้ส่ง The entered address "%1" is already in the address book. - + ป้อนที่อยู่ "%1" ที่มีอยู่แล้วในสมุดที่อยู่ The entered address "%1" is not a valid Bitcoin address. @@ -841,11 +841,11 @@ Address: %4 Could not unlock wallet. - + ไม่สามารถปลดล็อคกระเป๋าเงิน New key generation failed. - + สร้างกุญแจใหม่ล้มเหลว @@ -992,7 +992,7 @@ Address: %4 OptionsDialog Options - + ตัวเลือก &Main @@ -1207,7 +1207,7 @@ Address: %4 OverviewPage Form - + รูป The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. @@ -1251,7 +1251,7 @@ Address: %4 <b>Recent transactions</b> - + <b>รายการทำธุรกรรมล่าสุด</b> out of sync @@ -1695,7 +1695,7 @@ Address: %4 SendCoinsDialog Send Coins - + ส่งเหรียญ Coin Control Features @@ -2127,7 +2127,7 @@ Address: %4 [testnet] - + [testnet] @@ -2494,7 +2494,7 @@ Address: %4 Comma separated file (*.csv) - + คั่นไฟล์ด้วยเครื่องหมายจุลภาค (*.csv) Confirmed @@ -2544,7 +2544,7 @@ Address: %4 WalletModel Send Coins - + ส่งเหรียญ From dff0e3b9152e66ae569c4f45608677eee11e5351 Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Sat, 7 Jun 2014 01:22:08 +0200 Subject: [PATCH 147/336] [Qt] Improve rpc console history behavior --- src/qt/rpcconsole.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 0d3e11f4ac..199050cc57 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -415,8 +415,8 @@ void RPCConsole::on_lineEdit_returnPressed() { message(CMD_REQUEST, cmd); emit cmdRequest(cmd); - // Truncate history from current position - history.erase(history.begin() + historyPtr, history.end()); + // Remove command, if already in history + history.removeOne(cmd); // Append command to history history.append(cmd); // Enforce maximum history size From 02bec4b268fa32153f26a5f4c089d4f92d887186 Mon Sep 17 00:00:00 2001 From: Drak Date: Sat, 7 Jun 2014 12:57:58 +0100 Subject: [PATCH 148/336] Fix compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following compiler warning ``` miner.cpp: In constructor ‘COrphan::COrphan(const CTransaction*)’: miner.cpp:69:14: warning: ‘COrphan::feeRate’ will be initialized after [-Wreorder] CFeeRate feeRate; ^ miner.cpp:68:12: warning: ‘double COrphan::dPriority’ [-Wreorder] double dPriority; ^ miner.cpp:71:5: warning: when initialized here [-Wreorder] COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) ``` --- src/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 4e131c088b..ddd277a9bb 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -65,8 +65,8 @@ class COrphan public: const CTransaction* ptx; set setDependsOn; - double dPriority; CFeeRate feeRate; + double dPriority; COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) { From 95a93836d8ab3e5f2412503dfafdf54db4f8c1ee Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Sun, 8 Jun 2014 01:05:53 +0200 Subject: [PATCH 149/336] [Qt] Remove CENT-fee-rule from coin control completely --- src/qt/coincontroldialog.cpp | 24 ++++++------------------ src/qt/forms/coincontroldialog.ui | 2 +- src/qt/forms/sendcoinsdialog.ui | 2 +- src/qt/sendcoinsdialog.cpp | 4 ++-- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index e27f1bff97..42d6da7d37 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -71,7 +71,7 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) : QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); - QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this); + QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(clipboardQuantity())); @@ -309,7 +309,7 @@ void CoinControlDialog::clipboardPriority() GUIUtil::setClipboard(ui->labelCoinControlPriority->text()); } -// copy label "Low output" to clipboard +// copy label "Dust" to clipboard void CoinControlDialog::clipboardLowOutput() { GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text()); @@ -439,7 +439,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // nPayAmount qint64 nPayAmount = 0; - bool fLowOutput = false; bool fDust = false; CTransaction txDummy; foreach(const qint64 &amount, CoinControlDialog::payAmounts) @@ -448,9 +447,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (amount > 0) { - if (amount < CENT) - fLowOutput = true; - CTxOut txout(amount, (CScript)vector(24, 0)); txDummy.vout.push_back(txout); if (txout.IsDust(CTransaction::minRelayTxFee)) @@ -571,7 +567,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QLabel *l7 = dialog->findChild("labelCoinControlLowOutput"); QLabel *l8 = dialog->findChild("labelCoinControlChange"); - // enable/disable "low output" and "change" + // enable/disable "dust" and "change" dialog->findChild("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0); dialog->findChild("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0); dialog->findChild("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0); @@ -584,14 +580,13 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes l6->setText(sPriorityLabel); // Priority - l7->setText((fLowOutput ? (fDust ? tr("Dust") : tr("yes")) : tr("no"))); // Low Output / Dust + l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change // turn labels "red" l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000 l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium" - l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes" - l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC + l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes" // tool tips QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "

"; @@ -602,21 +597,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "

"; toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())); - QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "

"; - toolTip3 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "

"; - toolTip3 += tr("Amounts below 0.546 times the minimum relay fee are shown as dust."); - - QString toolTip4 = tr("This label turns red, if the change is smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)) + "

"; - toolTip4 += tr("This means a fee of at least %1 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())); + QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546))); l5->setToolTip(toolTip1); l6->setToolTip(toolTip2); l7->setToolTip(toolTip3); - l8->setToolTip(toolTip4); dialog->findChild("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); dialog->findChild("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); dialog->findChild("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); - dialog->findChild("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); // Insufficient funds QLabel *label = dialog->findChild("labelCoinControlInsuffFunds"); diff --git a/src/qt/forms/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui index cd1c0ffa18..67ea3a9d8c 100644 --- a/src/qt/forms/coincontroldialog.ui +++ b/src/qt/forms/coincontroldialog.ui @@ -225,7 +225,7 @@
- Low Output: + Dust: diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 4cb1670c79..a631b04670 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -417,7 +417,7 @@ - Low Output: + Dust: diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 23b8ef83e2..b7d74d7039 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -53,7 +53,7 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) : QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); - QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this); + QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity())); connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount())); @@ -478,7 +478,7 @@ void SendCoinsDialog::coinControlClipboardPriority() GUIUtil::setClipboard(ui->labelCoinControlPriority->text()); } -// Coin Control: copy label "Low output" to clipboard +// Coin Control: copy label "Dust" to clipboard void SendCoinsDialog::coinControlClipboardLowOutput() { GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text()); From 16be392975c5c74425821688a8051433cd34b126 Mon Sep 17 00:00:00 2001 From: sandakersmann Date: Sun, 8 Jun 2014 17:37:53 +0200 Subject: [PATCH 150/336] Update translation_process.md Qt changed to Bitcoin Core --- doc/translation_process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/translation_process.md b/doc/translation_process.md index 2f0845a877..61a0a0ffed 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -1,7 +1,7 @@ Translations ============ -The Qt GUI can be easily translated into other languages. Here's how we +The Bitcoin Core GUI can be easily translated into other languages. Here's how we handle those translations. Files and Folders From 7a9e0b6460037b72376af293dc87acafe4fca831 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 9 Jun 2014 01:27:56 +0200 Subject: [PATCH 151/336] Move checkpoint based heuristic checks to AcceptBlockHeader --- src/main.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 429473d8f8..cf8c436ded 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2329,28 +2329,6 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"), REJECT_INVALID, "time-too-new"); - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); - if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) - { - // Extra checks to prevent "fill up memory by spamming with bogus blocks" - int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime; - if (deltaTime < 0) - { - return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), - REJECT_CHECKPOINT, "time-too-old"); - } - bool fOverflow = false; - uint256 bnNewBlock; - bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow); - uint256 bnRequired; - bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); - if (fOverflow || bnNewBlock > bnRequired) - { - return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), - REJECT_INVALID, "bad-diffbits"); - } - } - return true; } @@ -2426,6 +2404,28 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); } + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime; + if (deltaTime < 0) + { + return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), + REJECT_CHECKPOINT, "time-too-old"); + } + bool fOverflow = false; + uint256 bnNewBlock; + bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow); + uint256 bnRequired; + bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); + if (fOverflow || bnNewBlock > bnRequired) + { + return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), + REJECT_INVALID, "bad-diffbits"); + } + } + // Get prev block index CBlockIndex* pindexPrev = NULL; int nHeight = 0; From 77339e5aec4da99f727b80829f9697357b4cec45 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 6 May 2014 00:54:10 +0200 Subject: [PATCH 152/336] Get rid of the static chainMostWork (optimization) --- src/main.cpp | 56 +++++++++++++++++++++++++--------------------------- src/main.h | 6 +++--- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 429473d8f8..806f1c20db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,6 @@ CTxMemPool mempool; map mapBlockIndex; CChain chainActive; -CChain chainMostWork; int64_t nTimeBestReceived = 0; int nScriptCheckThreads = 0; bool fImporting = false; @@ -398,6 +397,12 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const { return Genesis(); } +CBlockIndex *CChain::FindFork(CBlockIndex *pindex) const { + while (pindex && !Contains(pindex)) + pindex = pindex->pprev; + return pindex; +} + CCoinsViewCache *pcoinsTip = NULL; CBlockTreeDB *pblocktree = NULL; @@ -2035,23 +2040,17 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) { return true; } -// Make chainMostWork correspond to the chain with the most work in it, that isn't +// Return the tip of the chain with the most work in it, that isn't // known to be invalid (it's however far from certain to be valid). -void static FindMostWorkChain() { - CBlockIndex *pindexNew = NULL; - - // In case the current best is invalid, do not consider it. - while (chainMostWork.Tip() && (chainMostWork.Tip()->nStatus & BLOCK_FAILED_MASK)) { - setBlockIndexValid.erase(chainMostWork.Tip()); - chainMostWork.SetTip(chainMostWork.Tip()->pprev); - } - +static CBlockIndex* FindMostWorkChain() { do { + CBlockIndex *pindexNew = NULL; + // Find the best candidate header. { std::set::reverse_iterator it = setBlockIndexValid.rbegin(); if (it == setBlockIndexValid.rend()) - return; + return NULL; pindexNew = *it; } @@ -2075,18 +2074,9 @@ void static FindMostWorkChain() { } pindexTest = pindexTest->pprev; } - if (fInvalidAncestor) - continue; - - break; + if (!fInvalidAncestor) + return pindexNew; } while(true); - - // Check whether it's actually an improvement. - if (chainMostWork.Tip() && !CBlockIndexWorkComparator()(chainMostWork.Tip(), pindexNew)) - return; - - // We have a new best. - chainMostWork.SetTip(pindexNew); } // Try to activate to the most-work chain (thereby connecting it). @@ -2095,26 +2085,34 @@ bool ActivateBestChain(CValidationState &state) { CBlockIndex *pindexOldTip = chainActive.Tip(); bool fComplete = false; while (!fComplete) { - FindMostWorkChain(); + CBlockIndex *pindexMostWork = FindMostWorkChain(); + CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); fComplete = true; // Check whether we have something to do. - if (chainMostWork.Tip() == NULL) break; + if (pindexMostWork == NULL) break; // Disconnect active blocks which are no longer in the best chain. - while (chainActive.Tip() && !chainMostWork.Contains(chainActive.Tip())) { + while (chainActive.Tip() && chainActive.Tip() != pindexFork) { if (!DisconnectTip(state)) return false; } + // Build list of new blocks to connect. + std::vector vpindexToConnect; + vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); + while (pindexMostWork && pindexMostWork != pindexFork) { + vpindexToConnect.push_back(pindexMostWork); + pindexMostWork = pindexMostWork->pprev; + } + // Connect new blocks. - while (!chainActive.Contains(chainMostWork.Tip())) { - CBlockIndex *pindexConnect = chainMostWork[chainActive.Height() + 1]; + BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { if (!ConnectTip(state, pindexConnect)) { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) - InvalidChainFound(chainMostWork.Tip()); + InvalidChainFound(vpindexToConnect.back()); fComplete = false; state = CValidationState(); break; diff --git a/src/main.h b/src/main.h index 23c8660376..98155989a3 100644 --- a/src/main.h +++ b/src/main.h @@ -1079,14 +1079,14 @@ public: /** Find the last common block between this chain and a locator. */ CBlockIndex *FindFork(const CBlockLocator &locator) const; + + /** Find the last common block between this chain and a block index entry. */ + CBlockIndex *FindFork(CBlockIndex *pindex) const; }; /** The currently-connected chain of blocks. */ extern CChain chainActive; -/** The currently best known chain of headers (some of which may be invalid). */ -extern CChain chainMostWork; - /** Global variable that points to the active CCoinsView (protected by cs_main) */ extern CCoinsViewCache *pcoinsTip; From 4e0eed88acdd41826868c151373068bfad18b84d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 6 May 2014 01:23:13 +0200 Subject: [PATCH 153/336] Allow ActivateBestChain to release its lock on cs_main --- src/main.cpp | 92 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 806f1c20db..860487dece 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2079,47 +2079,43 @@ static CBlockIndex* FindMostWorkChain() { } while(true); } -// Try to activate to the most-work chain (thereby connecting it). -bool ActivateBestChain(CValidationState &state) { - LOCK(cs_main); +// Try to make some progress towards making pindexMostWork the active block. +static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) { + AssertLockHeld(cs_main); CBlockIndex *pindexOldTip = chainActive.Tip(); - bool fComplete = false; - while (!fComplete) { - CBlockIndex *pindexMostWork = FindMostWorkChain(); - CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); - fComplete = true; + CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); - // Check whether we have something to do. - if (pindexMostWork == NULL) break; + // Disconnect active blocks which are no longer in the best chain. + while (chainActive.Tip() && chainActive.Tip() != pindexFork) { + if (!DisconnectTip(state)) + return false; + } - // Disconnect active blocks which are no longer in the best chain. - while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state)) + // Build list of new blocks to connect. + std::vector vpindexToConnect; + vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); + while (pindexMostWork && pindexMostWork != pindexFork) { + vpindexToConnect.push_back(pindexMostWork); + pindexMostWork = pindexMostWork->pprev; + } + + // Connect new blocks. + BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { + if (!ConnectTip(state, pindexConnect)) { + if (state.IsInvalid()) { + // The block violates a consensus rule. + if (!state.CorruptionPossible()) + InvalidChainFound(vpindexToConnect.back()); + state = CValidationState(); + break; + } else { + // A system error occurred (disk space, database error, ...). return false; - } - - // Build list of new blocks to connect. - std::vector vpindexToConnect; - vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); - while (pindexMostWork && pindexMostWork != pindexFork) { - vpindexToConnect.push_back(pindexMostWork); - pindexMostWork = pindexMostWork->pprev; - } - - // Connect new blocks. - BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, pindexConnect)) { - if (state.IsInvalid()) { - // The block violates a consensus rule. - if (!state.CorruptionPossible()) - InvalidChainFound(vpindexToConnect.back()); - fComplete = false; - state = CValidationState(); - break; - } else { - // A system error occurred (disk space, database error, ...). - return false; - } + } + } else { + if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { + // We're in a better position than we were. Return temporarily to release the lock. + break; } } } @@ -2136,6 +2132,28 @@ bool ActivateBestChain(CValidationState &state) { return true; } +bool ActivateBestChain(CValidationState &state) { + do { + boost::this_thread::interruption_point(); + + LOCK(cs_main); + + // Check whether we're done (this could be avoided after the first run, + // but that's not worth optimizing. + CBlockIndex *pindexMostWork = FindMostWorkChain(); + if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) + return true; + + if (!ActivateBestChainStep(state, pindexMostWork)) + return false; + + // Check whether we're done now. + if (pindexMostWork == chainActive.Tip()) + return true; + } while(true); + + return true; +} CBlockIndex* AddToBlockIndex(CBlockHeader& block) { From 202e01941c087e0b06a7c18ce344a53ce94e1350 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 May 2014 16:45:33 +0200 Subject: [PATCH 154/336] Move all post-chaintip-change notifications to ActivateBestChain --- src/main.cpp | 100 +++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 860487dece..0d79246a11 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1895,6 +1895,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C for (unsigned int i = 0; i < block.vtx.size(); i++) g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block); + // Watch for changes to the previous coinbase transaction. + static uint256 hashPrevBestCoinBase; + g_signals.UpdatedTransaction(hashPrevBestCoinBase); + hashPrevBestCoinBase = block.GetTxHash(0); + return true; } @@ -2082,6 +2087,7 @@ static CBlockIndex* FindMostWorkChain() { // Try to make some progress towards making pindexMostWork the active block. static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) { AssertLockHeld(cs_main); + bool fInvalidFound = false; CBlockIndex *pindexOldTip = chainActive.Tip(); CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); @@ -2107,6 +2113,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo if (!state.CorruptionPossible()) InvalidChainFound(vpindexToConnect.back()); state = CValidationState(); + fInvalidFound = true; break; } else { // A system error occurred (disk space, database error, ...). @@ -2120,37 +2127,59 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo } } - if (chainActive.Tip() != pindexOldTip) { - std::string strCmd = GetArg("-blocknotify", ""); - if (!IsInitialBlockDownload() && !strCmd.empty()) - { - boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } - } + // Callbacks/notifications for a new best chain. + if (fInvalidFound) + CheckForkWarningConditionsOnNewFork(vpindexToConnect.back()); + else + CheckForkWarningConditions(); + + if (!pblocktree->Flush()) + return state.Abort(_("Failed to sync block index")); return true; } bool ActivateBestChain(CValidationState &state) { + CBlockIndex *pindexNewTip = NULL; + CBlockIndex *pindexMostWork = NULL; do { boost::this_thread::interruption_point(); - LOCK(cs_main); + bool fInitialDownload; + { + LOCK(cs_main); + pindexMostWork = FindMostWorkChain(); - // Check whether we're done (this could be avoided after the first run, - // but that's not worth optimizing. - CBlockIndex *pindexMostWork = FindMostWorkChain(); - if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) - return true; + // Whether we have anything to do at all. + if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip()) + return true; - if (!ActivateBestChainStep(state, pindexMostWork)) - return false; + if (!ActivateBestChainStep(state, pindexMostWork)) + return false; - // Check whether we're done now. - if (pindexMostWork == chainActive.Tip()) - return true; - } while(true); + pindexNewTip = chainActive.Tip(); + fInitialDownload = IsInitialBlockDownload(); + } + // When we reach this point, we switched to a new tip (stored in pindexNewTip). + + // Notifications/callbacks that can run without cs_main + if (!fInitialDownload) { + uint256 hashNewTip = pindexNewTip->GetBlockHash(); + // Relay inventory, but don't relay old inventory during initial block download. + int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) + pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); + + std::string strCmd = GetArg("-blocknotify", ""); + if (!strCmd.empty()) { + boost::replace_all(strCmd, "%s", hashNewTip.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } + } + uiInterface.NotifyBlocksChanged(); + } while(pindexMostWork != chainActive.Tip()); return true; } @@ -2215,26 +2244,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl return state.Abort(_("Failed to write block index")); // New best? - if (!ActivateBestChain(state)) - return false; - - LOCK(cs_main); - if (pindexNew == chainActive.Tip()) - { - // Clear fork warning if its no longer applicable - CheckForkWarningConditions(); - // Notify UI to display prev block's coinbase if it was ours - static uint256 hashPrevBestCoinBase; - g_signals.UpdatedTransaction(hashPrevBestCoinBase); - hashPrevBestCoinBase = block.GetTxHash(0); - } else - CheckForkWarningConditionsOnNewFork(pindexNew); - - if (!pblocktree->Flush()) - return state.Abort(_("Failed to sync block index")); - - uiInterface.NotifyBlocksChanged(); - return true; + return ActivateBestChain(state); } @@ -2554,16 +2564,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, return state.Abort(_("System error: ") + e.what()); } - // Relay inventory, but don't relay old inventory during initial block download - int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate(); - if (chainActive.Tip()->GetBlockHash() == hash) - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) - pnode->PushInventory(CInv(MSG_BLOCK, hash)); - } - return true; } From 18e72167ddfeaea95253b62994c6d64b55b35005 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 May 2014 17:10:35 +0200 Subject: [PATCH 155/336] Push cs_mains down in ProcessBlock --- src/main.cpp | 28 +++++++++++++++++----------- src/miner.cpp | 28 ++++++++++++++-------------- src/rpcserver.cpp | 2 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0d79246a11..16d1cba6ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2243,8 +2243,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew))) return state.Abort(_("Failed to write block index")); - // New best? - return ActivateBestChain(state); + return true; } @@ -2520,7 +2519,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } int nHeight = pindex->nHeight; - uint256 hash = pindex->GetBlockHash(); // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) @@ -2593,10 +2591,11 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd) bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp) { - AssertLockHeld(cs_main); - // Check for duplicate uint256 hash = pblock->GetHash(); + + { + LOCK(cs_main); if (mapBlockIndex.count(hash)) return state.Invalid(error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString()), 0, "duplicate"); if (mapOrphanBlocks.count(hash)) @@ -2665,7 +2664,11 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl mapOrphanBlocksByPrev.erase(hashPrev); } - LogPrintf("ProcessBlock: ACCEPTED\n"); + } + + if (!ActivateBestChain(state)) + return error("ProcessBlock() : ActivateBestChain failed"); + return true; } @@ -3101,6 +3104,8 @@ bool InitBlockIndex() { CBlockIndex *pindex = AddToBlockIndex(block); if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("LoadBlockIndex() : genesis block not accepted"); + if (!ActivateBestChain(state)) + return error("LoadBlockIndex() : genesis block cannot be activated"); } catch(std::runtime_error &e) { return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); } @@ -3230,7 +3235,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) // process block if (nBlockPos >= nStartByte) { - LOCK(cs_main); if (dbp) dbp->nPos = nBlockPos; CValidationState state; @@ -3919,10 +3923,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CInv inv(MSG_BLOCK, block.GetHash()); pfrom->AddInventoryKnown(inv); - LOCK(cs_main); - // Remember who we got this block from. - mapBlockSource[inv.hash] = pfrom->GetId(); - MarkBlockAsReceived(inv.hash, pfrom->GetId()); + { + LOCK(cs_main); + // Remember who we got this block from. + mapBlockSource[inv.hash] = pfrom->GetId(); + MarkBlockAsReceived(inv.hash, pfrom->GetId()); + } CValidationState state; ProcessBlock(state, pfrom, &block); diff --git a/src/miner.cpp b/src/miner.cpp index ddd277a9bb..baaa22c8f3 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -484,22 +484,22 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) LOCK(cs_main); if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash()) return error("BitcoinMiner : generated block is stale"); - - // Remove key from key pool - reservekey.KeepKey(); - - // Track how many getdata requests this block gets - { - LOCK(wallet.cs_wallet); - wallet.mapRequestCount[pblock->GetHash()] = 0; - } - - // Process this block the same as if we had received it from another node - CValidationState state; - if (!ProcessBlock(state, NULL, pblock)) - return error("BitcoinMiner : ProcessBlock, block not accepted"); } + // Remove key from key pool + reservekey.KeepKey(); + + // Track how many getdata requests this block gets + { + LOCK(wallet.cs_wallet); + wallet.mapRequestCount[pblock->GetHash()] = 0; + } + + // Process this block the same as if we had received it from another node + CValidationState state; + if (!ProcessBlock(state, NULL, pblock)) + return error("BitcoinMiner : ProcessBlock, block not accepted"); + return true; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 72a7fe83ef..d4ceb7f995 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -254,7 +254,7 @@ static const CRPCCommand vRPCCommands[] = { "getblocktemplate", &getblocktemplate, true, false, false }, { "getmininginfo", &getmininginfo, true, false, false }, { "getnetworkhashps", &getnetworkhashps, true, false, false }, - { "submitblock", &submitblock, false, false, false }, + { "submitblock", &submitblock, false, true, false }, /* Raw transactions */ { "createrawtransaction", &createrawtransaction, false, false, false }, From f1920e86063d0ed008c6028d8223b0e21889bf75 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 15 Oct 2013 00:34:20 +0200 Subject: [PATCH 156/336] Ping automatically every 2 minutes (unconditionally) ... instead of after 30 minutes of no sending, for latency measurement and keep-alive. Also, disconnect if no reply arrives within 20 minutes, instead of 90 of inactivity (for peers supporting the 'pong' message). --- src/main.cpp | 13 ++++++------- src/net.cpp | 18 +++++++++++------- src/net.h | 13 ++++++++++--- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5d1ff94f5d..dd33f443bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4296,8 +4296,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // RPC ping request by user pingSend = true; } - if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSendMsg.empty()) { - // Ping automatically sent as a keepalive + if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) { + // Ping automatically sent as a latency probe & keepalive. pingSend = true; } if (pingSend) { @@ -4305,15 +4305,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle) while (nonce == 0) { RAND_bytes((unsigned char*)&nonce, sizeof(nonce)); } - pto->nPingNonceSent = nonce; pto->fPingQueued = false; + pto->nPingUsecStart = GetTimeMicros(); if (pto->nVersion > BIP0031_VERSION) { - // Take timestamp as close as possible before transmitting ping - pto->nPingUsecStart = GetTimeMicros(); + pto->nPingNonceSent = nonce; pto->PushMessage("ping", nonce); } else { - // Peer is too old to support ping command with nonce, pong will never arrive, disable timing - pto->nPingUsecStart = 0; + // Peer is too old to support ping command with nonce, pong will never arrive. + pto->nPingNonceSent = 0; pto->PushMessage("ping"); } } diff --git a/src/net.cpp b/src/net.cpp index 479f77c469..fe6e9337ae 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1028,23 +1028,27 @@ void ThreadSocketHandler() // // Inactivity checking // - if (pnode->vSendMsg.empty()) - pnode->nLastSendEmpty = GetTime(); - if (GetTime() - pnode->nTimeConnected > 60) + int64_t nTime = GetTime(); + if (nTime - pnode->nTimeConnected > 60) { if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0); pnode->fDisconnect = true; } - else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60) + else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) { - LogPrintf("socket not sending\n"); + LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend); pnode->fDisconnect = true; } - else if (GetTime() - pnode->nLastRecv > 90*60) + else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60)) { - LogPrintf("socket inactivity timeout\n"); + LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv); + pnode->fDisconnect = true; + } + else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros()) + { + LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart)); pnode->fDisconnect = true; } } diff --git a/src/net.h b/src/net.h index 9fcdbf802b..7a77e55a14 100644 --- a/src/net.h +++ b/src/net.h @@ -28,6 +28,7 @@ #include #include + class CAddrMan; class CBlockIndex; class CNode; @@ -36,6 +37,10 @@ namespace boost { class thread_group; } +/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */ +static const int PING_INTERVAL = 2 * 60; +/** Time after which to disconnect, after waiting for a ping response (or inactivity). */ +static const int TIMEOUT_INTERVAL = 20 * 60; /** The maximum number of entries in an 'inv' protocol message */ static const unsigned int MAX_INV_SZ = 50000; /** -upnp default */ @@ -217,7 +222,6 @@ public: int64_t nLastSend; int64_t nLastRecv; - int64_t nLastSendEmpty; int64_t nTimeConnected; CAddress addr; std::string addrName; @@ -273,10 +277,14 @@ public: CCriticalSection cs_inventory; std::multimap mapAskFor; - // Ping time measurement + // Ping time measurement: + // The pong reply we're expecting, or 0 if no pong expected. uint64_t nPingNonceSent; + // Time (in usec) the last ping was sent, or 0 if no ping was ever sent. int64_t nPingUsecStart; + // Last measured round-trip time. int64_t nPingUsecTime; + // Whether a ping is requested. bool fPingQueued; CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) @@ -288,7 +296,6 @@ public: nLastRecv = 0; nSendBytes = 0; nRecvBytes = 0; - nLastSendEmpty = GetTime(); nTimeConnected = GetTime(); addr = addrIn; addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; From 6dd5edb7de7f5f9aeac71b676c71186405a15376 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Jun 2014 15:01:23 +0200 Subject: [PATCH 157/336] Remove unused Print/PrintHex functions You can just use HexStr(script) or script.ToString() for debugging, no need for these extra functions. --- src/script.cpp | 4 ---- src/script.h | 11 ----------- src/util.h | 11 ----------- 3 files changed, 26 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index 381e84d0b7..11cdfef950 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -838,10 +838,6 @@ bool EvalScript(vector >& stack, const CScript& script, co valtype& vchSig = stacktop(-2); valtype& vchPubKey = stacktop(-1); - ////// debug print - //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n"); - //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n"); - // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); diff --git a/src/script.h b/src/script.h index aed2b7a6ad..a282e7dc04 100644 --- a/src/script.h +++ b/src/script.h @@ -691,12 +691,6 @@ public: void SetDestination(const CTxDestination& address); void SetMultisig(int nRequired, const std::vector& keys); - - void PrintHex() const - { - LogPrintf("CScript(%s)\n", HexStr(begin(), end(), true).c_str()); - } - std::string ToString() const { std::string str; @@ -720,11 +714,6 @@ public: return str; } - void print() const - { - LogPrintf("%s\n", ToString()); - } - CScriptID GetID() const { return CScriptID(Hash160(*this)); diff --git a/src/util.h b/src/util.h index b09f9bb15e..e070365790 100644 --- a/src/util.h +++ b/src/util.h @@ -286,17 +286,6 @@ inline std::string HexStr(const T& vch, bool fSpaces=false) return HexStr(vch.begin(), vch.end(), fSpaces); } -template -void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true) -{ - LogPrintf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str()); -} - -inline void PrintHex(const std::vector& vch, const char* pszFormat="%s", bool fSpaces=true) -{ - LogPrintf(pszFormat, HexStr(vch, fSpaces).c_str()); -} - inline int64_t GetPerformanceCounter() { int64_t nCounter = 0; From ac14bcc1f12d2407516bcdfef57b2740df48381b Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 10 May 2014 14:54:20 +0200 Subject: [PATCH 158/336] small formatting, indentation and comment fixes - contains zero code changes --- src/main.cpp | 9 +++------ src/main.h | 1 - src/miner.cpp | 1 - src/miner.h | 3 ++- src/rpcblockchain.cpp | 6 +++--- src/rpcmining.cpp | 2 ++ src/util.cpp | 22 ++++++++++++---------- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5d1ff94f5d..f53d20fbb4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1985,7 +1985,7 @@ bool static DisconnectTip(CValidationState &state) { BOOST_FOREACH(const CTransaction &tx, block.vtx) { // ignore validation errors in resurrected transactions list removed; - CValidationState stateDummy; + CValidationState stateDummy; if (!tx.IsCoinBase()) if (!AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) mempool.remove(tx, removed, true); @@ -2213,7 +2213,6 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block) return pindexNew; } - // Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) { @@ -2246,7 +2245,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl return true; } - bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { bool fUpdatedLast = false; @@ -2341,7 +2339,6 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } - bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) { // Check proof of work matches claimed amount @@ -4455,8 +4452,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // in flight for over two minutes, since we first had a chance to // process an incoming block. int64_t nNow = GetTimeMicros(); - if (!pto->fDisconnect && state.nBlocksInFlight && - state.nLastBlockReceive < state.nLastBlockProcess - BLOCK_DOWNLOAD_TIMEOUT*1000000 && + if (!pto->fDisconnect && state.nBlocksInFlight && + state.nLastBlockReceive < state.nLastBlockProcess - BLOCK_DOWNLOAD_TIMEOUT*1000000 && state.vBlocksInFlight.front().nTime < state.nLastBlockProcess - 2*BLOCK_DOWNLOAD_TIMEOUT*1000000) { LogPrintf("Peer %s is stalling block download, disconnecting\n", state.name.c_str()); pto->fDisconnect = true; diff --git a/src/main.h b/src/main.h index 4ef3800084..e0cbbd25c3 100644 --- a/src/main.h +++ b/src/main.h @@ -1019,7 +1019,6 @@ public: /** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */ class CVerifyDB { public: - CVerifyDB(); ~CVerifyDB(); bool VerifyDB(int nCheckLevel, int nCheckDepth); diff --git a/src/miner.cpp b/src/miner.cpp index 68abc4a6ef..a0a728fb81 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -677,4 +677,3 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) } #endif - diff --git a/src/miner.h b/src/miner.h index 26151f6cd5..dcd61d8fd9 100644 --- a/src/miner.h +++ b/src/miner.h @@ -10,11 +10,12 @@ class CBlock; class CBlockIndex; -struct CBlockTemplate; class CReserveKey; class CScript; class CWallet; +struct CBlockTemplate; + /** Run the miner threads */ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads); /** Generate a new block, without valid proof-of-work */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index ff5057b526..5e0173dcf2 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -3,10 +3,10 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpcserver.h" -#include "main.h" -#include "sync.h" #include "checkpoints.h" +#include "main.h" +#include "rpcserver.h" +#include "sync.h" #include diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 837f5336c4..3caf7d89fe 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -13,9 +13,11 @@ #include "db.h" #include "wallet.h" #endif + #include #include + #include "json/json_spirit_utils.h" #include "json/json_spirit_value.h" diff --git a/src/util.cpp b/src/util.cpp index d106b03230..cccf2df484 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -962,13 +962,15 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) void ClearDatadirCache() { std::fill(&pathCached[0], &pathCached[CChainParams::MAX_NETWORK_TYPES+1], - boost::filesystem::path()); + boost::filesystem::path()); } boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf")); - if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + if (!pathConfigFile.is_complete()) + pathConfigFile = GetDataDir(false) / pathConfigFile; + return pathConfigFile; } @@ -1028,9 +1030,9 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) #endif /* WIN32 */ } - -// Ignores exceptions thrown by boost's create_directory if the requested directory exists. -// Specifically handles case where path p exists, but it wasn't possible for the user to write to the parent directory. +// Ignores exceptions thrown by Boost's create_directory if the requested directory exists. +// Specifically handles case where path p exists, but it wasn't possible for the user to +// write to the parent directory. bool TryCreateDirectory(const boost::filesystem::path& p) { try @@ -1381,19 +1383,19 @@ bool ParseInt32(const std::string& str, int32_t *out) void SetupEnvironment() { - #ifndef WIN32 +#ifndef WIN32 try { - #if BOOST_FILESYSTEM_VERSION == 3 +#if BOOST_FILESYSTEM_VERSION == 3 boost::filesystem::path::codecvt(); // Raises runtime error if current locale is invalid - #else // boost filesystem v2 +#else // boost filesystem v2 std::locale(); // Raises runtime error if current locale is invalid - #endif +#endif } catch(std::runtime_error &e) { setenv("LC_ALL", "C", 1); // Force C locale } - #endif +#endif } std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) From 1c24187b51c1b8ebbc0295a57d5509effc845984 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 10 Jun 2014 18:34:35 +0200 Subject: [PATCH 159/336] remove unused UPnP code from main.h --- src/main.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main.h b/src/main.h index 4ef3800084..d907bdbaff 100644 --- a/src/main.h +++ b/src/main.h @@ -66,12 +66,6 @@ static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 128; /** Timeout in seconds before considering a block download peer unresponsive. */ static const unsigned int BLOCK_DOWNLOAD_TIMEOUT = 60; -#ifdef USE_UPNP -static const int fHaveUPnP = true; -#else -static const int fHaveUPnP = false; -#endif - /** "reject" message codes **/ static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_INVALID = 0x10; From 699fe635c6f829e06739e096b0997976e2030ddf Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 10 Jun 2014 19:33:12 +0200 Subject: [PATCH 160/336] remove wrong ; in chainparams.h and order includes --- src/chainparams.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chainparams.h b/src/chainparams.h index 988e3ac3a4..8370cc5690 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -6,9 +6,9 @@ #ifndef BITCOIN_CHAIN_PARAMS_H #define BITCOIN_CHAIN_PARAMS_H -#include "uint256.h" #include "core.h" #include "protocol.h" +#include "uint256.h" #include @@ -62,7 +62,7 @@ public: /* Used if GenerateBitcoins is called with a negative number of threads */ int DefaultMinerThreads() const { return nMinerThreads; } - const CBlock& GenesisBlock() const { return genesis; }; + const CBlock& GenesisBlock() const { return genesis; } bool RequireRPCPassword() const { return fRequireRPCPassword; } /* Make miner wait to have peers to avoid wasting work */ bool MiningRequiresPeers() const { return fMiningRequiresPeers; } From 38e324af8693eb0c3d4bf22df9cbb73667f195ce Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 10 Jun 2014 15:43:02 -0400 Subject: [PATCH 161/336] build: qt: split locale resources. Fixes non-deterministic distcheck The rcc tool is quirky and only honors files in the same directory as the qrc. When doing an out-of-tree build (as 'make distcheck' does), the generated translation files end up in a different path, so rcc can't find them. Split them up so that rcc is run twice: once for static source files and once for generated files. --- src/Makefile.qt.include | 18 +++++++--- src/qt/bitcoin.cpp | 1 + src/qt/bitcoin.qrc | 73 ------------------------------------- src/qt/bitcoin_locale.qrc | 75 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 78 deletions(-) create mode 100644 src/qt/bitcoin_locale.qrc diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 749b976c44..72c7486258 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -152,6 +152,8 @@ QT_MOC = \ QT_QRC_CPP = qt/qrc_bitcoin.cpp QT_QRC = qt/bitcoin.qrc +QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp +QT_QRC_LOCALE = qt/bitcoin_locale.qrc PROTOBUF_CC = qt/paymentrequest.pb.cc PROTOBUF_H = qt/paymentrequest.pb.h @@ -321,10 +323,10 @@ qt_libbitcoinqt_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ - $(QT_QRC) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) + $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ - $(PROTOBUF_H) $(QT_QRC_CPP) + $(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP) # forms/foo.h -> forms/ui_foo.h QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h)))) @@ -371,10 +373,16 @@ translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts qt/locale/bitcoin_en.ts -$(QT_QRC_CPP): $(QT_QRC) $(QT_QM) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H) +$(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) @test -f $(RCC) - $(AM_V_GEN) cd $(srcdir); QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ - $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $(abs_builddir)/$@ + @test -f $(@D)/$( $@ + +$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H) + @test -f $(RCC) + $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ + $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 45d7a52889..2be8191eb5 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -475,6 +475,7 @@ int main(int argc, char *argv[]) #endif Q_INIT_RESOURCE(bitcoin); + Q_INIT_RESOURCE(bitcoin_locale); BitcoinApplication app(argc, argv); #if QT_VERSION > 0x050100 // Generate high-dpi pixmaps diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index e1c739b022..f38200c7f7 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -84,77 +84,4 @@ res/movies/spinner-033.png res/movies/spinner-034.png - - locale/bitcoin_ach.qm - locale/bitcoin_af_ZA.qm - locale/bitcoin_ar.qm - locale/bitcoin_be_BY.qm - locale/bitcoin_bg.qm - locale/bitcoin_bs.qm - locale/bitcoin_ca_ES.qm - locale/bitcoin_ca.qm - locale/bitcoin_ca@valencia.qm - locale/bitcoin_cmn.qm - locale/bitcoin_cs.qm - locale/bitcoin_cy.qm - locale/bitcoin_da.qm - locale/bitcoin_de.qm - locale/bitcoin_el_GR.qm - locale/bitcoin_en.qm - locale/bitcoin_eo.qm - locale/bitcoin_es_CL.qm - locale/bitcoin_es_DO.qm - locale/bitcoin_es_MX.qm - locale/bitcoin_es.qm - locale/bitcoin_es_UY.qm - locale/bitcoin_et.qm - locale/bitcoin_eu_ES.qm - locale/bitcoin_fa_IR.qm - locale/bitcoin_fa.qm - locale/bitcoin_fi.qm - locale/bitcoin_fr_CA.qm - locale/bitcoin_fr.qm - locale/bitcoin_gl.qm - locale/bitcoin_gu_IN.qm - locale/bitcoin_he.qm - locale/bitcoin_hi_IN.qm - locale/bitcoin_hr.qm - locale/bitcoin_hu.qm - locale/bitcoin_id_ID.qm - locale/bitcoin_it.qm - locale/bitcoin_ja.qm - locale/bitcoin_ka.qm - locale/bitcoin_kk_KZ.qm - locale/bitcoin_ko_KR.qm - locale/bitcoin_ky.qm - locale/bitcoin_la.qm - locale/bitcoin_lt.qm - locale/bitcoin_lv_LV.qm - locale/bitcoin_mn.qm - locale/bitcoin_ms_MY.qm - locale/bitcoin_nb.qm - locale/bitcoin_nl.qm - locale/bitcoin_pam.qm - locale/bitcoin_pl.qm - locale/bitcoin_pt_BR.qm - locale/bitcoin_pt_PT.qm - locale/bitcoin_ro_RO.qm - locale/bitcoin_ru.qm - locale/bitcoin_sah.qm - locale/bitcoin_sk.qm - locale/bitcoin_sl_SI.qm - locale/bitcoin_sq.qm - locale/bitcoin_sr.qm - locale/bitcoin_sv.qm - locale/bitcoin_th_TH.qm - locale/bitcoin_tr.qm - locale/bitcoin_uk.qm - locale/bitcoin_ur_PK.qm - locale/bitcoin_uz@Cyrl.qm - locale/bitcoin_vi.qm - locale/bitcoin_vi_VN.qm - locale/bitcoin_zh_CN.qm - locale/bitcoin_zh_HK.qm - locale/bitcoin_zh_TW.qm - diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc new file mode 100644 index 0000000000..b70a107397 --- /dev/null +++ b/src/qt/bitcoin_locale.qrc @@ -0,0 +1,75 @@ + + + locale/bitcoin_ach.qm + locale/bitcoin_af_ZA.qm + locale/bitcoin_ar.qm + locale/bitcoin_be_BY.qm + locale/bitcoin_bg.qm + locale/bitcoin_bs.qm + locale/bitcoin_ca_ES.qm + locale/bitcoin_ca.qm + locale/bitcoin_ca@valencia.qm + locale/bitcoin_cmn.qm + locale/bitcoin_cs.qm + locale/bitcoin_cy.qm + locale/bitcoin_da.qm + locale/bitcoin_de.qm + locale/bitcoin_el_GR.qm + locale/bitcoin_en.qm + locale/bitcoin_eo.qm + locale/bitcoin_es_CL.qm + locale/bitcoin_es_DO.qm + locale/bitcoin_es_MX.qm + locale/bitcoin_es.qm + locale/bitcoin_es_UY.qm + locale/bitcoin_et.qm + locale/bitcoin_eu_ES.qm + locale/bitcoin_fa_IR.qm + locale/bitcoin_fa.qm + locale/bitcoin_fi.qm + locale/bitcoin_fr_CA.qm + locale/bitcoin_fr.qm + locale/bitcoin_gl.qm + locale/bitcoin_gu_IN.qm + locale/bitcoin_he.qm + locale/bitcoin_hi_IN.qm + locale/bitcoin_hr.qm + locale/bitcoin_hu.qm + locale/bitcoin_id_ID.qm + locale/bitcoin_it.qm + locale/bitcoin_ja.qm + locale/bitcoin_ka.qm + locale/bitcoin_kk_KZ.qm + locale/bitcoin_ko_KR.qm + locale/bitcoin_ky.qm + locale/bitcoin_la.qm + locale/bitcoin_lt.qm + locale/bitcoin_lv_LV.qm + locale/bitcoin_mn.qm + locale/bitcoin_ms_MY.qm + locale/bitcoin_nb.qm + locale/bitcoin_nl.qm + locale/bitcoin_pam.qm + locale/bitcoin_pl.qm + locale/bitcoin_pt_BR.qm + locale/bitcoin_pt_PT.qm + locale/bitcoin_ro_RO.qm + locale/bitcoin_ru.qm + locale/bitcoin_sah.qm + locale/bitcoin_sk.qm + locale/bitcoin_sl_SI.qm + locale/bitcoin_sq.qm + locale/bitcoin_sr.qm + locale/bitcoin_sv.qm + locale/bitcoin_th_TH.qm + locale/bitcoin_tr.qm + locale/bitcoin_uk.qm + locale/bitcoin_ur_PK.qm + locale/bitcoin_uz@Cyrl.qm + locale/bitcoin_vi.qm + locale/bitcoin_vi_VN.qm + locale/bitcoin_zh_CN.qm + locale/bitcoin_zh_HK.qm + locale/bitcoin_zh_TW.qm + + From 77a055d04979dc2b3ec4064e99c69259a4216f12 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 10 Jun 2014 22:26:50 -0400 Subject: [PATCH 162/336] build: Add a top-level forwarding target for src/* objects Fixes #3955. It's hackish, but seems to always function as expected. Examples: make src/bitcoind make src/qt/bitcoin-qt make src/libbitcoin.a --- Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 04f8368dd7..719af42ac7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I src/m4 SUBDIRS = src -.PHONY: deploy +.PHONY: deploy FORCE GZIP_ENV="-9n" @@ -53,8 +53,8 @@ $(BITCOIN_WIN_INSTALLER): $(BITCOIND_BIN) $(BITCOIN_QT_BIN) $(BITCOIN_CLI_BIN) @test -f $(MAKENSIS) && $(MAKENSIS) $(top_builddir)/share/setup.nsi || \ echo error: could not build $@ -$(BITCOIND_BIN) $(BITCOIN_QT_BIN) $(BITCOIN_CLI_BIN): - make -C $(dir $@) $(notdir $@) +$(if $(findstring src/,$(MAKECMDGOALS)),$(MAKECMDGOALS), none): FORCE + $(MAKE) -C src $(patsubst src/%,%,$@) $(OSX_APP)/Contents/PkgInfo: $(MKDIR_P) $(@D) From 68ba85fd750e94861440ef15047d571d6b518217 Mon Sep 17 00:00:00 2001 From: Giuseppe Mazzotta Date: Tue, 10 Jun 2014 11:43:27 +0200 Subject: [PATCH 163/336] Updated Debian example bitcoin.conf with config from wiki + removed some cruft and updated comments --- contrib/debian/examples/bitcoin.conf | 95 ++++++++++++++++++---------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/contrib/debian/examples/bitcoin.conf b/contrib/debian/examples/bitcoin.conf index 10ec36ae7e..0aa8674af9 100644 --- a/contrib/debian/examples/bitcoin.conf +++ b/contrib/debian/examples/bitcoin.conf @@ -1,79 +1,110 @@ -# bitcoin.conf configuration file. Lines beginning with # are comments. - - +## +## 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 +#testnet=0 + +# Run a regression test network +#regtest=0 # Connect via a socks4 proxy #proxy=127.0.0.1:9050 +############################################################## +## Quick Primer on addnode vs connect ## +## Let's say for instance you use addnode=4.2.2.4 ## +## addnode will connect you to and tell you about the ## +## nodes connected to 4.2.2.4. In addition it will tell ## +## the other nodes connected to it that you exist so ## +## they can connect to you. ## +## connect will not do the above when you 'connect' to it. ## +## It will *only* connect you to 4.2.2.4 and no one else.## +## ## +## So if you're behind a firewall, or have other problems ## +## finding nodes, add some using 'addnode'. ## +## ## +## If you want to stay private, use 'connect' to only ## +## connect to "trusted" nodes. ## +## ## +## If you run multiple nodes on a LAN, there's no need for ## +## all of them to open lots of connections. Instead ## +## 'connect' them all to one node that is port forwarded ## +## and has lots of connections. ## +## Thanks goes to [Noodle] on Freenode. ## +############################################################## + # 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: +# Alternatively 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 +# Listening mode, enabled by default except when 'connect' is being used +#listen=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 +# server=1 tells Bitcoin-QT and bitcoind to accept JSON-RPC commands +#server=0 # You must set rpcuser and rpcpassword to secure the JSON-RPC api #rpcuser=Ulysseys -#rpcpassword=YourSuperGreatPasswordNumber_385593 +#rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_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.* +# How many seconds bitcoin will wait for a complete RPC HTTP request. +# after the HTTP connection is established. +#rpctimeout=30 + +# By default, only RPC connections from localhost are allowed. +# Specify as many rpcallowip= settings as you like to allow connections from other hosts, +# either as a single IPv4/IPv6 or with a subnet specification. + +# NOTE: opening up the RPC port to hosts outside your local trusted network is NOT RECOMMENDED, +# because the rpcpassword is transmitted over the network unencrypted. + +# server=1 tells Bitcoin-QT to accept JSON-RPC commands. +# it is also read by bitcoind to determine if RPC should be enabled +#rpcallowip=10.1.1.34/255.255.255.0 +#rpcallowip=1.2.3.4/24 +#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96 # Listen for RPC connections on this TCP port: -rpcport=8332 +#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 +#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 +#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 +#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 - +#paytxfee=0.00 # User interface options From 56b07d2dcdec336173b866210c535439b03416a1 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Thu, 29 May 2014 13:02:22 +0200 Subject: [PATCH 164/336] [Qt] allow setting listen via GUI - add DEFAULT_LISTEN in net.h and use in the code (shared setting between core and GUI) Important: This makes it obvious, that we need to re-think the settings/options handling, as GUI settings are processed before any parameter-interaction (which is mostly important for network stuff) in AppInit2()! --- src/init.cpp | 2 +- src/net.h | 2 ++ src/qt/forms/optionsdialog.ui | 10 ++++++++++ src/qt/optionsdialog.cpp | 2 ++ src/qt/optionsmodel.cpp | 13 +++++++++++++ src/qt/optionsmodel.h | 1 + 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 1d86cf087d..528c3df064 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -766,7 +766,7 @@ bool AppInit2(boost::thread_group& threadGroup) } // see Step 2: parameter interactions for more information about these - fListen = GetBoolArg("-listen", true); + fListen = GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = GetBoolArg("-discover", true); fNameLookup = GetBoolArg("-dns", true); diff --git a/src/net.h b/src/net.h index 9fcdbf802b..11744aa7c4 100644 --- a/src/net.h +++ b/src/net.h @@ -38,6 +38,8 @@ namespace boost { /** The maximum number of entries in an 'inv' protocol message */ static const unsigned int MAX_INV_SZ = 50000; +/** -listen default */ +static const bool DEFAULT_LISTEN = true; /** -upnp default */ #ifdef USE_UPNP static const bool DEFAULT_UPNP = USE_UPNP; diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 0103842e02..0c5b8895aa 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -242,6 +242,16 @@ + + + + Accept connections from outside + + + Allow incoming connections + + + diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 1cbf5f8810..abfd4123e0 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -151,6 +151,7 @@ void OptionsDialog::setModel(OptionsModel *model) /* Wallet */ connect(ui->spendZeroConfChange, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning())); /* Network */ + connect(ui->allowIncoming, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning())); connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning())); /* Display */ connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning())); @@ -171,6 +172,7 @@ void OptionsDialog::setMapper() /* Network */ mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); + mapper->addMapping(ui->allowIncoming, OptionsModel::Listen); mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index f3a5f37bb3..4dafd9d2af 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -110,6 +110,11 @@ void OptionsModel::Init() if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) addOverriddenOption("-upnp"); + if (!settings.contains("fListen")) + settings.setValue("fListen", DEFAULT_LISTEN); + if (!SoftSetBoolArg("-listen", settings.value("fListen").toBool())) + addOverriddenOption("-listen"); + if (!settings.contains("fUseProxy")) settings.setValue("fUseProxy", false); if (!settings.contains("addrProxy")) @@ -214,6 +219,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return settings.value("nDatabaseCache"); case ThreadsScriptVerif: return settings.value("nThreadsScriptVerif"); + case Listen: + return settings.value("fListen"); default: return QVariant(); } @@ -339,6 +346,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in setRestartRequired(true); } break; + case Listen: + if (settings.value("fListen") != value) { + settings.setValue("fListen", value); + setRestartRequired(true); + } + break; default: break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index f05e3e92de..2596682d07 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -42,6 +42,7 @@ public: ThreadsScriptVerif, // int DatabaseCache, // int SpendZeroConfChange, // bool + Listen, // bool OptionIDRowCount, }; From 4aaa01783d4e3592db456fb2db05207c3c278244 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 11 Jun 2014 12:16:26 +0200 Subject: [PATCH 165/336] rework help messages for fee-related options - mention the units and show the default for -paytxfee --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1d86cf087d..b85078832f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -253,7 +253,7 @@ std::string HelpMessage(HelpMessageMode hmm) #ifdef ENABLE_WALLET strUsage += "\n" + _("Wallet options:") + "\n"; strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; - strUsage += " -paytxfee= " + _("Fee per kB to add to transactions you send") + "\n"; + strUsage += " -paytxfee= " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; @@ -291,8 +291,8 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -limitfreerelay= " + _("Continuously rate-limit free transactions to *1000 bytes per minute (default:15)") + "\n"; strUsage += " -maxsigcachesize= " + _("Limit size of signature cache to entries (default: 50000)") + "\n"; } - strUsage += " -mintxfee= " + _("Fees smaller than this are considered zero fee (for transaction creation) (default:") + " " + FormatMoney(CTransaction::minTxFee.GetFeePerK()) + ")" + "\n"; - strUsage += " -minrelaytxfee= " + _("Fees smaller than this are considered zero fee (for relaying) (default:") + " " + FormatMoney(CTransaction::minRelayTxFee.GetFeePerK()) + ")" + "\n"; + strUsage += " -mintxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CTransaction::minTxFee.GetFeePerK())) + "\n"; + strUsage += " -minrelaytxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(CTransaction::minRelayTxFee.GetFeePerK())) + "\n"; strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { From 5bd6c31bd63261f16d3d1b40512a8bb51b28abcf Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 24 May 2014 11:14:52 +0200 Subject: [PATCH 166/336] small cleanup of net - remove an unneded else in ConnectNode() - make 0 a double and change to 0.0 in ConnectNode() - rename strDest to pszDest in OpenNetworkConnection() - remove an unneded call to our REF() macro in BindListenPort() - small style cleanups and removal of unneeded new-lines --- src/net.cpp | 26 +++++++++++--------------- src/net.h | 4 ++-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 479f77c469..07a2848e9c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -469,11 +469,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) } } - /// debug print LogPrint("net", "trying connection %s lastseen=%.1fhrs\n", pszDest ? pszDest : addrConnect.ToString(), - pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); + pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); // Connect SOCKET hSocket; @@ -505,10 +504,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) pnode->nTimeConnected = GetTime(); return pnode; } - else - { - return NULL; - } + + return NULL; } void CNode::CloseSocketDisconnect() @@ -535,7 +532,6 @@ void CNode::Cleanup() { } - void CNode::PushVersion() { int nBestHeight = g_signals.GetHeight().get_value_or(0); @@ -1425,21 +1421,22 @@ void ThreadOpenAddedConnections() } // if successful, this moves the passed grant to the constructed node -bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot) +bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot) { // // Initiate outbound network connection // boost::this_thread::interruption_point(); - if (!strDest) + if (!pszDest) { if (IsLocal(addrConnect) || FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || FindNode(addrConnect.ToStringIPPort().c_str())) return false; - if (strDest && FindNode(strDest)) + } + if (pszDest && FindNode(pszDest)) return false; - CNode* pnode = ConnectNode(addrConnect, strDest); + CNode* pnode = ConnectNode(addrConnect, pszDest); boost::this_thread::interruption_point(); if (!pnode) @@ -1575,7 +1572,7 @@ bool BindListenPort(const CService &addrBind, string& strError) socklen_t len = sizeof(sockaddr); if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { - strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString()); + strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString()); LogPrintf("%s\n", strError); return false; } @@ -1769,9 +1766,8 @@ bool StopNode() class CNetCleanup { public: - CNetCleanup() - { - } + CNetCleanup() {} + ~CNetCleanup() { // Close sockets diff --git a/src/net.h b/src/net.h index 9fcdbf802b..df7555d476 100644 --- a/src/net.h +++ b/src/net.h @@ -54,11 +54,11 @@ bool GetMyExternalIP(CNetAddr& ipRet); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CService& ip); -CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL); +CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL); bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); -bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); +bool BindListenPort(const CService &bindAddr, std::string& strError); void StartNode(boost::thread_group& threadGroup); bool StopNode(); void SocketSendData(CNode *pnode); From 634bd61b76c9d03d7ce7dfab4e4a48f4b70f282a Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 11 Jun 2014 12:39:09 +0200 Subject: [PATCH 167/336] convert an if into an else if in OpenNetworkConnection() --- src/net.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 07a2848e9c..ac0da26de9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1432,8 +1432,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || FindNode(addrConnect.ToStringIPPort().c_str())) return false; - } - if (pszDest && FindNode(pszDest)) + } else if (FindNode(pszDest)) return false; CNode* pnode = ConnectNode(addrConnect, pszDest); From 96b733e99694e74dcd38b16112655f7e1ea2d43b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 3 Jun 2014 16:12:19 +0200 Subject: [PATCH 168/336] Add `-version` option to get just the version Adds a `-version` or `--version` option to print just the version of the program for bitcoind, bitcoin-cli and bitcoin-qt. Also make it that `-help` can be used to display the help (as well as existing `--help`). Up to now, `-help` was the only option that didn't work with either one or two dashes. --- src/bitcoin-cli.cpp | 18 ++++++++++-------- src/bitcoind.cpp | 25 ++++++++++++++----------- src/qt/bitcoin.cpp | 4 ++-- src/qt/bitcoingui.cpp | 2 +- src/qt/utilitydialog.cpp | 19 ++++++++++--------- src/qt/utilitydialog.h | 5 +---- 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 29efdfa821..0bb71329f5 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -39,16 +39,18 @@ static bool AppInitRPC(int argc, char* argv[]) return false; } - if (argc<2 || mapArgs.count("-?") || mapArgs.count("--help")) + if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { - // First part of help message is specific to RPC client - std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n\n" + - _("Usage:") + "\n" + - " bitcoin-cli [options] [params] " + _("Send command to Bitcoin Core") + "\n" + - " bitcoin-cli [options] help " + _("List commands") + "\n" + - " bitcoin-cli [options] help " + _("Get help for a command") + "\n"; + std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n"; + if (!mapArgs.count("-version")) + { + strUsage += "\n" + _("Usage:") + "\n" + + " bitcoin-cli [options] [params] " + _("Send command to Bitcoin Core") + "\n" + + " bitcoin-cli [options] help " + _("List commands") + "\n" + + " bitcoin-cli [options] help " + _("Get help for a command") + "\n"; - strUsage += "\n" + HelpMessageCli(true); + strUsage += "\n" + HelpMessageCli(true); + } fprintf(stdout, "%s", strUsage.c_str()); return false; diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 704332c39b..99dc9d726d 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -83,19 +83,22 @@ bool AppInit(int argc, char* argv[]) return false; } - if (mapArgs.count("-?") || mapArgs.count("--help")) + if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { - // First part of help message is specific to bitcoind / RPC client - std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" + - _("Usage:") + "\n" + - " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" + - _("Usage (deprecated, use bitcoin-cli):") + "\n" + - " bitcoind [options] [params] " + _("Send command to Bitcoin Core") + "\n" + - " bitcoind [options] help " + _("List commands") + "\n" + - " bitcoind [options] help " + _("Get help for a command") + "\n"; + std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n"; - strUsage += "\n" + HelpMessage(HMM_BITCOIND); - strUsage += "\n" + HelpMessageCli(false); + if (!mapArgs.count("-version")) + { + strUsage += "\n" + _("Usage:") + "\n" + + " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" + + _("Usage (deprecated, use bitcoin-cli):") + "\n" + + " bitcoind [options] [params] " + _("Send command to Bitcoin Core") + "\n" + + " bitcoind [options] help " + _("List commands") + "\n" + + " bitcoind [options] help " + _("Get help for a command") + "\n"; + + strUsage += "\n" + HelpMessage(HMM_BITCOIND); + strUsage += "\n" + HelpMessageCli(false); + } fprintf(stdout, "%s", strUsage.c_str()); return false; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 2be8191eb5..387f6ede4b 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -503,9 +503,9 @@ int main(int argc, char *argv[]) // Show help message immediately after parsing command-line options (for "-lang") and setting locale, // but before showing splash screen. - if (mapArgs.count("-?") || mapArgs.count("--help")) + if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { - HelpMessageDialog help(NULL); + HelpMessageDialog help(NULL, mapArgs.count("-version")); help.showOrPrint(); return 1; } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 3469f990ac..847a3ab8f1 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -556,7 +556,7 @@ void BitcoinGUI::aboutClicked() void BitcoinGUI::showHelpMessageClicked() { - HelpMessageDialog *help = new HelpMessageDialog(this); + HelpMessageDialog *help = new HelpMessageDialog(this, false); help->setAttribute(Qt::WA_DeleteOnClose); help->show(); } diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 01b710e876..435c6a4368 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -57,21 +57,20 @@ void AboutDialog::on_buttonBox_accepted() } /** "Help message" dialog box */ -HelpMessageDialog::HelpMessageDialog(QWidget *parent) : +HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool versionOnly) : QDialog(parent), ui(new Ui::HelpMessageDialog) { ui->setupUi(this); GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this); - header = tr("Bitcoin Core") + " " + tr("version") + " " + - QString::fromStdString(FormatFullVersion()) + "\n\n" + - tr("Usage:") + "\n" + + QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); + QString header = tr("Usage:") + "\n" + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; - coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); + QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); - uiOptions = tr("UI options") + ":\n" + + QString uiOptions = tr("UI options") + ":\n" + " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" + " -lang= " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + " -min " + tr("Start minimized") + "\n" + @@ -81,7 +80,10 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent) : ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont()); // Set help message text - ui->helpMessageLabel->setText(header + "\n" + coreOptions + "\n" + uiOptions); + if(versionOnly) + ui->helpMessageLabel->setText(version); + else + ui->helpMessageLabel->setText(version + "\n" + header + "\n" + coreOptions + "\n" + uiOptions); } HelpMessageDialog::~HelpMessageDialog() @@ -93,8 +95,7 @@ HelpMessageDialog::~HelpMessageDialog() void HelpMessageDialog::printToConsole() { // On other operating systems, the expected action is to print the message to the console. - QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions + "\n"; - fprintf(stdout, "%s", strUsage.toStdString().c_str()); + fprintf(stdout, "%s\n", qPrintable(ui->helpMessageLabel->text())); } void HelpMessageDialog::showOrPrint() diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index 874daf6a7f..cc23420169 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -40,7 +40,7 @@ class HelpMessageDialog : public QDialog Q_OBJECT public: - explicit HelpMessageDialog(QWidget *parent); + explicit HelpMessageDialog(QWidget *parent, bool versionOnly); ~HelpMessageDialog(); void printToConsole(); @@ -48,9 +48,6 @@ public: private: Ui::HelpMessageDialog *ui; - QString header; - QString coreOptions; - QString uiOptions; private slots: void on_okButton_accepted(); From 97789d374c40f4f7fc8feb19c1235ca09ad2e06e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Jun 2014 16:02:29 +0200 Subject: [PATCH 169/336] util: Add function FormatParagraph to format paragraph to fixed-width This is to be used for the `-version` and `-help` messages. --- src/test/util_tests.cpp | 11 +++++++++++ src/util.cpp | 35 +++++++++++++++++++++++++++++++++++ src/util.h | 5 +++++ 3 files changed, 51 insertions(+) diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 0e53a57593..0b071361d8 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -351,4 +351,15 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32) BOOST_CHECK(!ParseInt32("32482348723847471234", NULL)); } +BOOST_AUTO_TEST_CASE(test_FormatParagraph) +{ + BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), ""); + BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test"); + BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), "test"); + BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test"); + BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest"); + BOOST_CHECK_EQUAL(FormatParagraph("testerde test ", 4, 0), "testerde\ntest"); + BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.cpp b/src/util.cpp index cccf2df484..3e3dabb678 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1407,3 +1407,38 @@ std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) ss << boost::posix_time::from_time_t(nTime); return ss.str(); } + +std::string FormatParagraph(const std::string in, size_t width, size_t indent) +{ + std::stringstream out; + size_t col = 0; + size_t ptr = 0; + while(ptr < in.size()) + { + // Find beginning of next word + ptr = in.find_first_not_of(' ', ptr); + if (ptr == std::string::npos) + break; + // Find end of next word + size_t endword = in.find_first_of(' ', ptr); + if (endword == std::string::npos) + endword = in.size(); + // Add newline and indentation if this wraps over the allowed width + if (col > 0) + { + if ((col + endword - ptr) > width) + { + out << '\n'; + for(size_t i=0; i Date: Wed, 11 Jun 2014 14:56:08 +0200 Subject: [PATCH 170/336] remove unused code from getblockchaininfo() --- src/rpcblockchain.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 5e0173dcf2..2a21fb462a 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -450,9 +450,6 @@ Value getblockchaininfo(const Array& params, bool fHelp) + HelpExampleRpc("getblockchaininfo", "") ); - proxyType proxy; - GetProxy(NET_IPV4, proxy); - Object obj; std::string chain = Params().DataDir(); if(chain.empty()) From c30329adfaa6d3e1e7150b05b69c4691248300b1 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Thu, 12 Jun 2014 00:36:53 +0200 Subject: [PATCH 171/336] Add testnet DNS seed of Alex Kotenko. --- src/chainparams.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 3f4d7f7064..1749dd6ff9 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -212,6 +212,7 @@ public: vFixedSeeds.clear(); vSeeds.clear(); + vSeeds.push_back(CDNSSeedData("alexykot.me", "testnet-seed.alexykot.me")); vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org")); vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me")); From 88df548dde280efac8eb33520f8192885455bc03 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 11 Jun 2014 23:20:37 -0400 Subject: [PATCH 172/336] base58: add paranoid return value checks --- src/base58.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 5975703887..1bd64684e5 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -114,9 +114,8 @@ std::string EncodeBase58Check(const std::vector& vchIn) { } bool DecodeBase58Check(const char* psz, std::vector& vchRet) { - if (!DecodeBase58(psz, vchRet)) - return false; - if (vchRet.size() < 4) + if (!DecodeBase58(psz, vchRet) || + (vchRet.size() < 4)) { vchRet.clear(); return false; @@ -154,8 +153,8 @@ void CBase58Data::SetData(const std::vector &vchVersionIn, const bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes) { std::vector vchTemp; - DecodeBase58Check(psz, vchTemp); - if (vchTemp.size() < nVersionBytes) { + bool rc58 = DecodeBase58Check(psz, vchTemp); + if ((!rc58) || (vchTemp.size() < nVersionBytes)) { vchData.clear(); vchVersion.clear(); return false; From f5ae6c98260fdd3c0ca203ce67c6467d9cdaea95 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 11 Jun 2014 12:23:49 +0200 Subject: [PATCH 173/336] add NetworkIDString() to chainparams - returns the BIP70 network string - use that new function in the core and GUI code and remove unused code and functions --- src/chainparams.cpp | 3 +++ src/chainparams.h | 3 +++ src/qt/clientmodel.cpp | 8 -------- src/qt/clientmodel.h | 2 -- src/qt/paymentserver.cpp | 13 +------------ src/qt/paymentserver.h | 1 - src/qt/rpcconsole.cpp | 2 +- src/rpcblockchain.cpp | 15 ++++++--------- 8 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1749dd6ff9..47136eeeea 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -99,6 +99,7 @@ class CMainParams : public CChainParams { public: CMainParams() { networkID = CChainParams::MAIN; + strNetworkID = "main"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. @@ -189,6 +190,7 @@ class CTestNetParams : public CMainParams { public: CTestNetParams() { networkID = CChainParams::TESTNET; + strNetworkID = "test"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. @@ -240,6 +242,7 @@ class CRegTestParams : public CTestNetParams { public: CRegTestParams() { networkID = CChainParams::REGTEST; + strNetworkID = "regtest"; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; pchMessageStart[2] = 0xb5; diff --git a/src/chainparams.h b/src/chainparams.h index 8370cc5690..6e09a2cba3 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -79,6 +79,8 @@ public: * until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } Network NetworkID() const { return networkID; } + /* Return the BIP70 network string (main, test or regtest) */ + std::string NetworkIDString() const { return strNetworkID; } const vector& DNSSeeds() const { return vSeeds; } const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } const vector& FixedSeeds() const { return vFixedSeeds; } @@ -102,6 +104,7 @@ protected: vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; Network networkID; + std::string strNetworkID; CBlock genesis; vector vFixedSeeds; bool fRequireRPCPassword; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 403b03378f..9c9565be67 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -142,14 +142,6 @@ void ClientModel::updateAlert(const QString &hash, int status) emit alertsChanged(getStatusBarWarnings()); } -QString ClientModel::getNetworkName() const -{ - QString netname(QString::fromStdString(Params().DataDir())); - if(netname.isEmpty()) - netname = "main"; - return netname; -} - bool ClientModel::inInitialBlockDownload() const { return IsInitialBlockDownload(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 9c9a35b654..c7bd60bd41 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -56,8 +56,6 @@ public: double getVerificationProgress() const; QDateTime getLastBlockDate() const; - //! Return network (main, testnet3, regtest) - QString getNetworkName() const; //! Return true if core is doing initial block download bool inInitialBlockDownload() const; //! Return true if core is importing blocks diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 9241f9dc3c..eb6ab879aa 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -490,17 +490,6 @@ bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPl return request.parse(data); } -std::string PaymentServer::mapNetworkIdToName(CChainParams::Network networkId) -{ - if (networkId == CChainParams::MAIN) - return "main"; - if (networkId == CChainParams::TESTNET) - return "test"; - if (networkId == CChainParams::REGTEST) - return "regtest"; - return ""; -} - bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient) { if (!optionsModel) @@ -510,7 +499,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins const payments::PaymentDetails& details = request.getDetails(); // Payment request network matches client network? - if (details.network() != mapNetworkIdToName(Params().NetworkID())) + if (details.network() != Params().NetworkIDString()) { emit message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), CClientUIInterface::MSG_ERROR); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index d6949a47ce..d84d09c57d 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -118,7 +118,6 @@ protected: private: static bool readPaymentRequest(const QString& filename, PaymentRequestPlus& request); - std::string mapNetworkIdToName(CChainParams::Network networkId); bool processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient); void fetchRequest(const QUrl& url); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 199050cc57..f7491f4a42 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -316,7 +316,7 @@ void RPCConsole::setClientModel(ClientModel *model) ui->buildDate->setText(model->formatBuildDate()); ui->startupTime->setText(model->formatClientStartupTime()); - ui->networkName->setText(model->getNetworkName()); + ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); } } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 2a21fb462a..0fabc86872 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -451,14 +451,11 @@ Value getblockchaininfo(const Array& params, bool fHelp) ); Object obj; - std::string chain = Params().DataDir(); - if(chain.empty()) - chain = "main"; - obj.push_back(Pair("chain", chain)); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); - obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(chainActive.Tip()))); - obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); + obj.push_back(Pair("chain", Params().NetworkIDString())); + obj.push_back(Pair("blocks", (int)chainActive.Height())); + obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); + obj.push_back(Pair("difficulty", (double)GetDifficulty())); + obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(chainActive.Tip()))); + obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); return obj; } From e5ee8f016ebb1db1bac3c4d0dd895249a4a17a1d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 12 Jun 2014 13:52:15 +0200 Subject: [PATCH 174/336] Remove -beta suffix It conflicts with our normal naming of releases/builds. Fixes #4221. --- src/version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.cpp b/src/version.cpp index 51e34aa9c9..d86caa3ac2 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -12,7 +12,7 @@ const std::string CLIENT_NAME("Satoshi"); // Client version number -#define CLIENT_VERSION_SUFFIX "-beta" +#define CLIENT_VERSION_SUFFIX "" // The following part of the code determines the CLIENT_BUILD variable. From 18116b06c177acb97ad1051a0d5da92251adf2dc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Jun 2014 09:42:42 +0200 Subject: [PATCH 175/336] Ignore too-long redeemScripts while loading wallet This avoids that long redeemScripts that were grandfathered in prevent the wallet from loading. Fixes #4313. --- src/wallet.cpp | 16 ++++++++++++++++ src/wallet.h | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/wallet.cpp b/src/wallet.cpp index ef0b442e1a..400c966a95 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -128,6 +128,22 @@ bool CWallet::AddCScript(const CScript& redeemScript) return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); } +bool CWallet::LoadCScript(const CScript& redeemScript) +{ + /* A sanity check was added in pull #3843 to avoid adding redeemScripts + * that never can be redeemed. However, old wallets may still contain + * these. Do not add them to the wallet and warn. */ + if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) + { + std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString(); + LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n", + __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); + return true; + } + + return CCryptoKeyStore::AddCScript(redeemScript); +} + bool CWallet::Unlock(const SecureString& strWalletPassphrase) { CCrypter crypter; diff --git a/src/wallet.h b/src/wallet.h index 274c31157c..7df656fc25 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -211,7 +211,7 @@ public: // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); bool AddCScript(const CScript& redeemScript); - bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); } + bool LoadCScript(const CScript& redeemScript); /// Adds a destination data tuple to the store, and saves it to disk bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value); From 45615af26fe374fa996c116984a05f0a632a0e79 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Jun 2014 16:02:46 +0200 Subject: [PATCH 176/336] Add 'about' information to `-version` output Adds a copyright and attribution message to the `-version` output (the same as shown in the About dialog in the GUI). Move the message to a function LicenseInfo in init.cpp. --- src/bitcoind.cpp | 6 +++- src/init.cpp | 13 ++++++- src/init.h | 3 ++ src/qt/forms/aboutdialog.ui | 70 +++---------------------------------- src/qt/utilitydialog.cpp | 20 +++++++---- 5 files changed, 38 insertions(+), 74 deletions(-) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 99dc9d726d..b7d8ee7f90 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -87,7 +87,11 @@ bool AppInit(int argc, char* argv[]) { std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n"; - if (!mapArgs.count("-version")) + if (mapArgs.count("-version")) + { + strUsage += LicenseInfo(); + } + else { strUsage += "\n" + _("Usage:") + "\n" + " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" + diff --git a/src/init.cpp b/src/init.cpp index 528c3df064..39453da9c8 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -195,7 +195,6 @@ bool static Bind(const CService &addr, unsigned int flags) { return true; } -// Core-specific options shared between UI, daemon and RPC client std::string HelpMessage(HelpMessageMode hmm) { string strUsage = _("Options:") + "\n"; @@ -330,6 +329,18 @@ std::string HelpMessage(HelpMessageMode hmm) return strUsage; } +std::string LicenseInfo() +{ + return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" + + "\n" + + FormatParagraph(_("This is experimental software.")) + "\n" + + "\n" + + FormatParagraph(_("Distributed under the MIT/X11 software license, see the accompanying file COPYING or .")) + "\n" + + "\n" + + FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.")) + + "\n"; +} + struct CImportingNow { CImportingNow() { diff --git a/src/init.h b/src/init.h index 4a967bea37..52daa47616 100644 --- a/src/init.h +++ b/src/init.h @@ -28,6 +28,9 @@ enum HelpMessageMode HMM_BITCOIN_QT }; +/** Help for options shared between UI and daemon (for -help) */ std::string HelpMessage(HelpMessageMode mode); +/** Returns licensing information (for -version) */ +std::string LicenseInfo(); #endif diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index fec63f737a..51dabf2c30 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -43,76 +43,14 @@ - - - - - IBeamCursor - - - <b>Bitcoin Core</b> version - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - IBeamCursor - - - 0.3.666-beta - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + IBeamCursor - Copyright &copy; 2009-YYYY The Bitcoin Core developers - - - Qt::RichText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - IBeamCursor - - - -This is experimental software. - -Distributed under the MIT/X11 software license, see the accompanying file COPYING or <a href="http://www.opensource.org/licenses/mit-license.php">http://www.opensource.org/licenses/mit-license.php</a>. - -This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (<a href="https://www.openssl.org/">https://www.openssl.org/</a>) and cryptographic software written by Eric Young (<a href="mailto:eay@cryptsoft.com">eay@cryptsoft.com</a>) and UPnP software written by Thomas Bernard. + +(placeholder for version message) + Qt::RichText diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 435c6a4368..a34ebd3a37 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -16,6 +16,7 @@ #include "util.h" #include +#include #include /** "About" dialog box */ @@ -24,16 +25,13 @@ AboutDialog::AboutDialog(QWidget *parent) : ui(new Ui::AboutDialog) { ui->setupUi(this); - - // Set current copyright year - ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers")); } void AboutDialog::setModel(ClientModel *model) { if(model) { - QString version = model->formatFullVersion(); + QString version = tr("Bitcoin Core") + " " + tr("version") + " " + model->formatFullVersion(); /* On x86 add a bit specifier to the version so that users can distinguish between * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. */ @@ -42,7 +40,17 @@ void AboutDialog::setModel(ClientModel *model) #elif defined(__i386__ ) version += " " + tr("(%1-bit)").arg(32); #endif - ui->versionLabel->setText(version); + + /// HTML-format the license message from the core + QString licenseInfo = QString::fromStdString(LicenseInfo()); + // Make URLs clickable + QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2); + uri.setMinimal(true); // use non-greedy matching + licenseInfo = licenseInfo.replace(uri, "\\1"); + // Replace newlines with HTML breaks + licenseInfo = licenseInfo.replace("\n\n", "

"); + + ui->versionLabel->setText(version + "

" + licenseInfo); } } @@ -81,7 +89,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool versionOnly) : // Set help message text if(versionOnly) - ui->helpMessageLabel->setText(version); + ui->helpMessageLabel->setText(version + "\n" + QString::fromStdString(LicenseInfo())); else ui->helpMessageLabel->setText(version + "\n" + header + "\n" + coreOptions + "\n" + uiOptions); } From 5c97aae6da813ce4873651b31f75b26ea6f1352f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 11 Jun 2014 21:44:47 +0200 Subject: [PATCH 177/336] qt: Unify AboutDialog and HelpMessageDialog They share so much code and functionality that they may as well be one class. --- src/Makefile.qt.include | 1 - src/qt/bitcoingui.cpp | 3 +- src/qt/forms/aboutdialog.ui | 130 ------------------------------ src/qt/forms/helpmessagedialog.ui | 7 +- src/qt/utilitydialog.cpp | 117 +++++++++++---------------- src/qt/utilitydialog.h | 22 +---- 6 files changed, 53 insertions(+), 227 deletions(-) delete mode 100644 src/qt/forms/aboutdialog.ui diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 72c7486258..647434e1ef 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -76,7 +76,6 @@ QT_TS = \ qt/locale/bitcoin_zh_TW.ts QT_FORMS_UI = \ - qt/forms/aboutdialog.ui \ qt/forms/addressbookpage.ui \ qt/forms/askpassphrasedialog.ui \ qt/forms/coincontroldialog.ui \ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 847a3ab8f1..30f5ec8939 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -549,8 +549,7 @@ void BitcoinGUI::aboutClicked() if(!clientModel) return; - AboutDialog dlg(this); - dlg.setModel(clientModel); + HelpMessageDialog dlg(this, true); dlg.exec(); } diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui deleted file mode 100644 index 51dabf2c30..0000000000 --- a/src/qt/forms/aboutdialog.ui +++ /dev/null @@ -1,130 +0,0 @@ - - - AboutDialog - - - - 0 - 0 - 593 - 319 - - - - About Bitcoin Core - - - - - - - 0 - 0 - - - - :/images/about - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - IBeamCursor - - - -(placeholder for version message) - - - - Qt::RichText - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Ok - - - - - - - - - - - - - buttonBox - accepted() - AboutDialog - accept() - - - 20 - 20 - - - 20 - 20 - - - - - buttonBox - rejected() - AboutDialog - reject() - - - 20 - 20 - - - 20 - 20 - - - - - diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui index f68fea7e64..d8ab27c238 100644 --- a/src/qt/forms/helpmessagedialog.ui +++ b/src/qt/forms/helpmessagedialog.ui @@ -16,7 +16,7 @@
- Bitcoin Core - Command-line options + Bitcoin Core - Command-line options @@ -54,11 +54,6 @@ - - - Terminal - - IBeamCursor diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index a34ebd3a37..eb647d0170 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -4,7 +4,6 @@ #include "utilitydialog.h" -#include "ui_aboutdialog.h" #include "ui_helpmessagedialog.h" #include "bitcoingui.h" @@ -19,53 +18,8 @@ #include #include -/** "About" dialog box */ -AboutDialog::AboutDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::AboutDialog) -{ - ui->setupUi(this); -} - -void AboutDialog::setModel(ClientModel *model) -{ - if(model) - { - QString version = tr("Bitcoin Core") + " " + tr("version") + " " + model->formatFullVersion(); - /* On x86 add a bit specifier to the version so that users can distinguish between - * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. - */ -#if defined(__x86_64__) - version += " " + tr("(%1-bit)").arg(64); -#elif defined(__i386__ ) - version += " " + tr("(%1-bit)").arg(32); -#endif - - /// HTML-format the license message from the core - QString licenseInfo = QString::fromStdString(LicenseInfo()); - // Make URLs clickable - QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2); - uri.setMinimal(true); // use non-greedy matching - licenseInfo = licenseInfo.replace(uri, "\\1"); - // Replace newlines with HTML breaks - licenseInfo = licenseInfo.replace("\n\n", "

"); - - ui->versionLabel->setText(version + "

" + licenseInfo); - } -} - -AboutDialog::~AboutDialog() -{ - delete ui; -} - -void AboutDialog::on_buttonBox_accepted() -{ - close(); -} - -/** "Help message" dialog box */ -HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool versionOnly) : +/** "Help message" or "About" dialog box */ +HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) : QDialog(parent), ui(new Ui::HelpMessageDialog) { @@ -73,25 +27,52 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool versionOnly) : GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this); QString version = tr("Bitcoin Core") + " " + tr("version") + " " + QString::fromStdString(FormatFullVersion()); - QString header = tr("Usage:") + "\n" + - " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; + /* On x86 add a bit specifier to the version so that users can distinguish between + * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious. + */ +#if defined(__x86_64__) + version += " " + tr("(%1-bit)").arg(64); +#elif defined(__i386__ ) + version += " " + tr("(%1-bit)").arg(32); +#endif - QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); + if (about) + { + setWindowTitle(tr("About Bitcoin Core")); - QString uiOptions = tr("UI options") + ":\n" + - " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" + - " -lang= " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + - " -min " + tr("Start minimized") + "\n" + - " -rootcertificates= " + tr("Set SSL root certificates for payment request (default: -system-)") + "\n" + - " -splash " + tr("Show splash screen on startup (default: 1)"); + /// HTML-format the license message from the core + QString licenseInfo = QString::fromStdString(LicenseInfo()); + QString licenseInfoHTML = licenseInfo; + // Make URLs clickable + QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2); + uri.setMinimal(true); // use non-greedy matching + licenseInfoHTML.replace(uri, "\\1"); + // Replace newlines with HTML breaks + licenseInfoHTML.replace("\n\n", "

"); - ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont()); + ui->helpMessageLabel->setTextFormat(Qt::RichText); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + text = version + "\n" + licenseInfo; + ui->helpMessageLabel->setText(version + "

" + licenseInfoHTML); + ui->helpMessageLabel->setWordWrap(true); + } else { + setWindowTitle(tr("Command-line options")); + QString header = tr("Usage:") + "\n" + + " bitcoin-qt [" + tr("command-line options") + "] " + "\n"; - // Set help message text - if(versionOnly) - ui->helpMessageLabel->setText(version + "\n" + QString::fromStdString(LicenseInfo())); - else - ui->helpMessageLabel->setText(version + "\n" + header + "\n" + coreOptions + "\n" + uiOptions); + QString coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT)); + + QString uiOptions = tr("UI options") + ":\n" + + " -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n" + + " -lang= " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" + + " -min " + tr("Start minimized") + "\n" + + " -rootcertificates= " + tr("Set SSL root certificates for payment request (default: -system-)") + "\n" + + " -splash " + tr("Show splash screen on startup (default: 1)"); + + ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont()); + text = version + "\n" + header + "\n" + coreOptions + "\n" + uiOptions; + ui->helpMessageLabel->setText(text); + } } HelpMessageDialog::~HelpMessageDialog() @@ -103,17 +84,17 @@ HelpMessageDialog::~HelpMessageDialog() void HelpMessageDialog::printToConsole() { // On other operating systems, the expected action is to print the message to the console. - fprintf(stdout, "%s\n", qPrintable(ui->helpMessageLabel->text())); + fprintf(stdout, "%s\n", qPrintable(text)); } void HelpMessageDialog::showOrPrint() { #if defined(WIN32) - // On Windows, show a message box, as there is no stderr/stdout in windowed applications - exec(); + // On Windows, show a message box, as there is no stderr/stdout in windowed applications + exec(); #else - // On other operating systems, print help text to console - printToConsole(); + // On other operating systems, print help text to console + printToConsole(); #endif } diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index cc23420169..154bb70b8b 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -12,35 +12,16 @@ class BitcoinGUI; class ClientModel; namespace Ui { - class AboutDialog; class HelpMessageDialog; } -/** "About" dialog box */ -class AboutDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AboutDialog(QWidget *parent); - ~AboutDialog(); - - void setModel(ClientModel *model); - -private: - Ui::AboutDialog *ui; - -private slots: - void on_buttonBox_accepted(); -}; - /** "Help message" dialog box */ class HelpMessageDialog : public QDialog { Q_OBJECT public: - explicit HelpMessageDialog(QWidget *parent, bool versionOnly); + explicit HelpMessageDialog(QWidget *parent, bool about); ~HelpMessageDialog(); void printToConsole(); @@ -48,6 +29,7 @@ public: private: Ui::HelpMessageDialog *ui; + QString text; private slots: void on_okButton_accepted(); From 0cafb630254c6459ea02f6fc47e1c37bb81a1238 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 12 Jun 2014 22:26:46 -0400 Subject: [PATCH 178/336] bitcoin-cli, rpcclient: prefer EXIT_FAILURE cstdlib constant A more complex construction via abs() yields the same end result. Rebased-From: 34ff109 Rebased-By: Wladimir J. van der Laan --- src/bitcoin-cli.cpp | 8 ++++---- src/rpcclient.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 0bb71329f5..0c7d6fe5ac 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -65,17 +65,17 @@ int main(int argc, char* argv[]) try { if(!AppInitRPC(argc, argv)) - return abs(RPC_MISC_ERROR); + return EXIT_FAILURE; } catch (std::exception& e) { PrintExceptionContinue(&e, "AppInitRPC()"); - return abs(RPC_MISC_ERROR); + return EXIT_FAILURE; } catch (...) { PrintExceptionContinue(NULL, "AppInitRPC()"); - return abs(RPC_MISC_ERROR); + return EXIT_FAILURE; } - int ret = abs(RPC_MISC_ERROR); + int ret = EXIT_FAILURE; try { ret = CommandLineRPC(argc, argv); diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index b89a95ad11..1a5b3f7412 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -234,7 +234,7 @@ int CommandLineRPC(int argc, char *argv[]) } catch (std::exception& e) { strPrint = string("error: ") + e.what(); - nRet = abs(RPC_MISC_ERROR); + nRet = EXIT_FAILURE; } catch (...) { PrintExceptionContinue(NULL, "CommandLineRPC()"); From b750cf1fb9b6529ab1761b22947677ca78a2c626 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 26 May 2014 11:38:44 +0200 Subject: [PATCH 179/336] Remove cli functionality from bitcoind As it says on the tin. It was deprecated in version 0.9, and at some point it should be removed. Removes the dependency of bitcoind on libbitcoin-cli.a. Move some functions that used to be shared but are now only used in bitcoin-cli.cpp to that file. After this change, an error is printed (and exit code 1 is returned) when the user tries to send RPC commands using bitcoind. --- src/Makefile.am | 1 - src/bitcoin-cli.cpp | 158 ++++++++++++++++++++++++++++++++++++++- src/bitcoind.cpp | 12 +-- src/rpcclient.cpp | 175 -------------------------------------------- src/rpcclient.h | 10 --- 5 files changed, 160 insertions(+), 196 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3016be47b9..0a76829197 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -171,7 +171,6 @@ nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h # bitcoind binary # bitcoind_LDADD = \ libbitcoin_server.a \ - libbitcoin_cli.a \ libbitcoin_common.a \ $(LIBLEVELDB) \ $(LIBMEMENV) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 0c7d6fe5ac..c7327fd7c9 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,6 +12,32 @@ #include +using namespace boost; +using namespace boost::asio; +using namespace json_spirit; + +std::string HelpMessageCli() +{ + string strUsage; + strUsage += _("Options:") + "\n"; + strUsage += " -? " + _("This help message") + "\n"; + strUsage += " -conf= " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; + strUsage += " -datadir= " + _("Specify data directory") + "\n"; + strUsage += " -testnet " + _("Use the test network") + "\n"; + strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be " + "solved instantly. This is intended for regression testing tools and app development.") + "\n"; + strUsage += " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n"; + strUsage += " -rpcport= " + _("Connect to JSON-RPC on (default: 8332 or testnet: 18332)") + "\n"; + strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; + strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; + strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; + + strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; + strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; + + return strUsage; +} + ////////////////////////////////////////////////////////////////////////////// // // Start @@ -49,7 +75,7 @@ static bool AppInitRPC(int argc, char* argv[]) " bitcoin-cli [options] help " + _("List commands") + "\n" + " bitcoin-cli [options] help " + _("Get help for a command") + "\n"; - strUsage += "\n" + HelpMessageCli(true); + strUsage += "\n" + HelpMessageCli(); } fprintf(stdout, "%s", strUsage.c_str()); @@ -58,6 +84,136 @@ static bool AppInitRPC(int argc, char* argv[]) return true; } +Object CallRPC(const string& strMethod, const Array& params) +{ + if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") + throw runtime_error(strprintf( + _("You must set rpcpassword= in the configuration file:\n%s\n" + "If the file does not exist, create it with owner-readable-only file permissions."), + GetConfigFile().string().c_str())); + + // Connect to localhost + bool fUseSSL = GetBoolArg("-rpcssl", false); + asio::io_service io_service; + ssl::context context(io_service, ssl::context::sslv23); + context.set_options(ssl::context::no_sslv2); + asio::ssl::stream sslStream(io_service, context); + SSLIOStreamDevice d(sslStream, fUseSSL); + iostreams::stream< SSLIOStreamDevice > stream(d); + + bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started + do { + bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); + if (fConnected) break; + if (fWait) + MilliSleep(1000); + else + throw runtime_error("couldn't connect to server"); + } while (fWait); + + // HTTP basic authentication + string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); + map mapRequestHeaders; + mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; + + // Send request + string strRequest = JSONRPCRequest(strMethod, params, 1); + string strPost = HTTPPost(strRequest, mapRequestHeaders); + stream << strPost << std::flush; + + // Receive HTTP reply status + int nProto = 0; + int nStatus = ReadHTTPStatus(stream, nProto); + + // Receive HTTP reply message headers and body + map mapHeaders; + string strReply; + ReadHTTPMessage(stream, mapHeaders, strReply, nProto); + + if (nStatus == HTTP_UNAUTHORIZED) + throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); + else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) + throw runtime_error(strprintf("server returned HTTP error %d", nStatus)); + else if (strReply.empty()) + throw runtime_error("no response from server"); + + // Parse reply + Value valReply; + if (!read_string(strReply, valReply)) + throw runtime_error("couldn't parse reply from server"); + const Object& reply = valReply.get_obj(); + if (reply.empty()) + throw runtime_error("expected reply to have result, error and id properties"); + + return reply; +} + +int CommandLineRPC(int argc, char *argv[]) +{ + string strPrint; + int nRet = 0; + try + { + // Skip switches + while (argc > 1 && IsSwitchChar(argv[1][0])) + { + argc--; + argv++; + } + + // Method + if (argc < 2) + throw runtime_error("too few parameters"); + string strMethod = argv[1]; + + // Parameters default to strings + std::vector strParams(&argv[2], &argv[argc]); + Array params = RPCConvertValues(strMethod, strParams); + + // Execute + Object reply = CallRPC(strMethod, params); + + // Parse reply + const Value& result = find_value(reply, "result"); + const Value& error = find_value(reply, "error"); + + if (error.type() != null_type) + { + // Error + strPrint = "error: " + write_string(error, false); + int code = find_value(error.get_obj(), "code").get_int(); + nRet = abs(code); + } + else + { + // Result + if (result.type() == null_type) + strPrint = ""; + else if (result.type() == str_type) + strPrint = result.get_str(); + else + strPrint = write_string(result, true); + } + } + catch (boost::thread_interrupted) { + throw; + } + catch (std::exception& e) { + strPrint = string("error: ") + e.what(); + nRet = EXIT_FAILURE; + } + catch (...) { + PrintExceptionContinue(NULL, "CommandLineRPC()"); + throw; + } + + if (strPrint != "") + { + fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); + } + return nRet; +} + int main(int argc, char* argv[]) { SetupEnvironment(); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index b7d8ee7f90..880955481b 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "rpcserver.h" -#include "rpcclient.h" #include "init.h" #include "main.h" #include "noui.h" @@ -94,14 +93,9 @@ bool AppInit(int argc, char* argv[]) else { strUsage += "\n" + _("Usage:") + "\n" + - " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n" + - _("Usage (deprecated, use bitcoin-cli):") + "\n" + - " bitcoind [options] [params] " + _("Send command to Bitcoin Core") + "\n" + - " bitcoind [options] help " + _("List commands") + "\n" + - " bitcoind [options] help " + _("Get help for a command") + "\n"; + " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n"; strUsage += "\n" + HelpMessage(HMM_BITCOIND); - strUsage += "\n" + HelpMessageCli(false); } fprintf(stdout, "%s", strUsage.c_str()); @@ -116,8 +110,8 @@ bool AppInit(int argc, char* argv[]) if (fCommandLine) { - int ret = CommandLineRPC(argc, argv); - exit(ret); + fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n"); + exit(1); } #ifndef WIN32 fDaemon = GetBoolArg("-daemon", false); diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 1a5b3f7412..3a06e33016 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -12,86 +12,9 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "json/json_spirit_writer_template.h" - using namespace std; -using namespace boost; -using namespace boost::asio; using namespace json_spirit; -Object CallRPC(const string& strMethod, const Array& params) -{ - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "") - throw runtime_error(strprintf( - _("You must set rpcpassword= in the configuration file:\n%s\n" - "If the file does not exist, create it with owner-readable-only file permissions."), - GetConfigFile().string().c_str())); - - // Connect to localhost - bool fUseSSL = GetBoolArg("-rpcssl", false); - asio::io_service io_service; - ssl::context context(io_service, ssl::context::sslv23); - context.set_options(ssl::context::no_sslv2); - asio::ssl::stream sslStream(io_service, context); - SSLIOStreamDevice d(sslStream, fUseSSL); - iostreams::stream< SSLIOStreamDevice > stream(d); - - bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started - do { - bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); - if (fConnected) break; - if (fWait) - MilliSleep(1000); - else - throw runtime_error("couldn't connect to server"); - } while (fWait); - - // HTTP basic authentication - string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); - map mapRequestHeaders; - mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64; - - // Send request - string strRequest = JSONRPCRequest(strMethod, params, 1); - string strPost = HTTPPost(strRequest, mapRequestHeaders); - stream << strPost << std::flush; - - // Receive HTTP reply status - int nProto = 0; - int nStatus = ReadHTTPStatus(stream, nProto); - - // Receive HTTP reply message headers and body - map mapHeaders; - string strReply; - ReadHTTPMessage(stream, mapHeaders, strReply, nProto); - - if (nStatus == HTTP_UNAUTHORIZED) - throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); - else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) - throw runtime_error(strprintf("server returned HTTP error %d", nStatus)); - else if (strReply.empty()) - throw runtime_error("no response from server"); - - // Parse reply - Value valReply; - if (!read_string(strReply, valReply)) - throw runtime_error("couldn't parse reply from server"); - const Object& reply = valReply.get_obj(); - if (reply.empty()) - throw runtime_error("expected reply to have result, error and id properties"); - - return reply; -} - template void ConvertTo(Value& value, bool fAllowNull=false) { @@ -182,101 +105,3 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1 && IsSwitchChar(argv[1][0])) - { - argc--; - argv++; - } - - // Method - if (argc < 2) - throw runtime_error("too few parameters"); - string strMethod = argv[1]; - - // Parameters default to strings - std::vector strParams(&argv[2], &argv[argc]); - Array params = RPCConvertValues(strMethod, strParams); - - // Execute - Object reply = CallRPC(strMethod, params); - - // Parse reply - const Value& result = find_value(reply, "result"); - const Value& error = find_value(reply, "error"); - - if (error.type() != null_type) - { - // Error - strPrint = "error: " + write_string(error, false); - int code = find_value(error.get_obj(), "code").get_int(); - nRet = abs(code); - } - else - { - // Result - if (result.type() == null_type) - strPrint = ""; - else if (result.type() == str_type) - strPrint = result.get_str(); - else - strPrint = write_string(result, true); - } - } - catch (boost::thread_interrupted) { - throw; - } - catch (std::exception& e) { - strPrint = string("error: ") + e.what(); - nRet = EXIT_FAILURE; - } - catch (...) { - PrintExceptionContinue(NULL, "CommandLineRPC()"); - throw; - } - - if (strPrint != "") - { - fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); - } - return nRet; -} - -std::string HelpMessageCli(bool mainProgram) -{ - string strUsage; - if(mainProgram) - { - strUsage += _("Options:") + "\n"; - strUsage += " -? " + _("This help message") + "\n"; - strUsage += " -conf= " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; - strUsage += " -datadir= " + _("Specify data directory") + "\n"; - strUsage += " -testnet " + _("Use the test network") + "\n"; - strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be " - "solved instantly. This is intended for regression testing tools and app development.") + "\n"; - } else { - strUsage += _("RPC client options:") + "\n"; - } - - strUsage += " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n"; - strUsage += " -rpcport= " + _("Connect to JSON-RPC on (default: 8332 or testnet: 18332)") + "\n"; - strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; - - if(mainProgram) - { - strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; - strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; - - strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; - strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n"; - } - - return strUsage; -} - diff --git a/src/rpcclient.h b/src/rpcclient.h index e101d22ec5..840890e34b 100644 --- a/src/rpcclient.h +++ b/src/rpcclient.h @@ -10,16 +10,6 @@ #include "json/json_spirit_utils.h" #include "json/json_spirit_writer_template.h" -int CommandLineRPC(int argc, char *argv[]); - json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams); -/** Show help message for bitcoin-cli. - * The mainProgram argument is used to determine whether to show this message as main program - * (and include some common options) or as sub-header of another help message. - * - * @note the argument can be removed once bitcoin-cli functionality is removed from bitcoind - */ -std::string HelpMessageCli(bool mainProgram); - #endif From 676301879755588cb32ed6cd95a84f4da1d4f83f Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Thu, 12 Jun 2014 14:29:18 +0200 Subject: [PATCH 180/336] [Qt] rename In:/Out: to Received/Sent in traffic tab - collides with In:/Out: used for displaying number of connections when translating --- src/qt/forms/rpcconsole.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 1e574e8527..7158b65c2d 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -559,7 +559,7 @@ - In: + Received @@ -639,7 +639,7 @@ - Out: + Sent From 1569353b8aa535f086833acb6223650972c89790 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 7 May 2014 18:10:48 +0000 Subject: [PATCH 181/336] Add `-stopafterblockimport` option Stop after importing blocks. This can be useful for development and trouble shooting. --- src/init.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 39453da9c8..0a0b479fa2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -273,6 +273,7 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -dropmessagestest= " + _("Randomly drop 1 of every network messages") + "\n"; strUsage += " -fuzzmessagestest= " + _("Randomly fuzz 1 of every network messages") + "\n"; strUsage += " -flushwallet " + _("Run a thread to flush wallet periodically (default: 1)") + "\n"; + strUsage += " -stopafterblockimport " + _("Stop running after importing blocks from disk (default: 0)") + "\n"; } strUsage += " -debug= " + _("Output debugging information (default: 0, supplying is optional)") + "\n"; strUsage += " " + _("If is not supplied, output all debugging information.") + "\n"; @@ -404,6 +405,11 @@ void ThreadImport(std::vector vImportFiles) LogPrintf("Warning: Could not open blocks file %s\n", path.string()); } } + + if (GetBoolArg("-stopafterblockimport", false)) { + LogPrintf("Stopping after block import\n"); + StartShutdown(); + } } /** Sanity checks From 09eb201b1b3ed808e5167245149f5635d4eaf6f9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 16 Jun 2014 16:30:38 +0200 Subject: [PATCH 182/336] Remove `using namespace std` from header file It's considered bad form to import things into the global namespace in a header. Put it in the cpp files where it is needed instead. --- src/bitcoin-cli.cpp | 1 + src/chainparams.cpp | 1 + src/chainparams.h | 22 ++++++++++------------ src/miner.cpp | 2 ++ src/qt/paymentrequestplus.cpp | 1 + src/qt/paymentrequestplus.h | 2 +- src/qt/paymentserver.cpp | 1 + src/qt/transactiondesc.cpp | 2 ++ src/qt/walletmodel.cpp | 2 ++ 9 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index c7327fd7c9..40b45415c4 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,6 +12,7 @@ #include +using namespace std; using namespace boost; using namespace boost::asio; using namespace json_spirit; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 47136eeeea..6b2cfa1d1f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -10,6 +10,7 @@ #include +using namespace std; using namespace boost::assign; // diff --git a/src/chainparams.h b/src/chainparams.h index 6e09a2cba3..28a51cbb0c 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -12,13 +12,11 @@ #include -using namespace std; - typedef unsigned char MessageStartChars[MESSAGE_START_SIZE]; struct CDNSSeedData { - string name, host; - CDNSSeedData(const string &strName, const string &strHost) : name(strName), host(strHost) {} + std::string name, host; + CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} }; /** @@ -51,7 +49,7 @@ public: const uint256& HashGenesisBlock() const { return hashGenesisBlock; } const MessageStartChars& MessageStart() const { return pchMessageStart; } - const vector& AlertKey() const { return vAlertPubKey; } + const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; } @@ -74,16 +72,16 @@ public: bool RequireStandard() const { return fRequireStandard; } /* Make standard checks */ bool RPCisTestNet() const { return fRPCisTestNet; } - const string& DataDir() const { return strDataDir; } + const std::string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } Network NetworkID() const { return networkID; } /* Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } - const vector& DNSSeeds() const { return vSeeds; } + const std::vector& DNSSeeds() const { return vSeeds; } const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } - const vector& FixedSeeds() const { return vFixedSeeds; } + const std::vector& FixedSeeds() const { return vFixedSeeds; } int RPCPort() const { return nRPCPort; } protected: CChainParams() {} @@ -91,7 +89,7 @@ protected: uint256 hashGenesisBlock; MessageStartChars pchMessageStart; // Raw pub key bytes for the broadcast alert signing key. - vector vAlertPubKey; + std::vector vAlertPubKey; int nDefaultPort; int nRPCPort; uint256 bnProofOfWorkLimit; @@ -99,14 +97,14 @@ protected: int nEnforceBlockUpgradeMajority; int nRejectBlockOutdatedMajority; int nToCheckBlockUpgradeMajority; - string strDataDir; + std::string strDataDir; int nMinerThreads; - vector vSeeds; + std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; Network networkID; std::string strNetworkID; CBlock genesis; - vector vFixedSeeds; + std::vector vFixedSeeds; bool fRequireRPCPassword; bool fMiningRequiresPeers; bool fDefaultCheckMemPool; diff --git a/src/miner.cpp b/src/miner.cpp index a0a728fb81..87779efbbd 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -11,6 +11,8 @@ #ifdef ENABLE_WALLET #include "wallet.h" #endif + +using namespace std; ////////////////////////////////////////////////////////////////////////////// // // BitcoinMiner diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index e369734a98..464f995eb6 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -17,6 +17,7 @@ #include #include +using namespace std; class SSLVerifyError : public std::runtime_error { diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index 8c126b1fad..3c4861a4d4 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -24,7 +24,7 @@ public: PaymentRequestPlus() { } bool parse(const QByteArray& data); - bool SerializeToString(string* output) const; + bool SerializeToString(std::string* output) const; bool IsInitialized() const; QString getPKIType() const; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index eb6ab879aa..49923a1afc 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -44,6 +44,7 @@ #include #endif +using namespace std; using namespace boost; const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 0cfcb048c8..61da3373fd 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -18,6 +18,8 @@ #include #include +using namespace std; + QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { AssertLockHeld(cs_main); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 87ff3db584..2f633a26c8 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -24,6 +24,8 @@ #include #include +using namespace std; + WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), transactionTableModel(0), From 77cbd4623e171ee9c48ada8a421295ed2c8e6c7c Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Fri, 14 Feb 2014 18:27:15 +0100 Subject: [PATCH 183/336] Let -zapwallettxes recover transaction meta data --- qa/rpc-tests/util.sh | 8 ++ qa/rpc-tests/zapwallettxes.sh | 161 ++++++++++++++++++++++++++++++++++ src/init.cpp | 34 ++++++- src/wallet.cpp | 4 +- src/wallet.h | 2 +- src/walletdb.cpp | 10 ++- src/walletdb.h | 4 +- 7 files changed, 212 insertions(+), 11 deletions(-) create mode 100755 qa/rpc-tests/zapwallettxes.sh diff --git a/qa/rpc-tests/util.sh b/qa/rpc-tests/util.sh index 1e7bd6a7ee..b726ef627f 100644 --- a/qa/rpc-tests/util.sh +++ b/qa/rpc-tests/util.sh @@ -38,6 +38,10 @@ function AssertEqual { if (( $( echo "$1 == $2" | bc ) == 0 )) then echoerr "AssertEqual: $1 != $2" + declare -f CleanUp > /dev/null 2>&1 + if [[ $? -eq 0 ]] ; then + CleanUp + fi exit 1 fi } @@ -49,6 +53,10 @@ function CheckBalance { if (( $( echo "$B == $EXPECT" | bc ) == 0 )) then echoerr "bad balance: $B (expected $2)" + declare -f CleanUp > /dev/null 2>&1 + if [[ $? -eq 0 ]] ; then + CleanUp + fi exit 1 fi } diff --git a/qa/rpc-tests/zapwallettxes.sh b/qa/rpc-tests/zapwallettxes.sh new file mode 100755 index 0000000000..bc52a7dacd --- /dev/null +++ b/qa/rpc-tests/zapwallettxes.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +# Test -zapwallettxes= + +if [ $# -lt 1 ]; then + echo "Usage: $0 path_to_binaries" + echo "e.g. $0 ../../src" + exit 1 +fi + +set -f + +BITCOIND=${1}/bitcoind +CLI=${1}/bitcoin-cli + +DIR="${BASH_SOURCE%/*}" +SENDANDWAIT="${DIR}/send.sh" +if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi +. "$DIR/util.sh" + +D=$(mktemp -d test.XXXXX) + +D1=${D}/node1 +CreateDataDir "$D1" port=11000 rpcport=11001 +B1ARGS="-datadir=$D1" +$BITCOIND $B1ARGS & +B1PID=$! + +D2=${D}/node2 +CreateDataDir "$D2" port=11010 rpcport=11011 +B2ARGS="-datadir=$D2" +$BITCOIND $B2ARGS & +B2PID=$! + +function CleanUp { +$CLI $B2ARGS stop > /dev/null 2>&1 +wait $B2PID +$CLI $B1ARGS stop > /dev/null 2>&1 +wait $B1PID + +rm -rf $D +} + +# 110 blocks, 10 mature == 500 XBT +$CLI $B1ARGS setgenerate true 110 +$CLI $B2ARGS setgenerate true 110 + +CheckBalance "$B1ARGS" 500 +CheckBalance "$B2ARGS" 500 + +# Send 10 XBT +TXID1_DEFAULT=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10) +TXID2_DEFAULT=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 10) + +CheckBalance $B1ARGS 490 +CheckBalance $B2ARGS 490 + +# Move 10 XBT to testaccount +TMP=$($CLI $B1ARGS move "" "testaccount" 10) +TMP=$($CLI $B2ARGS move "" "testaccount" 10) + +CheckBalance $B1ARGS 10 "testaccount" +CheckBalance $B2ARGS 10 "testaccount" + +# Send 1 XBT from testaccount +TXID1_TESTACCOUNT=$($CLI $B1ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) +TXID2_TESTACCOUNT=$($CLI $B2ARGS sendfrom "testaccount" "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) + +CheckBalance $B1ARGS 9 "testaccount" +CheckBalance $B2ARGS 9 "testaccount" + +CheckBalance $B1ARGS 489 +CheckBalance $B2ARGS 489 + +# Confirm transactions +$CLI $B1ARGS setgenerate true 1 +$CLI $B2ARGS setgenerate true 1 + +# Create unconfirmed transaction +TXID1_UNCONFIRMED=$($CLI $B1ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) +TXID2_UNCONFIRMED=$($CLI $B2ARGS sendtoaddress "mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV" 1) + +# check balance (we created another 50 and spent 1 in the meantime) +CheckBalance $B1ARGS 538 +CheckBalance $B2ARGS 538 + +# Safety check, if unconfirmed transactions are there +$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "gettransaction1_1: $TXID1_UNCONFIRMED failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "gettransaction2_1: $TXID2_UNCONFIRMED failed" + CleanUp + exit 1 +fi + +# stop nodes +$CLI $B2ARGS stop > /dev/null 2>&1 +wait $B2PID +$CLI $B1ARGS stop > /dev/null 2>&1 +wait $B1PID + +# restart nodes with -zapwallettxes +$BITCOIND -zapwallettxes=1 $B1ARGS & +B1PID=$! +$BITCOIND -zapwallettxes=2 $B2ARGS & +B2PID=$! + +# check if confirmed transactions are there +$CLI $B1ARGS gettransaction $TXID1_DEFAULT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 1: $TXID1_DEFAULT failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_DEFAULT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 2: $TXID2_DEFAULT failed" + CleanUp + exit 1 +fi +$CLI $B1ARGS gettransaction $TXID1_TESTACCOUNT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 3: $TXID1_TESTACCOUNT failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_TESTACCOUNT > /dev/null 2>&1 +if [[ $? -ne 0 ]] ; then + echoerr "check confirmed transaction 4: $TXID2_TESTACCOUNT failed" + CleanUp + exit 1 +fi + +# check if unconfirmed transaction is gone +$CLI $B1ARGS gettransaction $TXID1_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -eq 0 ]] ; then + echoerr "check unconfirmed transaction 1: $TXID1_UNCONFIRMED failed" + CleanUp + exit 1 +fi +$CLI $B2ARGS gettransaction $TXID2_UNCONFIRMED > /dev/null 2>&1 +if [[ $? -eq 0 ]] ; then + echoerr "check unconfirmed transaction 2: $TXID2_UNCONFIRMED failed" + CleanUp + exit 1 +fi + +# check zapwallet mode 1, testaccount balance must be 9 (keeping transaction metadata) +CheckBalance $B1ARGS 9 "testaccount" + +# check zapwallet mode 2, testaccount balance must be 10 (dropping transaction metadata) +CheckBalance $B2ARGS 10 "testaccount" + +echo "Tests successful, cleaning up" +CleanUp +exit 0 diff --git a/src/init.cpp b/src/init.cpp index 39453da9c8..b9af16a156 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -259,7 +259,8 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; strUsage += " -wallet= " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; strUsage += " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; - strUsage += " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n"; + strUsage += " -zapwallettxes= " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n"; + strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; #endif strUsage += "\n" + _("Debugging/Testing options:") + "\n"; @@ -529,7 +530,7 @@ bool AppInit2(boost::thread_group& threadGroup) // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false)) { if (SoftSetBoolArg("-rescan", true)) - LogPrintf("AppInit2 : parameter interaction: -zapwallettxes=1 -> setting -rescan=1\n"); + LogPrintf("AppInit2 : parameter interaction: -zapwallettxes= -> setting -rescan=1\n"); } // Make sure enough file descriptors are available @@ -986,11 +987,15 @@ bool AppInit2(boost::thread_group& threadGroup) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { + + // needed to restore wallet transaction meta data after -zapwallettxes + std::vector vWtx; + if (GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); pwalletMain = new CWallet(strWalletFile); - DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(); + DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); return false; @@ -1085,6 +1090,29 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); pwalletMain->SetBestChain(chainActive.GetLocator()); nWalletDBUpdated++; + + // Restore wallet transaction metadata after -zapwallettxes=1 + if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") + { + BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) + { + uint256 hash = wtxOld.GetHash(); + std::map::iterator mi = pwalletMain->mapWallet.find(hash); + if (mi != pwalletMain->mapWallet.end()) + { + const CWalletTx* copyFrom = &wtxOld; + CWalletTx* copyTo = &mi->second; + copyTo->mapValue = copyFrom->mapValue; + copyTo->vOrderForm = copyFrom->vOrderForm; + copyTo->nTimeReceived = copyFrom->nTimeReceived; + copyTo->nTimeSmart = copyFrom->nTimeSmart; + copyTo->fFromMe = copyFrom->fFromMe; + copyTo->strFromAccount = copyFrom->strFromAccount; + copyTo->nOrderPos = copyFrom->nOrderPos; + copyTo->WriteToDisk(); + } + } + } } } // (!fDisableWallet) #else // ENABLE_WALLET diff --git a/src/wallet.cpp b/src/wallet.cpp index 400c966a95..36e40b1fc8 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1511,11 +1511,11 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } -DBErrors CWallet::ZapWalletTx() +DBErrors CWallet::ZapWalletTx(std::vector& vWtx) { if (!fFileBacked) return DB_LOAD_OK; - DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this); + DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx); if (nZapWalletTxRet == DB_NEED_REWRITE) { if (CDB::Rewrite(strWalletFile, "\x04pool")) diff --git a/src/wallet.h b/src/wallet.h index 7df656fc25..b168116f49 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -341,7 +341,7 @@ public: void SetBestChain(const CBlockLocator& loc); DBErrors LoadWallet(bool& fFirstRunRet); - DBErrors ZapWalletTx(); + DBErrors ZapWalletTx(std::vector& vWtx); bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 80e9dded5f..3ce2ef019c 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -680,7 +680,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } -DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash) +DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash, vector& vWtx) { pwallet->vchDefaultKey = CPubKey(); CWalletScanState wss; @@ -725,7 +725,11 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash) uint256 hash; ssKey >> hash; + CWalletTx wtx; + ssValue >> wtx; + vTxHash.push_back(hash); + vWtx.push_back(wtx); } } pcursor->close(); @@ -743,11 +747,11 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector& vTxHash) return result; } -DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet) +DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector& vWtx) { // build list of wallet TXs vector vTxHash; - DBErrors err = FindWalletTx(pwallet, vTxHash); + DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx); if (err != DB_LOAD_OK) return err; diff --git a/src/walletdb.h b/src/walletdb.h index 3bfb436050..8eb716acbb 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -122,8 +122,8 @@ public: DBErrors ReorderTransactions(CWallet*); DBErrors LoadWallet(CWallet* pwallet); - DBErrors FindWalletTx(CWallet* pwallet, std::vector& vTxHash); - DBErrors ZapWalletTx(CWallet* pwallet); + DBErrors FindWalletTx(CWallet* pwallet, std::vector& vTxHash, std::vector& vWtx); + DBErrors ZapWalletTx(CWallet* pwallet, std::vector& vWtx); static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, std::string filename); }; From b3c912d93a2d1cf98f894c28adaf94204174c6d7 Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Wed, 11 Jun 2014 13:58:16 +0200 Subject: [PATCH 184/336] [Qt] Change Coin control labels and tooltips because of non-rounding fees --- src/qt/coincontroldialog.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 42d6da7d37..f6e757f457 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -521,7 +521,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); // Fee - int64_t nFee = payTxFee.GetFee(nBytes); + int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes)); // Min Fee int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND); @@ -582,6 +582,13 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l6->setText(sPriorityLabel); // Priority l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change + if (nPayFee > 0) + { + l3->setText("~" + l3->text()); + l4->setText("~" + l4->text()); + if (nChange > 0) + l8->setText("~" + l8->text()); + } // turn labels "red" l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000 @@ -599,12 +606,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546))); + // how many satoshis the estimated fee can vary per byte we guess wrong + double dFeeVary = (double)std::max(CTransaction::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000; + QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); + + l3->setToolTip(toolTip4); + l4->setToolTip(toolTip4); l5->setToolTip(toolTip1); l6->setToolTip(toolTip2); l7->setToolTip(toolTip3); + l8->setToolTip(toolTip4); + dialog->findChild("labelCoinControlFeeText") ->setToolTip(l3->toolTip()); + dialog->findChild("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip()); dialog->findChild("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); dialog->findChild("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); dialog->findChild("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); + dialog->findChild("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); // Insufficient funds QLabel *label = dialog->findChild("labelCoinControlInsuffFunds"); From 11404af34c5e3d5aa334e1cfd8edee82fb9dc9a4 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:18:13 -0400 Subject: [PATCH 185/336] sanity: autoconf check for sys/select.h --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d8521ad3ad..81a32f9fb7 100644 --- a/configure.ac +++ b/configure.ac @@ -368,7 +368,7 @@ if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi -AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h]) +AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h]) dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) From 679240d0e92f71b38cefd23e3d99e8ebf63c2508 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:19:35 -0400 Subject: [PATCH 186/336] sanity: add libc/stdlib sanity checks These are meant to test our back-compat stubs, but they are enabled for all builds for the sake of consistency. --- src/Makefile.am | 5 ++- src/compat/glibc_sanity.cpp | 61 +++++++++++++++++++++++++++++++++++ src/compat/glibcxx_sanity.cpp | 61 +++++++++++++++++++++++++++++++++++ src/compat/sanity.h | 7 ++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/compat/glibc_sanity.cpp create mode 100644 src/compat/glibcxx_sanity.cpp create mode 100644 src/compat/sanity.h diff --git a/src/Makefile.am b/src/Makefile.am index 0a76829197..e1542203f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,7 +85,8 @@ BITCOIN_CORE_H = \ util.h \ version.h \ walletdb.h \ - wallet.h + wallet.h \ + compat/sanity.h JSON_H = \ json/json_spirit.h \ @@ -154,6 +155,8 @@ libbitcoin_common_a_SOURCES = \ sync.cpp \ util.cpp \ version.cpp \ + compat/glibc_sanity.cpp \ + compat/glibcxx_sanity.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp new file mode 100644 index 0000000000..1f64df9e33 --- /dev/null +++ b/src/compat/glibc_sanity.cpp @@ -0,0 +1,61 @@ +#include "bitcoin-config.h" + +#include +#if defined(HAVE_SYS_SELECT_H) +#include +#endif + +extern "C" void* memcpy(void* a, const void* b, size_t c); +void* memcpy_int(void* a, const void* b, size_t c) +{ + return memcpy(a,b,c); +} + +namespace { +// trigger: Use the memcpy_int wrapper which calls our internal memcpy. +// A direct call to memcpy may be optimized away by the compiler. +// test: Fill an array with a sequence of integers. memcpy to a new empty array. +// Verify that the arrays are equal. Use an odd size to decrease the odds of +// the call being optimized away. +template +bool sanity_test_memcpy() +{ + unsigned int memcpy_test[T]; + unsigned int memcpy_verify[T] = {}; + for (unsigned int i = 0; i != T; ++i) + memcpy_test[i] = i; + + memcpy_int(memcpy_verify,memcpy_test,sizeof(memcpy_test)); + + for (unsigned int i = 0; i != T; ++i) + { + if(memcpy_verify[i] != i) + return false; + } + return true; +} + +#if defined(HAVE_SYS_SELECT_H) +// trigger: Call FD_SET to trigger __fdelt_chk. FORTIFY_SOURCE must be defined +// as >0 and optimizations must be set to at least -O2. +// test: Add a file descriptor to an empty fd_set. Verify that it has been +// correctly added. +bool sanity_test_fdelt() +{ + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return FD_ISSET(0,&fds); +} +#endif + +} // anon namespace + +bool glibc_sanity_test() +{ +#if defined(HAVE_SYS_SELECT_H) + if (!sanity_test_fdelt()) + return false; +#endif + return sanity_test_memcpy<1025>(); +} diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp new file mode 100644 index 0000000000..2ff70948fd --- /dev/null +++ b/src/compat/glibcxx_sanity.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +namespace{ + +// trigger: use ctype::widen to trigger ctype::_M_widen_init(). +// test: convert a char from narrow to wide and back. Verify that the result +// matches the original. +bool sanity_test_widen(char testchar) +{ + const std::ctype& test(std::use_facet< std::ctype >(std::locale())); + return test.narrow(test.widen(testchar),'b') == testchar; +} + +// trigger: use list::push_back and list::pop_back to trigger _M_hook and +// _M_unhook. +// test: Push a sequence of integers into a list. Pop them off and verify that +// they match the original sequence. +bool sanity_test_list(unsigned int size) +{ + std::list test; + for (unsigned int i = 0; i != size; ++i) + test.push_back(i+1); + + if (test.size() != size) + return false; + + while (!test.empty()) + { + if(test.back() != test.size()) + return false; + test.pop_back(); + } + return true; +} + +} // anon namespace + +// trigger: string::at(x) on an empty string to trigger __throw_out_of_range_fmt. +// test: force std::string to throw an out_of_range exception. Verify that +// it's caught correctly. +bool sanity_test_range_fmt() +{ + std::string test; + try + { + test.at(1); + } + catch (const std::out_of_range&) + { + return true; + } + catch (...){} + return false; +} + +bool glibcxx_sanity_test() +{ + return sanity_test_widen('a') && sanity_test_list(100) && sanity_test_range_fmt(); +} diff --git a/src/compat/sanity.h b/src/compat/sanity.h new file mode 100644 index 0000000000..a221f69dfc --- /dev/null +++ b/src/compat/sanity.h @@ -0,0 +1,7 @@ +#ifndef BITCON_COMPAT_SANITY_H +#define BITCON_COMPAT_SANITY_H + +bool glibc_sanity_test(); +bool glibcxx_sanity_test(); + +#endif From 92a6220711b3f98c3daad8a8dcdf13f09ce484fd Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 13 Jun 2014 19:23:01 -0400 Subject: [PATCH 187/336] sanity: hook up sanity checks --- src/init.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 39453da9c8..f3df3cb375 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -31,6 +31,7 @@ #ifndef WIN32 #include #endif +#include "compat/sanity.h" #include #include @@ -417,8 +418,8 @@ bool InitSanityCheck(void) "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries"); return false; } - - // TODO: remaining sanity checks, see #4081 + if (!glibc_sanity_test() || !glibcxx_sanity_test()) + return false; return true; } From 7ad720d89020837ba1831055d8ee4eb955075f89 Mon Sep 17 00:00:00 2001 From: dllud Date: Tue, 17 Jun 2014 04:22:47 +0100 Subject: [PATCH 188/336] Added encryptwallet call to bitrpc.py This was the only call requiring password input which was still missing. Much useful to avoid leaving a plain text passphrase in the shell log. --- contrib/bitrpc/bitrpc.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py index a84d7e34dd..02577b1b6a 100644 --- a/contrib/bitrpc/bitrpc.py +++ b/contrib/bitrpc/bitrpc.py @@ -22,6 +22,18 @@ if cmd == "backupwallet": print access.backupwallet(path) except: print "\n---An error occurred---\n" + +elif cmd == "encryptwallet": + try: + pwd = getpass.getpass(prompt="Enter passphrase: ") + pwd2 = getpass.getpass(prompt="Repeat passphrase: ") + if pwd == pwd2: + access.encryptwallet(pwd) + print "\n---Wallet encrypted. Server stopping, restart to run with encrypted wallet---\n" + else: + print "\n---Passphrases do not match---\n" + except: + print "\n---An error occurred---\n" elif cmd == "getaccount": try: From 1020f599f33d47812a5ed73366fd266a25fef32d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 17 Jun 2014 09:13:52 +0200 Subject: [PATCH 189/336] add comment to HelpMessage() to ensure alphabetical ordering - also rename hmm to mode, to be consistent between .h and .cpp --- src/init.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 39453da9c8..dd5e4cf3b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -195,8 +195,9 @@ bool static Bind(const CService &addr, unsigned int flags) { return true; } -std::string HelpMessage(HelpMessageMode hmm) +std::string HelpMessage(HelpMessageMode mode) { + // When adding new options to the categories, please keep and ensure alphabetical ordering. string strUsage = _("Options:") + "\n"; strUsage += " -? " + _("This help message") + "\n"; strUsage += " -alertnotify= " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n"; @@ -204,7 +205,7 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " -checkblocks= " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n"; strUsage += " -checklevel= " + _("How thorough the block verification of -checkblocks is (0-4, default: 3)") + "\n"; strUsage += " -conf= " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; - if (hmm == HMM_BITCOIND) + if (mode == HMM_BITCOIND) { #if !defined(WIN32) strUsage += " -daemon " + _("Run in the background as a daemon and accept commands") + "\n"; @@ -278,7 +279,7 @@ std::string HelpMessage(HelpMessageMode hmm) strUsage += " " + _("If is not supplied, output all debugging information.") + "\n"; strUsage += " " + _(" can be:"); strUsage += " addrman, alert, coindb, db, lock, rand, rpc, selectcoins, mempool, net"; // Don't translate these and qt below - if (hmm == HMM_BITCOIN_QT) + if (mode == HMM_BITCOIN_QT) strUsage += ", qt"; strUsage += ".\n"; strUsage += " -gen " + _("Generate coins (default: 0)") + "\n"; From b82b7ec3dcbeda9e9f5de9bac05cc63c492e662e Mon Sep 17 00:00:00 2001 From: jtimon Date: Thu, 12 Jun 2014 13:48:31 +0200 Subject: [PATCH 190/336] Get rid of Params().RPCisTestNet() --- src/chainparams.cpp | 3 --- src/chainparams.h | 3 --- src/rpcmining.cpp | 2 +- src/rpcmisc.cpp | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6b2cfa1d1f..31eac62d48 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -178,7 +178,6 @@ public: fDefaultCheckMemPool = false; fAllowMinDifficultyBlocks = false; fRequireStandard = true; - fRPCisTestNet = false; fMineBlocksOnDemand = false; } }; @@ -230,7 +229,6 @@ public: fDefaultCheckMemPool = false; fAllowMinDifficultyBlocks = true; fRequireStandard = false; - fRPCisTestNet = true; fMineBlocksOnDemand = false; } }; @@ -269,7 +267,6 @@ public: fDefaultCheckMemPool = true; fAllowMinDifficultyBlocks = true; fRequireStandard = false; - fRPCisTestNet = true; fMineBlocksOnDemand = true; } }; diff --git a/src/chainparams.h b/src/chainparams.h index 28a51cbb0c..c0a6ebda6b 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -70,8 +70,6 @@ public: bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } /* Make standard checks */ bool RequireStandard() const { return fRequireStandard; } - /* Make standard checks */ - bool RPCisTestNet() const { return fRPCisTestNet; } const std::string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ @@ -110,7 +108,6 @@ protected: bool fDefaultCheckMemPool; bool fAllowMinDifficultyBlocks; bool fRequireStandard; - bool fRPCisTestNet; bool fMineBlocksOnDemand; }; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 3caf7d89fe..e18e44c5ef 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -268,7 +268,7 @@ Value getmininginfo(const Array& params, bool fHelp) obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); - obj.push_back(Pair("testnet", Params().RPCisTestNet())); + obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET)); #ifdef ENABLE_WALLET obj.push_back(Pair("generate", getgenerate(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 77e0e09ec3..5181aa23d8 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -73,7 +73,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", Params().RPCisTestNet())); + obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET)); #ifdef ENABLE_WALLET if (pwalletMain) { obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime())); From f6984e814134d2383e1353ce8aa951649f5fcbd2 Mon Sep 17 00:00:00 2001 From: jtimon Date: Thu, 12 Jun 2014 14:52:12 +0200 Subject: [PATCH 191/336] Add "chain" to getmininginfo, improve help in getblockchaininfo --- src/rpcblockchain.cpp | 2 +- src/rpcmining.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 0fabc86872..580c6bd5ba 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -438,7 +438,7 @@ Value getblockchaininfo(const Array& params, bool fHelp) "Returns an object containing various state info regarding block chain processing.\n" "\nResult:\n" "{\n" - " \"chain\": \"xxxx\", (string) current chain (main, testnet3, regtest)\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index e18e44c5ef..57a51c0fde 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -253,6 +253,7 @@ Value getmininginfo(const Array& params, bool fHelp) " \"hashespersec\": n (numeric) The hashes per second of the generation, or 0 if no generation.\n" " \"pooledtx\": n (numeric) The size of the mem pool\n" " \"testnet\": true|false (boolean) If using testnet or not\n" + " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmininginfo", "") @@ -269,6 +270,7 @@ Value getmininginfo(const Array& params, bool fHelp) obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("testnet", Params().NetworkID() == CChainParams::TESTNET)); + obj.push_back(Pair("chain", Params().NetworkIDString())); #ifdef ENABLE_WALLET obj.push_back(Pair("generate", getgenerate(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); From 33e5b4291036bbdad075f4a549491af72d8a0618 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 17 Jun 2014 09:09:12 +0200 Subject: [PATCH 192/336] rpc: Ignore and log errors during cancel Cancelling the RPC acceptors can sometimes result in an error about a bad file descriptor. As this is the shutdown sequence we need to continue nevertheless, ignore these errors, log a warning and proceed. Fixes #4352. --- src/rpcserver.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d4ceb7f995..2f7f5cc2ad 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -700,11 +700,20 @@ void StopRPCThreads() // First, cancel all timers and acceptors // This is not done automatically by ->stop(), and in some cases the destructor of // asio::io_service can hang if this is skipped. + boost::system::error_code ec; BOOST_FOREACH(const boost::shared_ptr &acceptor, rpc_acceptors) - acceptor->cancel(); + { + acceptor->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling acceptor", __func__, ec.message()); + } rpc_acceptors.clear(); BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr) &timer, deadlineTimers) - timer.second->cancel(); + { + timer.second->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling timer", __func__, ec.message()); + } deadlineTimers.clear(); rpc_io_service->stop(); From 6afa49329de860c080cdfd9b1c65afe313a43860 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 19 Jun 2014 08:19:07 +0200 Subject: [PATCH 193/336] rpc: Add acceptors only when listening succeeded --- src/rpcserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2f7f5cc2ad..56b5f2de0b 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -642,7 +642,6 @@ void StartRPCThreads() LogPrintf("Binding RPC on address %s port %i (IPv4+IPv6 bind any: %i)\n", bindAddress.to_string(), endpoint.port(), bBindAny); boost::system::error_code v6_only_error; boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); - rpc_acceptors.push_back(acceptor); try { acceptor->open(endpoint.protocol()); @@ -658,6 +657,7 @@ void StartRPCThreads() RPCListen(acceptor, *rpc_ssl_context, fUseSSL); fListening = true; + rpc_acceptors.push_back(acceptor); // If dual IPv6/IPv4 bind succesful, skip binding to IPv4 separately if(bBindAny && bindAddress == asio::ip::address_v6::any() && !v6_only_error) break; From ea3acaf383ade60d39643b786db5b6942b8b7991 Mon Sep 17 00:00:00 2001 From: Pavel Vasin Date: Fri, 20 Jun 2014 16:32:57 +0400 Subject: [PATCH 194/336] AvailableCoins: acquire cs_main mutex It's required when called from WalletModel --- src/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet.cpp b/src/wallet.cpp index 400c966a95..3176cf893a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1028,7 +1028,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const vCoins.clear(); { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const uint256& wtxid = it->first; From fc0c07eb64f4bc22377c35d13c71de9e2ede8861 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 21 Jun 2014 14:26:21 +0200 Subject: [PATCH 195/336] small cleanup in src/compat .h and .cpp - add license header - fix include guards - fix indentation --- src/compat/glibc_compat.cpp | 17 +++++++++--- src/compat/glibc_sanity.cpp | 8 +++++- src/compat/glibcxx_compat.cpp | 50 ++++++++++++++++++++--------------- src/compat/glibcxx_sanity.cpp | 6 ++++- src/compat/sanity.h | 6 ++++- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index 5b73e6051a..bb870c01f8 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -1,19 +1,28 @@ +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) #include "bitcoin-config.h" +#endif + #include +#if defined(HAVE_SYS_SELECT_H) #include +#endif // Prior to GLIBC_2.14, memcpy was aliased to memmove. extern "C" void* memmove(void* a, const void* b, size_t c); extern "C" void* memcpy(void* a, const void* b, size_t c) { - return memmove(a, b, c); + return memmove(a, b, c); } extern "C" void __chk_fail (void) __attribute__((__noreturn__)); extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a) { - if (a >= FD_SETSIZE) - __chk_fail (); - return a / __NFDBITS; + if (a >= FD_SETSIZE) + __chk_fail (); + return a / __NFDBITS; } extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn"))); diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index 1f64df9e33..6e5bae8a48 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -1,4 +1,10 @@ +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) #include "bitcoin-config.h" +#endif #include #if defined(HAVE_SYS_SELECT_H) @@ -8,7 +14,7 @@ extern "C" void* memcpy(void* a, const void* b, size_t c); void* memcpy_int(void* a, const void* b, size_t c) { - return memcpy(a,b,c); + return memcpy(a,b,c); } namespace { diff --git a/src/compat/glibcxx_compat.cpp b/src/compat/glibcxx_compat.cpp index e91376f818..417166aeda 100644 --- a/src/compat/glibcxx_compat.cpp +++ b/src/compat/glibcxx_compat.cpp @@ -1,49 +1,55 @@ +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include #include #include #include #ifndef _GLIBCXX_USE_NOEXCEPT - #define _GLIBCXX_USE_NOEXCEPT throw() +#define _GLIBCXX_USE_NOEXCEPT throw() #endif namespace std { const char* bad_exception::what() const throw() { - return "std::bad_exception"; + return "std::bad_exception"; } const char* bad_cast::what() const throw() { - return "std::bad_cast"; + return "std::bad_cast"; } const char* bad_alloc::what() const throw() { - return "std::bad_alloc"; + return "std::bad_alloc"; } namespace __detail { struct _List_node_base { - void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used)) - { - _M_next = __position; - _M_prev = __position->_M_prev; - __position->_M_prev->_M_next = this; - __position->_M_prev = this; - } - void _M_unhook() __attribute__((used)) - { - _List_node_base* const __next_node = _M_next; - _List_node_base* const __prev_node = _M_prev; - __prev_node->_M_next = __next_node; - __next_node->_M_prev = __prev_node; - } - _List_node_base* _M_next; - _List_node_base* _M_prev; + void _M_hook(std::__detail::_List_node_base* const __position) throw () __attribute__((used)) + { + _M_next = __position; + _M_prev = __position->_M_prev; + __position->_M_prev->_M_next = this; + __position->_M_prev = this; + } + + void _M_unhook() __attribute__((used)) + { + _List_node_base* const __next_node = _M_next; + _List_node_base* const __prev_node = _M_prev; + __prev_node->_M_next = __next_node; + __next_node->_M_prev = __prev_node; + } + + _List_node_base* _M_next; + _List_node_base* _M_prev; }; } // namespace detail @@ -61,8 +67,8 @@ out_of_range::~out_of_range() _GLIBCXX_USE_NOEXCEPT { } // Used with permission. // See: https://github.com/madlib/madlib/commit/c3db418c0d34d6813608f2137fef1012ce03043d -void -ctype::_M_widen_init() const { +void ctype::_M_widen_init() const +{ char __tmp[sizeof(_M_widen)]; for (unsigned __i = 0; __i < sizeof(_M_widen); ++__i) __tmp[__i] = __i; diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp index 2ff70948fd..cd8da4fd67 100644 --- a/src/compat/glibcxx_sanity.cpp +++ b/src/compat/glibcxx_sanity.cpp @@ -1,5 +1,9 @@ -#include +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + #include +#include #include namespace{ diff --git a/src/compat/sanity.h b/src/compat/sanity.h index a221f69dfc..e7df44307a 100644 --- a/src/compat/sanity.h +++ b/src/compat/sanity.h @@ -1,7 +1,11 @@ +// Copyright (c) 2009-2014 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 BITCON_COMPAT_SANITY_H #define BITCON_COMPAT_SANITY_H bool glibc_sanity_test(); bool glibcxx_sanity_test(); -#endif +#endif // BITCON_COMPAT_SANITY_H From 806fd19ecba0d58bf238a7b6f78e080da03eb9c7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 21 Jun 2014 17:00:38 +0200 Subject: [PATCH 196/336] Allocate receive buffers in on the fly --- src/net.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index 757a06aaed..707f58f8a6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -678,7 +678,6 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes) // switch state to reading message data in_data = true; - vRecv.resize(hdr.nMessageSize); return nCopy; } @@ -688,6 +687,11 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes) unsigned int nRemaining = hdr.nMessageSize - nDataPos; unsigned int nCopy = std::min(nRemaining, nBytes); + if (vRecv.size() < nDataPos + nCopy) { + // Allocate up to 256 KiB ahead, but never more than the total message size. + vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024)); + } + memcpy(&vRecv[nDataPos], pch, nCopy); nDataPos += nCopy; From 99ddc6cb706e825e54da244a10d4d6389fc5eaae Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 6 Jun 2014 03:15:55 -0400 Subject: [PATCH 197/336] Add nLocalServices info to RPC getinfo Also show full 64 bits of services. Previously service bits >32 that were advertised just didn't show up at all. --- src/rpcnet.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 0eca55a472..6fc86eedfb 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -80,7 +80,7 @@ Value getpeerinfo(const Array& params, bool fHelp) " {\n" " \"addr\":\"host:port\", (string) The ip address and port of the peer\n" " \"addrlocal\":\"ip:port\", (string) local address\n" - " \"services\":\"00000001\", (string) The services\n" + " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n" " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n" " \"bytessent\": n, (numeric) The total bytes sent\n" @@ -115,7 +115,7 @@ Value getpeerinfo(const Array& params, bool fHelp) obj.push_back(Pair("addr", stats.addrName)); if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); - obj.push_back(Pair("services", strprintf("%08x", stats.nServices))); + obj.push_back(Pair("services", strprintf("%016x", stats.nServices))); obj.push_back(Pair("lastsend", stats.nLastSend)); obj.push_back(Pair("lastrecv", stats.nLastRecv)); obj.push_back(Pair("bytessent", stats.nSendBytes)); @@ -344,6 +344,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) "{\n" " \"version\": xxxxx, (numeric) the server version\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"localservices\": \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" " \"timeoffset\": xxxxx, (numeric) the time offset\n" " \"connections\": xxxxx, (numeric) the number of connections\n" " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" @@ -365,6 +366,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); From 38405ac1411ce73f6945f296980d559e2949027f Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sat, 21 Jun 2014 09:05:24 -0400 Subject: [PATCH 198/336] Add comment regarding experimental-use service bits As per mailing list discussion. --- src/protocol.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/protocol.h b/src/protocol.h index 6de5d05a72..1f23274299 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -64,6 +64,14 @@ class CMessageHeader enum { NODE_NETWORK = (1 << 0), + + // Bits 24-31 are reserved for temporary experiments. Just pick a bit that + // isn't getting used, or one not being used much, and notify the + // bitcoin-development mailing list. Remember that service bits are just + // unauthenticated advertisements, so your code must be robust against + // collisions and other cases where nodes may be advertising a service they + // do not actually support. Other service bits should be allocated via the + // BIP process. }; /** A CService with information about it as peer */ From 977cdadea8a77eed04f1f0fd341ba9dedc3fa783 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 20 Apr 2014 17:36:25 +0200 Subject: [PATCH 199/336] Add a built-in SHA256/SHA512 implementation. This also moves the HMAC-SHA512 implementation to sha2.cpp. --- src/Makefile.am | 2 + src/Makefile.test.include | 2 + src/hash.cpp | 41 -- src/hash.h | 10 - src/key.cpp | 19 +- src/sha2.cpp | 428 ++++++++++++++++++++ src/sha2.h | 54 +++ src/test/{hmac_tests.cpp => sha2_tests.cpp} | 56 ++- 8 files changed, 536 insertions(+), 76 deletions(-) create mode 100644 src/sha2.cpp create mode 100644 src/sha2.h rename src/test/{hmac_tests.cpp => sha2_tests.cpp} (53%) diff --git a/src/Makefile.am b/src/Makefile.am index e1542203f8..4e94d47066 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,6 +75,7 @@ BITCOIN_CORE_H = \ rpcserver.h \ script.h \ serialize.h \ + sha2.h \ sync.h \ threadsafety.h \ tinyformat.h \ @@ -152,6 +153,7 @@ libbitcoin_common_a_SOURCES = \ protocol.cpp \ rpcprotocol.cpp \ script.cpp \ + sha2.cpp \ sync.cpp \ util.cpp \ version.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 988830260c..93723309af 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -33,6 +33,7 @@ BITCOIN_TESTS =\ test/compress_tests.cpp \ test/DoS_tests.cpp \ test/getarg_tests.cpp \ + test/hash_tests.cpp \ test/key_tests.cpp \ test/main_tests.cpp \ test/miner_tests.cpp \ @@ -44,6 +45,7 @@ BITCOIN_TESTS =\ test/script_P2SH_tests.cpp \ test/script_tests.cpp \ test/serialize_tests.cpp \ + test/sha2_tests.cpp \ test/sigopcount_tests.cpp \ test/test_bitcoin.cpp \ test/transaction_tests.cpp \ diff --git a/src/hash.cpp b/src/hash.cpp index 7b054bd154..bddd8abf38 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -56,44 +56,3 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vectorctxOuter); - SHA512_Update(&pctx->ctxOuter, key, 128); - - for (int n=0; n<128; n++) - key[n] ^= 0x5c ^ 0x36; - SHA512_Init(&pctx->ctxInner); - return SHA512_Update(&pctx->ctxInner, key, 128); -} - -int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len) -{ - return SHA512_Update(&pctx->ctxInner, pdata, len); -} - -int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx) -{ - unsigned char buf[64]; - SHA512_Final(buf, &pctx->ctxInner); - SHA512_Update(&pctx->ctxOuter, buf, 64); - return SHA512_Final(pmd, &pctx->ctxOuter); -} diff --git a/src/hash.h b/src/hash.h index 7dbf1b6448..718b627a78 100644 --- a/src/hash.h +++ b/src/hash.h @@ -126,14 +126,4 @@ inline uint160 Hash160(const std::vector& vch) unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); -typedef struct -{ - SHA512_CTX ctxInner; - SHA512_CTX ctxOuter; -} HMAC_SHA512_CTX; - -int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len); -int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len); -int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx); - #endif diff --git a/src/key.cpp b/src/key.cpp index 4747beffb4..0685948922 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -4,6 +4,8 @@ #include "key.h" +#include "sha2.h" + #include #include #include @@ -510,12 +512,10 @@ void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, un num[1] = (nChild >> 16) & 0xFF; num[2] = (nChild >> 8) & 0xFF; num[3] = (nChild >> 0) & 0xFF; - HMAC_SHA512_CTX ctx; - HMAC_SHA512_Init(&ctx, chainCode, 32); - HMAC_SHA512_Update(&ctx, &header, 1); - HMAC_SHA512_Update(&ctx, data, 32); - HMAC_SHA512_Update(&ctx, num, 4); - HMAC_SHA512_Final(output, &ctx); + CHMAC_SHA512(chainCode, 32).Write(&header, 1) + .Write(data, 32) + .Write(num, 4) + .Finalize(output); } bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { @@ -562,13 +562,10 @@ bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { } void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { - static const char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; - HMAC_SHA512_CTX ctx; - HMAC_SHA512_Init(&ctx, hashkey, sizeof(hashkey)); - HMAC_SHA512_Update(&ctx, seed, nSeedLen); + static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; unsigned char out[64]; LockObject(out); - HMAC_SHA512_Final(out, &ctx); + CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out); key.Set(&out[0], &out[32], true); memcpy(vchChainCode, &out[32], 32); UnlockObject(out); diff --git a/src/sha2.cpp b/src/sha2.cpp new file mode 100644 index 0000000000..c9beaf220b --- /dev/null +++ b/src/sha2.cpp @@ -0,0 +1,428 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sha2.h" + +#include + +// Internal implementation code. +namespace { + +/** Read 4 bytes, and interpret them as a 32-bit unsigned big-endian integer. */ +uint32_t inline ReadBE32(const unsigned char *data) { + return ((uint32_t)data[0] << 24 | (uint32_t)data[1] << 16 | (uint32_t)data[2] << 8 | (uint32_t)data[3]); +} + +/** Write a 32-bit unsigned big-endian integer. */ +void inline WriteBE32(unsigned char *data, uint32_t x) { + data[0] = x >> 24; + data[1] = x >> 16; + data[2] = x >> 8; + data[3] = x; +} + +/** Read 8 bytes, and interpret them as a 64-bit unsigned big-endian integer. */ +uint64_t inline ReadBE64(const unsigned char *data) { + return ((uint64_t)data[0] << 56 | (uint64_t)data[1] << 48 | (uint64_t)data[2] << 40 | (uint64_t)data[3] << 32 | + (uint64_t)data[4] << 24 | (uint64_t)data[5] << 16 | (uint64_t)data[6] << 8 | (uint64_t)data[7]); +} + +/** Write a 64-bit unsigned big-endian integer. */ +void inline WriteBE64(unsigned char *data, uint64_t x) { + data[0] = x >> 56; + data[1] = x >> 48; + data[2] = x >> 40; + data[3] = x >> 32; + data[4] = x >> 24; + data[5] = x >> 16; + data[6] = x >> 8; + data[7] = x; +} + +/// Internal SHA-256 implementation. +namespace sha256 { + +uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } +uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } +uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } +uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } +uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } +uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } + +/** One round of SHA-256. */ +void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t &d, + uint32_t e, uint32_t f, uint32_t g, uint32_t &h, + uint32_t k, uint32_t w) { + uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t t2 = Sigma0(a) + Maj(a, b, c); + d += t1; + h = t1 + t2; +} + +/** Initialize SHA-256 state. */ +void inline Initialize(uint32_t *s) { + s[0] = 0x6a09e667ul; + s[1] = 0xbb67ae85ul; + s[2] = 0x3c6ef372ul; + s[3] = 0xa54ff53aul; + s[4] = 0x510e527ful; + s[5] = 0x9b05688cul; + s[6] = 0x1f83d9abul; + s[7] = 0x5be0cd19ul; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +void Transform(uint32_t *s, const unsigned char *chunk) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0( w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0( w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0( w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +} // namespace sha256 + +/// Internal SHA-512 implementation. +namespace sha512 { + +uint64_t inline Ch(uint64_t x, uint64_t y, uint64_t z) { return z ^ (x & (y ^ z)); } +uint64_t inline Maj(uint64_t x, uint64_t y, uint64_t z) { return (x & y) | (z & (x | y)); } +uint64_t inline Sigma0(uint64_t x) { return (x >> 28 | x << 36) ^ (x >> 34 | x << 30) ^ (x >> 39 | x << 25); } +uint64_t inline Sigma1(uint64_t x) { return (x >> 14 | x << 50) ^ (x >> 18 | x << 46) ^ (x >> 41 | x << 23); } +uint64_t inline sigma0(uint64_t x) { return (x >> 1 | x << 63) ^ (x >> 8 | x << 56) ^ (x >> 7); } +uint64_t inline sigma1(uint64_t x) { return (x >> 19 | x << 45) ^ (x >> 61 | x << 3) ^ (x >> 6); } + +/** One round of SHA-512. */ +void inline Round(uint64_t a, uint64_t b, uint64_t c, uint64_t &d, + uint64_t e, uint64_t f, uint64_t g, uint64_t &h, + uint64_t k, uint64_t w) { + uint64_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; + uint64_t t2 = Sigma0(a) + Maj(a, b, c); + d += t1; + h = t1 + t2; +} + +/** Initialize SHA-256 state. */ +void inline Initialize(uint64_t *s) { + s[0] = 0x6a09e667f3bcc908ull; + s[1] = 0xbb67ae8584caa73bull; + s[2] = 0x3c6ef372fe94f82bull; + s[3] = 0xa54ff53a5f1d36f1ull; + s[4] = 0x510e527fade682d1ull; + s[5] = 0x9b05688c2b3e6c1full; + s[6] = 0x1f83d9abfb41bd6bull; + s[7] = 0x5be0cd19137e2179ull; +} + +/** Perform one SHA-512 transformation, processing a 128-byte chunk. */ +void Transform(uint64_t *s, const unsigned char *chunk) { + uint64_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint64_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22ull, w0 = ReadBE64(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x7137449123ef65cdull, w1 = ReadBE64(chunk + 8)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2full, w2 = ReadBE64(chunk + 16)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbcull, w3 = ReadBE64(chunk + 24)); + Round(e, f, g, h, a, b, c, d, 0x3956c25bf348b538ull, w4 = ReadBE64(chunk + 32)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1b605d019ull, w5 = ReadBE64(chunk + 40)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4af194f9bull, w6 = ReadBE64(chunk + 48)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118ull, w7 = ReadBE64(chunk + 56)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98a3030242ull, w8 = ReadBE64(chunk + 64)); + Round(h, a, b, c, d, e, f, g, 0x12835b0145706fbeull, w9 = ReadBE64(chunk + 72)); + Round(g, h, a, b, c, d, e, f, 0x243185be4ee4b28cull, w10 = ReadBE64(chunk + 80)); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2ull, w11 = ReadBE64(chunk + 88)); + Round(e, f, g, h, a, b, c, d, 0x72be5d74f27b896full, w12 = ReadBE64(chunk + 96)); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1ull, w13 = ReadBE64(chunk + 104)); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235ull, w14 = ReadBE64(chunk + 112)); + Round(b, c, d, e, f, g, h, a, 0xc19bf174cf692694ull, w15 = ReadBE64(chunk + 120)); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2ull, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3ull, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5ull, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65ull, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275ull, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483ull, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4ull, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da831153b5ull, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152ee66dfabull, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d2db43210ull, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c898fb213full, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4ull, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147930aa725ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351e003826full, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x142929670a0e6e70ull, w15 += sigma1(w13) + w8 + sigma0( w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffcull, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926ull, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aedull, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d139d95b3dfull, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x650a73548baf63deull, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8ull, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6ull, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c851482353bull, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364ull, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664bbc423001ull, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791ull, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a30654be30ull, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd69906245565a910ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e35855771202aull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8ull, w15 += sigma1(w13) + w8 + sigma0( w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8ull, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c085141ab53ull, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99ull, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8ull, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63ull, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acbull, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373ull, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3ull, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fcull, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f43172f60ull, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72ull, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc702081a6439ecull, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa23631e28ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9ull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915ull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2e372532bull, w15 += sigma1(w13) + w8 + sigma0( w0)); + + Round(a, b, c, d, e, f, g, h, 0xca273eceea26619cull, w0 += sigma1(w14) + w9 + sigma0( w1)); + Round(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207ull, w1 += sigma1(w15) + w10 + sigma0( w2)); + Round(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1eull, w2 += sigma1( w0) + w11 + sigma0( w3)); + Round(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178ull, w3 += sigma1( w1) + w12 + sigma0( w4)); + Round(e, f, g, h, a, b, c, d, 0x06f067aa72176fbaull, w4 += sigma1( w2) + w13 + sigma0( w5)); + Round(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6ull, w5 += sigma1( w3) + w14 + sigma0( w6)); + Round(c, d, e, f, g, h, a, b, 0x113f9804bef90daeull, w6 += sigma1( w4) + w15 + sigma0( w7)); + Round(b, c, d, e, f, g, h, a, 0x1b710b35131c471bull, w7 += sigma1( w5) + w0 + sigma0( w8)); + Round(a, b, c, d, e, f, g, h, 0x28db77f523047d84ull, w8 += sigma1( w6) + w1 + sigma0( w9)); + Round(h, a, b, c, d, e, f, g, 0x32caab7b40c72493ull, w9 += sigma1( w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebcull, w10 += sigma1( w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1( w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0( w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +} // namespace sha512 + +} // namespace + + +////// SHA-256 + +CSHA256::CSHA256() : bytes(0) { + sha256::Initialize(s); +} + +CSHA256& CSHA256::Write(const unsigned char *data, size_t len) { + const unsigned char *end = data + len; + size_t bufsize = bytes % 64; + if (bufsize && bufsize + len >= 64) { + // Fill the buffer, and process it. + memcpy(buf + bufsize, data, 64 - bufsize); + bytes += 64 - bufsize; + data += 64 - bufsize; + sha256::Transform(s, buf); + bufsize = 0; + } + while (end >= data + 64) { + // Process full chunks directly from the source. + sha256::Transform(s, data); + bytes += 64; + data += 64; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(buf + bufsize, data, end - data); + bytes += end - data; + } + return *this; +} + +void CSHA256::Finalize(unsigned char *hash) { + static const unsigned char pad[64] = {0x80}; + unsigned char sizedesc[8]; + WriteBE64(sizedesc, bytes << 3); + Write(pad, 1 + ((119 - (bytes % 64)) % 64)); + Write(sizedesc, 8); + WriteBE32(hash, s[0]); + WriteBE32(hash+4, s[1]); + WriteBE32(hash+8, s[2]); + WriteBE32(hash+12, s[3]); + WriteBE32(hash+16, s[4]); + WriteBE32(hash+20, s[5]); + WriteBE32(hash+24, s[6]); + WriteBE32(hash+28, s[7]); +} + +CSHA256& CSHA256::Reset() { + bytes = 0; + sha256::Initialize(s); + return *this; +} + +////// SHA-512 + +CSHA512::CSHA512() : bytes(0) { + sha512::Initialize(s); +} + +CSHA512& CSHA512::Write(const unsigned char *data, size_t len) { + const unsigned char *end = data + len; + size_t bufsize = bytes % 128; + if (bufsize && bufsize + len >= 128) { + // Fill the buffer, and process it. + memcpy(buf + bufsize, data, 128 - bufsize); + bytes += 128 - bufsize; + data += 128 - bufsize; + sha512::Transform(s, buf); + bufsize = 0; + } + while (end >= data + 128) { + // Process full chunks directly from the source. + sha512::Transform(s, data); + data += 128; + bytes += 128; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(buf + bufsize, data, end - data); + bytes += end - data; + } + return *this; +} + +void CSHA512::Finalize(unsigned char *hash) { + static const unsigned char pad[128] = {0x80}; + unsigned char sizedesc[16] = {0x00}; + WriteBE64(sizedesc+8, bytes << 3); + Write(pad, 1 + ((239 - (bytes % 128)) % 128)); + Write(sizedesc, 16); + WriteBE64(hash, s[0]); + WriteBE64(hash+8, s[1]); + WriteBE64(hash+16, s[2]); + WriteBE64(hash+24, s[3]); + WriteBE64(hash+32, s[4]); + WriteBE64(hash+40, s[5]); + WriteBE64(hash+48, s[6]); + WriteBE64(hash+56, s[7]); +} + +CSHA512& CSHA512::Reset() { + bytes = 0; + sha512::Initialize(s); + return *this; +} + +////// HMAC-SHA-512 + +CHMAC_SHA512::CHMAC_SHA512(const unsigned char *key, size_t keylen) { + unsigned char rkey[128]; + if (keylen <= 128) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 128 - keylen); + } else { + CSHA512().Write(key, keylen).Finalize(rkey); + memset(rkey + 64, 0, 64); + } + + for (int n=0; n<128; n++) + rkey[n] ^= 0x5c; + outer.Write(rkey, 128); + + for (int n=0; n<128; n++) + rkey[n] ^= 0x5c ^ 0x36; + inner.Write(rkey, 128); +} + +void CHMAC_SHA512::Finalize(unsigned char *hash) { + unsigned char temp[64]; + inner.Finalize(temp); + outer.Write(temp, 64).Finalize(hash); +} diff --git a/src/sha2.h b/src/sha2.h new file mode 100644 index 0000000000..001bfc647c --- /dev/null +++ b/src/sha2.h @@ -0,0 +1,54 @@ +// Copyright (c) 2014 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 BITCOIN_SHA2_H +#define BITCOIN_SHA2_H + +#include +#include + +/** A hasher class for SHA-256. */ +class CSHA256 { +private: + uint32_t s[8]; + unsigned char buf[64]; + size_t bytes; + +public: + CSHA256(); + CSHA256& Write(const unsigned char *data, size_t len); + void Finalize(unsigned char *hash); + CSHA256& Reset(); +}; + +/** A hasher class for SHA-512. */ +class CSHA512 { +private: + uint64_t s[8]; + unsigned char buf[128]; + size_t bytes; + +public: + CSHA512(); + CSHA512& Write(const unsigned char *data, size_t len); + void Finalize(unsigned char *hash); + CSHA512& Reset(); +}; + +/** A hasher class for HMAC-SHA-512. */ +class CHMAC_SHA512 { +private: + CSHA512 outer; + CSHA512 inner; + +public: + CHMAC_SHA512(const unsigned char *key, size_t keylen); + CHMAC_SHA512& Write(const unsigned char *data, size_t len) { + inner.Write(data, len); + return *this; + } + void Finalize(unsigned char *hash); +}; + +#endif diff --git a/src/test/hmac_tests.cpp b/src/test/sha2_tests.cpp similarity index 53% rename from src/test/hmac_tests.cpp rename to src/test/sha2_tests.cpp index 780ce480ce..516b942ad3 100644 --- a/src/test/hmac_tests.cpp +++ b/src/test/sha2_tests.cpp @@ -1,15 +1,49 @@ -// Copyright (c) 2013 The Bitcoin Core developers +// Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "hash.h" +#include "sha2.h" #include "util.h" +#include + #include -using namespace std; +BOOST_AUTO_TEST_SUITE(sha2_tests) -BOOST_AUTO_TEST_SUITE(hmac_tests) +void SHA256TestVector(const std::string &in, const std::string &out) { + std::vector hash; + hash.resize(32); + CSHA256().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); + BOOST_CHECK_EQUAL(HexStr(hash), out); +} + +void SHA512TestVector(const std::string &in, const std::string &out) { + std::vector hash; + hash.resize(64); + CSHA512().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); + BOOST_CHECK_EQUAL(HexStr(hash), out); +} + +BOOST_AUTO_TEST_CASE(sha256_testvectors) { + SHA256TestVector("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + SHA256TestVector("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + SHA256TestVector("message digest", "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); + SHA256TestVector("secure hash algorithm", "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d"); + SHA256TestVector("SHA256 is considered to be safe", "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630"); + SHA256TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + SHA256TestVector("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"); + SHA256TestVector("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"); + SHA256TestVector("As Bitcoin relies on 80 byte header hashes, we want to have an example for that.", "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743"); +} + +BOOST_AUTO_TEST_CASE(sha512_testvectors) { + SHA512TestVector("abc", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + SHA512TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"); + SHA512TestVector("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"); + SHA512TestVector(std::string(1000000, 'a'), "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); + SHA512TestVector("", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); +} typedef struct { const char *pszKey; @@ -111,18 +145,12 @@ BOOST_AUTO_TEST_CASE(hmacsha512_testvectors) { for (unsigned int n=0; n vchKey = ParseHex(vtest[n].pszKey); - vector vchData = ParseHex(vtest[n].pszData); - vector vchMAC = ParseHex(vtest[n].pszMAC); + std::vector vchKey = ParseHex(vtest[n].pszKey); + std::vector vchData = ParseHex(vtest[n].pszData); + std::vector vchMAC = ParseHex(vtest[n].pszMAC); unsigned char vchTemp[64]; - - HMAC_SHA512_CTX ctx; - HMAC_SHA512_Init(&ctx, &vchKey[0], vchKey.size()); - HMAC_SHA512_Update(&ctx, &vchData[0], vchData.size()); - HMAC_SHA512_Final(&vchTemp[0], &ctx); - + CHMAC_SHA512(&vchKey[0], vchKey.size()).Write(&vchData[0], vchData.size()).Finalize(&vchTemp[0]); BOOST_CHECK(memcmp(&vchTemp[0], &vchMAC[0], 64) == 0); - } } From 7b4737c87805b464cd47d01a9d814df5e41b8255 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 26 Apr 2014 19:26:34 +0200 Subject: [PATCH 200/336] Switch script.cpp and hash.cpp to use sha2.cpp instead of OpenSSL. --- src/hash.h | 174 +++++++++++++++++++++++++++++-------------------- src/miner.cpp | 3 + src/script.cpp | 15 ++--- 3 files changed, 111 insertions(+), 81 deletions(-) diff --git a/src/hash.h b/src/hash.h index 718b627a78..9e7a67550f 100644 --- a/src/hash.h +++ b/src/hash.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H +#include "sha2.h" #include "serialize.h" #include "uint256.h" #include "version.h" @@ -13,48 +14,127 @@ #include #include -#include +/** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */ +class CHash256 { +private: + CSHA256 sha; +public: + void Finalize(unsigned char *hash) { + unsigned char buf[32]; + sha.Finalize(buf); + sha.Reset().Write(buf, 32).Finalize(hash); + } + + CHash256& Write(const unsigned char *data, size_t len) { + sha.Write(data, len); + return *this; + } + + CHash256& Reset() { + sha.Reset(); + return *this; + } +}; + +/** A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160). */ +class CHash160 { +private: + CSHA256 sha; +public: + void Finalize(unsigned char *hash) { + unsigned char buf[32]; + sha.Finalize(buf); + RIPEMD160(buf, 32, hash); + } + + CHash160& Write(const unsigned char *data, size_t len) { + sha.Write(data, len); + return *this; + } + + CHash160& Reset() { + sha.Reset(); + return *this; + } +}; + +/** Compute the 256-bit hash of an object. */ template inline uint256 Hash(const T1 pbegin, const T1 pend) { - static unsigned char pblank[1]; - uint256 hash1; - SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; + static const unsigned char pblank[1] = {}; + uint256 result; + CHash256().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])) + .Finalize((unsigned char*)&result); + return result; } +/** Compute the 256-bit hash of the concatenation of two objects. */ +template +inline uint256 Hash(const T1 p1begin, const T1 p1end, + const T2 p2begin, const T2 p2end) { + static const unsigned char pblank[1] = {}; + uint256 result; + CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])) + .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])) + .Finalize((unsigned char*)&result); + return result; +} + +/** Compute the 256-bit hash of the concatenation of three objects. */ +template +inline uint256 Hash(const T1 p1begin, const T1 p1end, + const T2 p2begin, const T2 p2end, + const T3 p3begin, const T3 p3end) { + static const unsigned char pblank[1] = {}; + uint256 result; + CHash256().Write(p1begin == p1end ? pblank : (const unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0])) + .Write(p2begin == p2end ? pblank : (const unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0])) + .Write(p3begin == p3end ? pblank : (const unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0])) + .Finalize((unsigned char*)&result); + return result; +} + +/** Compute the 160-bit hash an object. */ +template +inline uint160 Hash160(const T1 pbegin, const T1 pend) +{ + static unsigned char pblank[1] = {}; + uint160 result; + CHash160().Write(pbegin == pend ? pblank : (const unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0])) + .Finalize((unsigned char*)&result); + return result; +} + +/** Compute the 160-bit hash of a vector. */ +inline uint160 Hash160(const std::vector& vch) +{ + return Hash160(vch.begin(), vch.end()); +} + +/** A writer stream (for serialization) that computes a 256-bit hash. */ class CHashWriter { private: - SHA256_CTX ctx; + CHash256 ctx; public: int nType; int nVersion; - void Init() { - SHA256_Init(&ctx); - } - - CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) { - Init(); - } + CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {} CHashWriter& write(const char *pch, size_t size) { - SHA256_Update(&ctx, pch, size); + ctx.Write((const unsigned char*)pch, size); return (*this); } // invalidates the object uint256 GetHash() { - uint256 hash1; - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; + uint256 result; + ctx.Finalize((unsigned char*)&result); + return result; } template @@ -65,41 +145,7 @@ public: } }; - -template -inline uint256 Hash(const T1 p1begin, const T1 p1end, - const T2 p2begin, const T2 p2end) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); - SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -template -inline uint256 Hash(const T1 p1begin, const T1 p1end, - const T2 p2begin, const T2 p2end, - const T3 p3begin, const T3 p3end) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0])); - SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0])); - SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0])); - SHA256_Final((unsigned char*)&hash1, &ctx); - uint256 hash2; - SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - +/** Compute the 256-bit hash of an object's serialization. */ template uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) { @@ -108,22 +154,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL return ss.GetHash(); } -template -inline uint160 Hash160(const T1 pbegin, const T1 pend) -{ - static unsigned char pblank[1]; - uint256 hash1; - SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1); - uint160 hash2; - RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2); - return hash2; -} - -inline uint160 Hash160(const std::vector& vch) -{ - return Hash160(vch.begin(), vch.end()); -} - unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash); #endif diff --git a/src/miner.cpp b/src/miner.cpp index 87779efbbd..c48c9f0521 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -12,7 +12,10 @@ #include "wallet.h" #endif +#include + using namespace std; + ////////////////////////////////////////////////////////////////////////////// // // BitcoinMiner diff --git a/src/script.cpp b/src/script.cpp index 11cdfef950..f20c0bcca3 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -9,10 +9,13 @@ #include "hash.h" #include "key.h" #include "keystore.h" +#include "sha2.h" #include "sync.h" #include "uint256.h" #include "util.h" +#include + #include #include #include @@ -805,17 +808,11 @@ bool EvalScript(vector >& stack, const CScript& script, co else if (opcode == OP_SHA1) SHA1(&vch[0], vch.size(), &vchHash[0]); else if (opcode == OP_SHA256) - SHA256(&vch[0], vch.size(), &vchHash[0]); + CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_HASH160) - { - uint160 hash160 = Hash160(vch); - memcpy(&vchHash[0], &hash160, sizeof(hash160)); - } + CHash160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_HASH256) - { - uint256 hash = Hash(vch.begin(), vch.end()); - memcpy(&vchHash[0], &hash, sizeof(hash)); - } + CHash256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); popstack(stack); stack.push_back(vchHash); } From cf0c47b2698a3e23654d9fd24f6b2ef9689bde3d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 28 Apr 2014 12:52:32 +0200 Subject: [PATCH 201/336] Remove getwork() RPC call --- src/init.cpp | 3 - src/rpcmining.cpp | 159 ---------------------------------------------- src/rpcserver.cpp | 3 +- src/rpcserver.h | 1 - 4 files changed, 1 insertion(+), 165 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 6eab273526..12d2d1bb44 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -116,7 +116,6 @@ void Shutdown() RenameThread("bitcoin-shutoff"); mempool.AddTransactionsUpdated(1); StopRPCThreads(); - ShutdownRPCMining(); #ifdef ENABLE_WALLET if (pwalletMain) bitdb.Flush(false); @@ -1148,8 +1147,6 @@ bool AppInit2(boost::thread_group& threadGroup) #endif StartNode(threadGroup); - // InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly. - InitRPCMining(); if (fServer) StartRPCThreads(); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 57a51c0fde..a1410f0e41 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -24,36 +24,6 @@ using namespace json_spirit; using namespace std; -#ifdef ENABLE_WALLET -// Key used by getwork miners. -// Allocated in InitRPCMining, free'd in ShutdownRPCMining -static CReserveKey* pMiningKey = NULL; - -void InitRPCMining() -{ - if (!pwalletMain) - return; - - // getwork/getblocktemplate mining rewards paid here: - pMiningKey = new CReserveKey(pwalletMain); -} - -void ShutdownRPCMining() -{ - if (!pMiningKey) - return; - - delete pMiningKey; pMiningKey = NULL; -} -#else -void InitRPCMining() -{ -} -void ShutdownRPCMining() -{ -} -#endif - // Return average network hashes per second based on the last 'lookup' blocks, // or from the last difficulty change if 'lookup' is nonpositive. // If 'height' is nonnegative, compute the estimate at the time when a given block was found. @@ -131,9 +101,6 @@ Value getgenerate(const Array& params, bool fHelp) + HelpExampleRpc("getgenerate", "") ); - if (!pMiningKey) - return false; - return GetBoolArg("-gen", false); } @@ -279,132 +246,6 @@ Value getmininginfo(const Array& params, bool fHelp) } -#ifdef ENABLE_WALLET -Value getwork(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "getwork ( \"data\" )\n" - "\nIf 'data' is not specified, it returns the formatted hash data to work on.\n" - "If 'data' is specified, tries to solve the block and returns true if it was successful.\n" - "\nArguments:\n" - "1. \"data\" (string, optional) The hex encoded data to solve\n" - "\nResult (when 'data' is not specified):\n" - "{\n" - " \"midstate\" : \"xxxx\", (string) The precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated - " \"data\" : \"xxxxx\", (string) The block data\n" - " \"hash1\" : \"xxxxx\", (string) The formatted hash buffer for second hash (DEPRECATED)\n" // deprecated - " \"target\" : \"xxxx\" (string) The little endian hash target\n" - "}\n" - "\nResult (when 'data' is specified):\n" - "true|false (boolean) If solving the block specified in the 'data' was successfull\n" - "\nExamples:\n" - + HelpExampleCli("getwork", "") - + HelpExampleRpc("getwork", "") - ); - - if (vNodes.empty()) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); - - if (IsInitialBlockDownload()) - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); - - typedef map > mapNewBlock_t; - static mapNewBlock_t mapNewBlock; // FIXME: thread safety - static vector vNewBlockTemplate; - - if (params.size() == 0) - { - // Update block - static unsigned int nTransactionsUpdatedLast; - static CBlockIndex* pindexPrev; - static int64_t nStart; - static CBlockTemplate* pblocktemplate; - if (pindexPrev != chainActive.Tip() || - (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)) - { - if (pindexPrev != chainActive.Tip()) - { - // Deallocate old blocks since they're obsolete now - mapNewBlock.clear(); - BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate) - delete pblocktemplate; - vNewBlockTemplate.clear(); - } - - // Clear pindexPrev so future getworks make a new block, despite any failures from here on - pindexPrev = NULL; - - // Store the pindexBest used before CreateNewBlock, to avoid races - nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrevNew = chainActive.Tip(); - nStart = GetTime(); - - // Create new block - pblocktemplate = CreateNewBlockWithKey(*pMiningKey); - if (!pblocktemplate) - throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); - vNewBlockTemplate.push_back(pblocktemplate); - - // Need to update only after we know CreateNewBlock succeeded - pindexPrev = pindexPrevNew; - } - CBlock* pblock = &pblocktemplate->block; // pointer for convenience - - // Update nTime - UpdateTime(*pblock, pindexPrev); - pblock->nNonce = 0; - - // Update nExtraNonce - static unsigned int nExtraNonce = 0; - IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - - // Save - mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); - - // Pre-build hash buffers - char pmidstate[32]; - char pdata[128]; - char phash1[64]; - FormatHashBuffers(pblock, pmidstate, pdata, phash1); - - uint256 hashTarget = uint256().SetCompact(pblock->nBits); - - Object result; - result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated - result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); - result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated - result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); - return result; - } - else - { - // Parse parameters - vector vchData = ParseHex(params[0].get_str()); - if (vchData.size() != 128) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); - CBlock* pdata = (CBlock*)&vchData[0]; - - // Byte reverse - for (int i = 0; i < 128/4; i++) - ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); - - // Get saved block - if (!mapNewBlock.count(pdata->hashMerkleRoot)) - return false; - CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; - - pblock->nTime = pdata->nTime; - pblock->nNonce = pdata->nNonce; - pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); - - assert(pwalletMain != NULL); - return CheckWork(pblock, *pwalletMain, *pMiningKey); - } -} -#endif - Value getblocktemplate(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 56b5f2de0b..93da81e429 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -315,7 +315,6 @@ static const CRPCCommand vRPCCommands[] = /* Wallet-enabled mining */ { "getgenerate", &getgenerate, true, false, false }, { "gethashespersec", &gethashespersec, true, false, false }, - { "getwork", &getwork, true, false, true }, { "setgenerate", &setgenerate, true, true, false }, #endif // ENABLE_WALLET }; @@ -772,7 +771,7 @@ void JSONRequest::parse(const Value& valRequest) if (valMethod.type() != str_type) throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); strMethod = valMethod.get_str(); - if (strMethod != "getwork" && strMethod != "getblocktemplate") + if (strMethod != "getblocktemplate") LogPrint("rpc", "ThreadRPCServer method=%s\n", strMethod); // Parse params diff --git a/src/rpcserver.h b/src/rpcserver.h index 73e8b9426c..5271542385 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -130,7 +130,6 @@ extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHe extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp); From 85aab2a08824a83a535e6dfee4c150b25ebaf9de Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 27 Apr 2014 23:34:02 +0200 Subject: [PATCH 202/336] Switch miner.cpp to use sha2 instead of OpenSSL. --- src/miner.cpp | 162 +++++++-------------------------------- src/miner.h | 4 - src/test/miner_tests.cpp | 28 ------- 3 files changed, 29 insertions(+), 165 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index c48c9f0521..7efca7cfff 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -6,14 +6,13 @@ #include "miner.h" #include "core.h" +#include "hash.h" #include "main.h" #include "net.h" #ifdef ENABLE_WALLET #include "wallet.h" #endif -#include - using namespace std; ////////////////////////////////////////////////////////////////////////////// @@ -21,42 +20,6 @@ using namespace std; // BitcoinMiner // -int static FormatHashBlocks(void* pbuffer, unsigned int len) -{ - unsigned char* pdata = (unsigned char*)pbuffer; - unsigned int blocks = 1 + ((len + 8) / 64); - unsigned char* pend = pdata + 64 * blocks; - memset(pdata + len, 0, 64 * blocks - len); - pdata[len] = 0x80; - unsigned int bits = len * 8; - pend[-1] = (bits >> 0) & 0xff; - pend[-2] = (bits >> 8) & 0xff; - pend[-3] = (bits >> 16) & 0xff; - pend[-4] = (bits >> 24) & 0xff; - return blocks; -} - -static const unsigned int pSHA256InitState[8] = -{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - -void SHA256Transform(void* pstate, void* pinput, const void* pinit) -{ - SHA256_CTX ctx; - unsigned char data[64]; - - SHA256_Init(&ctx); - - for (int i = 0; i < 16; i++) - ((uint32_t*)data)[i] = ByteReverse(((uint32_t*)pinput)[i]); - - for (int i = 0; i < 8; i++) - ctx.h[i] = ((uint32_t*)pinit)[i]; - - SHA256_Update(&ctx, data, sizeof(data)); - for (int i = 0; i < 8; i++) - ((uint32_t*)pstate)[i] = ctx.h[i]; -} - // // Unconfirmed transactions in the memory pool often depend on other // transactions in the memory pool. When we select transactions from the @@ -372,51 +335,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& } -void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1) -{ - // - // Pre-build hash buffers - // - struct - { - struct unnamed2 - { - int nVersion; - uint256 hashPrevBlock; - uint256 hashMerkleRoot; - unsigned int nTime; - unsigned int nBits; - unsigned int nNonce; - } - block; - unsigned char pchPadding0[64]; - uint256 hash1; - unsigned char pchPadding1[64]; - } - tmp; - memset(&tmp, 0, sizeof(tmp)); - - tmp.block.nVersion = pblock->nVersion; - tmp.block.hashPrevBlock = pblock->hashPrevBlock; - tmp.block.hashMerkleRoot = pblock->hashMerkleRoot; - tmp.block.nTime = pblock->nTime; - tmp.block.nBits = pblock->nBits; - tmp.block.nNonce = pblock->nNonce; - - FormatHashBlocks(&tmp.block, sizeof(tmp.block)); - FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1)); - - // Byte swap all the input buffer - for (unsigned int i = 0; i < sizeof(tmp)/4; i++) - ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]); - - // Precalc the first half of the first hash, which stays constant - SHA256Transform(pmidstate, &tmp.block, pSHA256InitState); - - memcpy(pdata, &tmp.block, 128); - memcpy(phash1, &tmp.hash1, 64); -} - #ifdef ENABLE_WALLET ////////////////////////////////////////////////////////////////////////////// // @@ -427,34 +345,33 @@ int64_t nHPSTimerStart = 0; // // ScanHash scans nonces looking for a hash with at least some zero bits. -// It operates on big endian data. Caller does the byte reversing. -// All input buffers are 16-byte aligned. nNonce is usually preserved -// between calls, but periodically or if nNonce is 0xffff0000 or above, -// the block is rebuilt and nNonce starts over at zero. +// The nonce is usually preserved between calls, but periodically or if the +// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at +// zero. // -unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone) -{ - unsigned int& nNonce = *(unsigned int*)(pdata + 12); - for (;;) - { - // Crypto++ SHA256 - // Hash pdata using pmidstate as the starting state into - // pre-formatted buffer phash1, then hash phash1 into phash +bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) { + // Write the first 76 bytes of the block header to a double-SHA256 state. + CHash256 hasher; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << *pblock; + assert(ss.size() == 80); + hasher.Write((unsigned char*)&ss[0], 76); + + for (;;) { nNonce++; - SHA256Transform(phash1, pdata, pmidstate); - SHA256Transform(phash, phash1, pSHA256InitState); + + // Write the last 4 bytes of the block header (the nonce) to a copy of + // the double-SHA256 state, and compute the result. + CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash); // Return the nonce if the hash has at least some zero bits, // caller will check if it has enough to reach the target - if (((unsigned short*)phash)[14] == 0) - return nNonce; + if (((uint16_t*)phash)[15] == 0) + return true; // If nothing found after trying for a while, return -1 if ((nNonce & 0xffff) == 0) - { - nHashesDone = 0xffff+1; - return (unsigned int) -1; - } + return false; if ((nNonce & 0xfff) == 0) boost::this_thread::interruption_point(); } @@ -541,46 +458,27 @@ void static BitcoinMiner(CWallet *pwallet) LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - // - // Pre-build hash buffers - // - char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf); - char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf); - char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf); - - FormatHashBuffers(pblock, pmidstate, pdata, phash1); - - unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4); - unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8); - unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12); - - // // Search // int64_t nStart = GetTime(); uint256 hashTarget = uint256().SetCompact(pblock->nBits); - uint256 hashbuf[2]; - uint256& hash = *alignup<16>(hashbuf); + uint256 hash; + uint32_t nNonce = 0; + uint32_t nOldNonce = 0; while (true) { - unsigned int nHashesDone = 0; - unsigned int nNonceFound; - - // Crypto++ SHA256 - nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1, - (char*)&hash, nHashesDone); + bool fFound = ScanHash(pblock, nNonce, &hash); + uint32_t nHashesDone = nNonce - nOldNonce; + nOldNonce = nNonce; // Check if something found - if (nNonceFound != (unsigned int) -1) + if (fFound) { - for (unsigned int i = 0; i < sizeof(hash)/4; i++) - ((unsigned int*)&hash)[i] = ByteReverse(((unsigned int*)&hash)[i]); - if (hash <= hashTarget) { // Found a solution - pblock->nNonce = ByteReverse(nNonceFound); + pblock->nNonce = nNonce; assert(hash == pblock->GetHash()); SetThreadPriority(THREAD_PRIORITY_NORMAL); @@ -629,7 +527,7 @@ void static BitcoinMiner(CWallet *pwallet) // Regtest mode doesn't require peers if (vNodes.empty() && Params().MiningRequiresPeers()) break; - if (nBlockNonce >= 0xffff0000) + if (nNonce >= 0xffff0000) break; if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) break; @@ -638,11 +536,9 @@ void static BitcoinMiner(CWallet *pwallet) // Update nTime every few seconds UpdateTime(*pblock, pindexPrev); - nBlockTime = ByteReverse(pblock->nTime); if (Params().AllowMinDifficultyBlocks()) { // Changing pblock->nTime can change work required on testnet: - nBlockBits = ByteReverse(pblock->nBits); hashTarget.SetCompact(pblock->nBits); } } diff --git a/src/miner.h b/src/miner.h index dcd61d8fd9..1fa499dc5b 100644 --- a/src/miner.h +++ b/src/miner.h @@ -23,12 +23,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); -/** Do mining precalculation */ -void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); /** Check mined block */ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); -/** Base sha256 mining transform */ -void SHA256Transform(void* pstate, void* pinput, const void* pinit); extern double dHashesPerSec; extern int64_t nHPSTimerStart; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index b72ba0293f..bff6de41a3 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -9,8 +9,6 @@ #include -extern void SHA256Transform(void* pstate, void* pinput, const void* pinit); - BOOST_AUTO_TEST_SUITE(miner_tests) static @@ -259,30 +257,4 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } -BOOST_AUTO_TEST_CASE(sha256transform_equality) -{ - unsigned int pSHA256InitState[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - - - // unsigned char pstate[32]; - unsigned char pinput[64]; - - int i; - - for (i = 0; i < 32; i++) { - pinput[i] = i; - pinput[i+32] = 0; - } - - uint256 hash; - - SHA256Transform(&hash, pinput, pSHA256InitState); - - BOOST_TEST_MESSAGE(hash.GetHex()); - - uint256 hash_reference("0x2df5e1c65ef9f8cde240d23cae2ec036d31a15ec64bc68f64be242b1da6631f3"); - - BOOST_CHECK(hash == hash_reference); -} - BOOST_AUTO_TEST_SUITE_END() From 1cc344ce42d8dddd6356c89ef3ceb58418676816 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 28 Apr 2014 03:09:13 +0200 Subject: [PATCH 203/336] Add built-in SHA-1 implementation. --- src/Makefile.am | 2 + src/Makefile.test.include | 1 + src/script.cpp | 5 +- src/sha1.cpp | 205 ++++++++++++++++++++++++++++++++++++++ src/sha1.h | 25 +++++ src/test/sha1_tests.cpp | 27 +++++ 6 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 src/sha1.cpp create mode 100644 src/sha1.h create mode 100644 src/test/sha1_tests.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 4e94d47066..67b069bde1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,6 +76,7 @@ BITCOIN_CORE_H = \ script.h \ serialize.h \ sha2.h \ + sha1.h \ sync.h \ threadsafety.h \ tinyformat.h \ @@ -153,6 +154,7 @@ libbitcoin_common_a_SOURCES = \ protocol.cpp \ rpcprotocol.cpp \ script.cpp \ + sha1.cpp \ sha2.cpp \ sync.cpp \ util.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 93723309af..7cf441bd6c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -45,6 +45,7 @@ BITCOIN_TESTS =\ test/script_P2SH_tests.cpp \ test/script_tests.cpp \ test/serialize_tests.cpp \ + test/sha1_tests.cpp \ test/sha2_tests.cpp \ test/sigopcount_tests.cpp \ test/test_bitcoin.cpp \ diff --git a/src/script.cpp b/src/script.cpp index f20c0bcca3..facf3044d6 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -9,13 +9,12 @@ #include "hash.h" #include "key.h" #include "keystore.h" +#include "sha1.h" #include "sha2.h" #include "sync.h" #include "uint256.h" #include "util.h" -#include - #include #include #include @@ -806,7 +805,7 @@ bool EvalScript(vector >& stack, const CScript& script, co if (opcode == OP_RIPEMD160) RIPEMD160(&vch[0], vch.size(), &vchHash[0]); else if (opcode == OP_SHA1) - SHA1(&vch[0], vch.size(), &vchHash[0]); + CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_SHA256) CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_HASH160) diff --git a/src/sha1.cpp b/src/sha1.cpp new file mode 100644 index 0000000000..0a70077544 --- /dev/null +++ b/src/sha1.cpp @@ -0,0 +1,205 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sha1.h" + +#include + +// Internal implementation code. +namespace { + +/** Read 4 bytes, and interpret them as a 32-bit unsigned big-endian integer. */ +uint32_t inline ReadBE32(const unsigned char *data) { + return ((uint32_t)data[0] << 24 | (uint32_t)data[1] << 16 | (uint32_t)data[2] << 8 | (uint32_t)data[3]); +} + +/** Write a 32-bit unsigned big-endian integer. */ +void inline WriteBE32(unsigned char *data, uint32_t x) { + data[0] = x >> 24; + data[1] = x >> 16; + data[2] = x >> 8; + data[3] = x; +} + +/// Internal SHA-1 implementation. +namespace sha1 { + +/** One round of SHA-1. */ +void inline Round(uint32_t a, uint32_t &b, uint32_t c, uint32_t d, uint32_t &e, + uint32_t f, uint32_t k, uint32_t w) { + e += ((a << 5) | (a >> 27)) + f + k + w; + b = (b << 30) | (b >> 2); +} + +uint32_t inline f1(uint32_t b, uint32_t c, uint32_t d) { return d ^ (b & (c ^ d)); } +uint32_t inline f2(uint32_t b, uint32_t c, uint32_t d) { return b ^ c ^ d; } +uint32_t inline f3(uint32_t b, uint32_t c, uint32_t d) { return (b & c) | (d & (b | c)); } + +uint32_t inline left(uint32_t x) { return (x << 1) | (x >> 31); } + +/** Initialize SHA-1 state. */ +void inline Initialize(uint32_t *s) { + s[0] = 0x67452301ul; + s[1] = 0xEFCDAB89ul; + s[2] = 0x98BADCFEul; + s[3] = 0x10325476ul; + s[4] = 0xC3D2E1F0ul; +} + +const uint32_t k1 = 0x5A827999ul; +const uint32_t k2 = 0x6ED9EBA1ul; +const uint32_t k3 = 0x8F1BBCDCul; +const uint32_t k4 = 0xCA62C1D6ul; + +/** Perform a SHA-1 transformation, processing a 64-byte chunk. */ +void Transform(uint32_t *s, const unsigned char *chunk) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f1(b, c, d), k1, w0 = ReadBE32(chunk + 0)); + Round(e, a, b, c, d, f1(a, b, c), k1, w1 = ReadBE32(chunk + 4)); + Round(d, e, a, b, c, f1(e, a, b), k1, w2 = ReadBE32(chunk + 8)); + Round(c, d, e, a, b, f1(d, e, a), k1, w3 = ReadBE32(chunk + 12)); + Round(b, c, d, e, a, f1(c, d, e), k1, w4 = ReadBE32(chunk + 16)); + Round(a, b, c, d, e, f1(b, c, d), k1, w5 = ReadBE32(chunk + 20)); + Round(e, a, b, c, d, f1(a, b, c), k1, w6 = ReadBE32(chunk + 24)); + Round(d, e, a, b, c, f1(e, a, b), k1, w7 = ReadBE32(chunk + 28)); + Round(c, d, e, a, b, f1(d, e, a), k1, w8 = ReadBE32(chunk + 32)); + Round(b, c, d, e, a, f1(c, d, e), k1, w9 = ReadBE32(chunk + 36)); + Round(a, b, c, d, e, f1(b, c, d), k1, w10 = ReadBE32(chunk + 40)); + Round(e, a, b, c, d, f1(a, b, c), k1, w11 = ReadBE32(chunk + 44)); + Round(d, e, a, b, c, f1(e, a, b), k1, w12 = ReadBE32(chunk + 48)); + Round(c, d, e, a, b, f1(d, e, a), k1, w13 = ReadBE32(chunk + 52)); + Round(b, c, d, e, a, f1(c, d, e), k1, w14 = ReadBE32(chunk + 56)); + Round(a, b, c, d, e, f1(b, c, d), k1, w15 = ReadBE32(chunk + 60)); + + Round(e, a, b, c, d, f1(a, b, c), k1, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); + Round(d, e, a, b, c, f1(e, a, b), k1, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); + Round(c, d, e, a, b, f1(d, e, a), k1, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); + Round(b, c, d, e, a, f1(c, d, e), k1, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); + Round(a, b, c, d, e, f2(b, c, d), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); + Round(e, a, b, c, d, f2(a, b, c), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); + Round(d, e, a, b, c, f2(e, a, b), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); + Round(c, d, e, a, b, f2(d, e, a), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); + Round(b, c, d, e, a, f2(c, d, e), k2, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(a, b, c, d, e, f2(b, c, d), k2, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(e, a, b, c, d, f2(a, b, c), k2, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(d, e, a, b, c, f2(e, a, b), k2, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(c, d, e, a, b, f2(d, e, a), k2, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(b, c, d, e, a, f2(c, d, e), k2, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(a, b, c, d, e, f2(b, c, d), k2, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); + Round(e, a, b, c, d, f2(a, b, c), k2, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); + + Round(d, e, a, b, c, f2(e, a, b), k2, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); + Round(c, d, e, a, b, f2(d, e, a), k2, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); + Round(b, c, d, e, a, f2(c, d, e), k2, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); + Round(a, b, c, d, e, f2(b, c, d), k2, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); + Round(e, a, b, c, d, f2(a, b, c), k2, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); + Round(d, e, a, b, c, f2(e, a, b), k2, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); + Round(c, d, e, a, b, f2(d, e, a), k2, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); + Round(b, c, d, e, a, f2(c, d, e), k2, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); + Round(a, b, c, d, e, f3(b, c, d), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(e, a, b, c, d, f3(a, b, c), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(d, e, a, b, c, f3(e, a, b), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(c, d, e, a, b, f3(d, e, a), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(b, c, d, e, a, f3(c, d, e), k3, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(a, b, c, d, e, f3(b, c, d), k3, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(e, a, b, c, d, f3(a, b, c), k3, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); + Round(d, e, a, b, c, f3(e, a, b), k3, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); + + Round(c, d, e, a, b, f3(d, e, a), k3, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); + Round(b, c, d, e, a, f3(c, d, e), k3, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); + Round(a, b, c, d, e, f3(b, c, d), k3, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); + Round(e, a, b, c, d, f3(a, b, c), k3, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); + Round(d, e, a, b, c, f3(e, a, b), k3, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); + Round(c, d, e, a, b, f3(d, e, a), k3, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); + Round(b, c, d, e, a, f3(c, d, e), k3, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); + Round(a, b, c, d, e, f3(b, c, d), k3, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); + Round(e, a, b, c, d, f3(a, b, c), k3, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(d, e, a, b, c, f3(e, a, b), k3, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(c, d, e, a, b, f3(d, e, a), k3, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(b, c, d, e, a, f3(c, d, e), k3, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(a, b, c, d, e, f2(b, c, d), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(e, a, b, c, d, f2(a, b, c), k4, w13 = left(w13 ^ w10 ^ w5 ^ w15)); + Round(d, e, a, b, c, f2(e, a, b), k4, w14 = left(w14 ^ w11 ^ w6 ^ w0 )); + Round(c, d, e, a, b, f2(d, e, a), k4, w15 = left(w15 ^ w12 ^ w7 ^ w1 )); + + Round(b, c, d, e, a, f2(c, d, e), k4, w0 = left(w0 ^ w13 ^ w8 ^ w2 )); + Round(a, b, c, d, e, f2(b, c, d), k4, w1 = left(w1 ^ w14 ^ w9 ^ w3 )); + Round(e, a, b, c, d, f2(a, b, c), k4, w2 = left(w2 ^ w15 ^ w10 ^ w4 )); + Round(d, e, a, b, c, f2(e, a, b), k4, w3 = left(w3 ^ w0 ^ w11 ^ w5 )); + Round(c, d, e, a, b, f2(d, e, a), k4, w4 = left(w4 ^ w1 ^ w12 ^ w6 )); + Round(b, c, d, e, a, f2(c, d, e), k4, w5 = left(w5 ^ w2 ^ w13 ^ w7 )); + Round(a, b, c, d, e, f2(b, c, d), k4, w6 = left(w6 ^ w3 ^ w14 ^ w8 )); + Round(e, a, b, c, d, f2(a, b, c), k4, w7 = left(w7 ^ w4 ^ w15 ^ w9 )); + Round(d, e, a, b, c, f2(e, a, b), k4, w8 = left(w8 ^ w5 ^ w0 ^ w10)); + Round(c, d, e, a, b, f2(d, e, a), k4, w9 = left(w9 ^ w6 ^ w1 ^ w11)); + Round(b, c, d, e, a, f2(c, d, e), k4, w10 = left(w10 ^ w7 ^ w2 ^ w12)); + Round(a, b, c, d, e, f2(b, c, d), k4, w11 = left(w11 ^ w8 ^ w3 ^ w13)); + Round(e, a, b, c, d, f2(a, b, c), k4, w12 = left(w12 ^ w9 ^ w4 ^ w14)); + Round(d, e, a, b, c, f2(e, a, b), k4, left(w13 ^ w10 ^ w5 ^ w15)); + Round(c, d, e, a, b, f2(d, e, a), k4, left(w14 ^ w11 ^ w6 ^ w0 )); + Round(b, c, d, e, a, f2(c, d, e), k4, left(w15 ^ w12 ^ w7 ^ w1 )); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; +} + +} // namespace sha1 + +} // namespace + +////// SHA1 + +CSHA1::CSHA1() : bytes(0) { + sha1::Initialize(s); +} + +CSHA1& CSHA1::Write(const unsigned char *data, size_t len) { + const unsigned char *end = data + len; + size_t bufsize = bytes % 64; + if (bufsize && bufsize + len >= 64) { + // Fill the buffer, and process it. + memcpy(buf + bufsize, data, 64 - bufsize); + bytes += 64 - bufsize; + data += 64 - bufsize; + sha1::Transform(s, buf); + bufsize = 0; + } + while (end >= data + 64) { + // Process full chunks directly from the source. + sha1::Transform(s, data); + bytes += 64; + data += 64; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(buf + bufsize, data, end - data); + bytes += end - data; + } + return *this; +} + +void CSHA1::Finalize(unsigned char *hash) { + static const unsigned char pad[64] = {0x80}; + unsigned char sizedesc[8]; + WriteBE32(sizedesc, bytes >> 29); + WriteBE32(sizedesc+4, bytes << 3); + Write(pad, 1 + ((119 - (bytes % 64)) % 64)); + Write(sizedesc, 8); + WriteBE32(hash, s[0]); + WriteBE32(hash+4, s[1]); + WriteBE32(hash+8, s[2]); + WriteBE32(hash+12, s[3]); + WriteBE32(hash+16, s[4]); +} + +CSHA1& CSHA1::Reset() { + bytes = 0; + sha1::Initialize(s); + return *this; +} diff --git a/src/sha1.h b/src/sha1.h new file mode 100644 index 0000000000..6efde78a5b --- /dev/null +++ b/src/sha1.h @@ -0,0 +1,25 @@ +// Copyright (c) 2014 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 BITCOIN_SHA1_H +#define BITCOIN_SHA1_H + +#include +#include + +/** A hasher class for SHA1. */ +class CSHA1 { +private: + uint32_t s[5]; + unsigned char buf[64]; + size_t bytes; + +public: + CSHA1(); + CSHA1& Write(const unsigned char *data, size_t len); + void Finalize(unsigned char *hash); + CSHA1& Reset(); +}; + +#endif diff --git a/src/test/sha1_tests.cpp b/src/test/sha1_tests.cpp new file mode 100644 index 0000000000..bae17c5d4a --- /dev/null +++ b/src/test/sha1_tests.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sha1.h" +#include "util.h" + +#include + +#include + +BOOST_AUTO_TEST_SUITE(sha1_tests) + +void SHA1TestVector(const std::string &in, const std::string &out) { + std::vector hash; + hash.resize(20); + CSHA1().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); + BOOST_CHECK_EQUAL(HexStr(hash), out); +} + +BOOST_AUTO_TEST_CASE(sha1_testvectors) { + SHA1TestVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"); + SHA1TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + SHA1TestVector(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); +} + +BOOST_AUTO_TEST_SUITE_END() From 13b5dfef64bbb77d583b2acc59e2b33f89645308 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 28 Apr 2014 12:20:15 +0200 Subject: [PATCH 204/336] Move crypto implementations to src/crypto/ --- src/Makefile.am | 8 ++++---- src/{ => crypto}/sha1.cpp | 2 +- src/{ => crypto}/sha1.h | 0 src/{ => crypto}/sha2.cpp | 2 +- src/{ => crypto}/sha2.h | 0 src/hash.h | 2 +- src/key.cpp | 2 +- src/script.cpp | 4 ++-- src/test/sha1_tests.cpp | 2 +- src/test/sha2_tests.cpp | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) rename src/{ => crypto}/sha1.cpp (99%) rename src/{ => crypto}/sha1.h (100%) rename src/{ => crypto}/sha2.cpp (99%) rename src/{ => crypto}/sha2.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index 67b069bde1..bc65119a92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,8 +75,8 @@ BITCOIN_CORE_H = \ rpcserver.h \ script.h \ serialize.h \ - sha2.h \ - sha1.h \ + crypto/sha2.h \ + crypto/sha1.h \ sync.h \ threadsafety.h \ tinyformat.h \ @@ -154,8 +154,8 @@ libbitcoin_common_a_SOURCES = \ protocol.cpp \ rpcprotocol.cpp \ script.cpp \ - sha1.cpp \ - sha2.cpp \ + crypto/sha1.cpp \ + crypto/sha2.cpp \ sync.cpp \ util.cpp \ version.cpp \ diff --git a/src/sha1.cpp b/src/crypto/sha1.cpp similarity index 99% rename from src/sha1.cpp rename to src/crypto/sha1.cpp index 0a70077544..4b2e3e19d1 100644 --- a/src/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sha1.h" +#include "crypto/sha1.h" #include diff --git a/src/sha1.h b/src/crypto/sha1.h similarity index 100% rename from src/sha1.h rename to src/crypto/sha1.h diff --git a/src/sha2.cpp b/src/crypto/sha2.cpp similarity index 99% rename from src/sha2.cpp rename to src/crypto/sha2.cpp index c9beaf220b..0d0c32883f 100644 --- a/src/sha2.cpp +++ b/src/crypto/sha2.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sha2.h" +#include "crypto/sha2.h" #include diff --git a/src/sha2.h b/src/crypto/sha2.h similarity index 100% rename from src/sha2.h rename to src/crypto/sha2.h diff --git a/src/hash.h b/src/hash.h index 9e7a67550f..318399c334 100644 --- a/src/hash.h +++ b/src/hash.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H -#include "sha2.h" +#include "crypto/sha2.h" #include "serialize.h" #include "uint256.h" #include "version.h" diff --git a/src/key.cpp b/src/key.cpp index 0685948922..96b1ac439c 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -4,7 +4,7 @@ #include "key.h" -#include "sha2.h" +#include "crypto/sha2.h" #include #include diff --git a/src/script.cpp b/src/script.cpp index facf3044d6..c6574a6ee8 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -9,8 +9,8 @@ #include "hash.h" #include "key.h" #include "keystore.h" -#include "sha1.h" -#include "sha2.h" +#include "crypto/sha1.h" +#include "crypto/sha2.h" #include "sync.h" #include "uint256.h" #include "util.h" diff --git a/src/test/sha1_tests.cpp b/src/test/sha1_tests.cpp index bae17c5d4a..88f2da0bbb 100644 --- a/src/test/sha1_tests.cpp +++ b/src/test/sha1_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sha1.h" +#include "crypto/sha1.h" #include "util.h" #include diff --git a/src/test/sha2_tests.cpp b/src/test/sha2_tests.cpp index 516b942ad3..1e48c973cf 100644 --- a/src/test/sha2_tests.cpp +++ b/src/test/sha2_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "sha2.h" +#include "crypto/sha2.h" #include "util.h" #include From a5bc9c09177420bd1c6a1f9ece9ecfbe80c453fe Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 1 May 2014 00:43:31 +0200 Subject: [PATCH 205/336] Add built-in RIPEMD-160 implementation --- src/Makefile.am | 2 + src/crypto/ripemd160.cpp | 217 +++++++++++++++++++++++++++++++++++++++ src/crypto/ripemd160.h | 25 +++++ src/hash.h | 5 +- src/script.cpp | 3 +- 5 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 src/crypto/ripemd160.cpp create mode 100644 src/crypto/ripemd160.h diff --git a/src/Makefile.am b/src/Makefile.am index bc65119a92..d583a79032 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ BITCOIN_CORE_H = \ serialize.h \ crypto/sha2.h \ crypto/sha1.h \ + crypto/ripemd160.h \ sync.h \ threadsafety.h \ tinyformat.h \ @@ -156,6 +157,7 @@ libbitcoin_common_a_SOURCES = \ script.cpp \ crypto/sha1.cpp \ crypto/sha2.cpp \ + crypto/ripemd160.cpp \ sync.cpp \ util.cpp \ version.cpp \ diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp new file mode 100644 index 0000000000..aa6874fa85 --- /dev/null +++ b/src/crypto/ripemd160.cpp @@ -0,0 +1,217 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/ripemd160.h" + +#include + +// Internal implementation code. +namespace { + +/** Read 4 bytes, and interpret them as a 32-bit unsigned little-endian integer. */ +uint32_t inline ReadLE32(const unsigned char *data) { + return ((uint32_t)data[0] | (uint32_t)data[1] << 8 | (uint32_t)data[2] << 16 | (uint32_t)data[3] << 24); +} + +/** Write a 32-bit unsigned little-endian integer. */ +void inline WriteLE32(unsigned char *data, uint32_t x) { + data[0] = x; + data[1] = x >> 8; + data[2] = x >> 16; + data[3] = x >> 24; +} + +/// Internal RIPEMD-160 implementation. +namespace ripemd160 { + +uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } +uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } +uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; } +uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); } +uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); } + +/** Initialize RIPEMD-160 state. */ +void inline Initialize(uint32_t *s) { + s[0] = 0x67452301ul; + s[1] = 0xEFCDAB89ul; + s[2] = 0x98BADCFEul; + s[3] = 0x10325476ul; + s[4] = 0xC3D2E1F0ul; +} + +uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32-i)); } + +void inline Round(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) { + a = rol(a + f + x + k, r) + e; + c = rol(c, 10); +} + +void inline R11(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } +void inline R21(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x5A827999ul, r); } +void inline R31(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6ED9EBA1ul, r); } +void inline R41(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x8F1BBCDCul, r); } +void inline R51(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0xA953FD4Eul, r); } + +void inline R12(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f5(b, c, d), x, 0x50A28BE6ul, r); } +void inline R22(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f4(b, c, d), x, 0x5C4DD124ul, r); } +void inline R32(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f3(b, c, d), x, 0x6D703EF3ul, r); } +void inline R42(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f2(b, c, d), x, 0x7A6D76E9ul, r); } +void inline R52(uint32_t &a, uint32_t b, uint32_t &c, uint32_t d, uint32_t e, uint32_t x, int r) { Round(a, b, c, d, e, f1(b, c, d), x, 0, r); } + +/** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */ +void Transform(uint32_t *s, const unsigned char *chunk) { + uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4]; + uint32_t a2 = a1 , b2 = b1 , c2 = c1 , d2 = d1 , e2 = e1 ; + uint32_t w0 = ReadLE32(chunk + 0), w1 = ReadLE32(chunk + 4), w2 = ReadLE32(chunk + 8), w3 = ReadLE32(chunk + 12); + uint32_t w4 = ReadLE32(chunk + 16), w5 = ReadLE32(chunk + 20), w6 = ReadLE32(chunk + 24), w7 = ReadLE32(chunk + 28); + uint32_t w8 = ReadLE32(chunk + 32), w9 = ReadLE32(chunk + 36), w10 = ReadLE32(chunk + 40), w11 = ReadLE32(chunk + 44); + uint32_t w12 = ReadLE32(chunk + 48), w13 = ReadLE32(chunk + 52), w14 = ReadLE32(chunk + 56), w15 = ReadLE32(chunk + 60); + + R11(a1, b1, c1, d1, e1, w0 , 11); R12(a2, b2, c2, d2, e2, w5 , 8); + R11(e1, a1, b1, c1, d1, w1 , 14); R12(e2, a2, b2, c2, d2, w14, 9); + R11(d1, e1, a1, b1, c1, w2 , 15); R12(d2, e2, a2, b2, c2, w7 , 9); + R11(c1, d1, e1, a1, b1, w3 , 12); R12(c2, d2, e2, a2, b2, w0 , 11); + R11(b1, c1, d1, e1, a1, w4 , 5); R12(b2, c2, d2, e2, a2, w9 , 13); + R11(a1, b1, c1, d1, e1, w5 , 8); R12(a2, b2, c2, d2, e2, w2 , 15); + R11(e1, a1, b1, c1, d1, w6 , 7); R12(e2, a2, b2, c2, d2, w11, 15); + R11(d1, e1, a1, b1, c1, w7 , 9); R12(d2, e2, a2, b2, c2, w4 , 5); + R11(c1, d1, e1, a1, b1, w8 , 11); R12(c2, d2, e2, a2, b2, w13, 7); + R11(b1, c1, d1, e1, a1, w9 , 13); R12(b2, c2, d2, e2, a2, w6 , 7); + R11(a1, b1, c1, d1, e1, w10, 14); R12(a2, b2, c2, d2, e2, w15, 8); + R11(e1, a1, b1, c1, d1, w11, 15); R12(e2, a2, b2, c2, d2, w8 , 11); + R11(d1, e1, a1, b1, c1, w12, 6); R12(d2, e2, a2, b2, c2, w1 , 14); + R11(c1, d1, e1, a1, b1, w13, 7); R12(c2, d2, e2, a2, b2, w10, 14); + R11(b1, c1, d1, e1, a1, w14, 9); R12(b2, c2, d2, e2, a2, w3 , 12); + R11(a1, b1, c1, d1, e1, w15, 8); R12(a2, b2, c2, d2, e2, w12, 6); + + R21(e1, a1, b1, c1, d1, w7 , 7); R22(e2, a2, b2, c2, d2, w6 , 9); + R21(d1, e1, a1, b1, c1, w4 , 6); R22(d2, e2, a2, b2, c2, w11, 13); + R21(c1, d1, e1, a1, b1, w13, 8); R22(c2, d2, e2, a2, b2, w3 , 15); + R21(b1, c1, d1, e1, a1, w1 , 13); R22(b2, c2, d2, e2, a2, w7 , 7); + R21(a1, b1, c1, d1, e1, w10, 11); R22(a2, b2, c2, d2, e2, w0 , 12); + R21(e1, a1, b1, c1, d1, w6 , 9); R22(e2, a2, b2, c2, d2, w13, 8); + R21(d1, e1, a1, b1, c1, w15, 7); R22(d2, e2, a2, b2, c2, w5 , 9); + R21(c1, d1, e1, a1, b1, w3 , 15); R22(c2, d2, e2, a2, b2, w10, 11); + R21(b1, c1, d1, e1, a1, w12, 7); R22(b2, c2, d2, e2, a2, w14, 7); + R21(a1, b1, c1, d1, e1, w0 , 12); R22(a2, b2, c2, d2, e2, w15, 7); + R21(e1, a1, b1, c1, d1, w9 , 15); R22(e2, a2, b2, c2, d2, w8 , 12); + R21(d1, e1, a1, b1, c1, w5 , 9); R22(d2, e2, a2, b2, c2, w12, 7); + R21(c1, d1, e1, a1, b1, w2 , 11); R22(c2, d2, e2, a2, b2, w4 , 6); + R21(b1, c1, d1, e1, a1, w14, 7); R22(b2, c2, d2, e2, a2, w9 , 15); + R21(a1, b1, c1, d1, e1, w11, 13); R22(a2, b2, c2, d2, e2, w1 , 13); + R21(e1, a1, b1, c1, d1, w8 , 12); R22(e2, a2, b2, c2, d2, w2 , 11); + + R31(d1, e1, a1, b1, c1, w3 , 11); R32(d2, e2, a2, b2, c2, w15, 9); + R31(c1, d1, e1, a1, b1, w10, 13); R32(c2, d2, e2, a2, b2, w5 , 7); + R31(b1, c1, d1, e1, a1, w14, 6); R32(b2, c2, d2, e2, a2, w1 , 15); + R31(a1, b1, c1, d1, e1, w4 , 7); R32(a2, b2, c2, d2, e2, w3 , 11); + R31(e1, a1, b1, c1, d1, w9 , 14); R32(e2, a2, b2, c2, d2, w7 , 8); + R31(d1, e1, a1, b1, c1, w15, 9); R32(d2, e2, a2, b2, c2, w14, 6); + R31(c1, d1, e1, a1, b1, w8 , 13); R32(c2, d2, e2, a2, b2, w6 , 6); + R31(b1, c1, d1, e1, a1, w1 , 15); R32(b2, c2, d2, e2, a2, w9 , 14); + R31(a1, b1, c1, d1, e1, w2 , 14); R32(a2, b2, c2, d2, e2, w11, 12); + R31(e1, a1, b1, c1, d1, w7 , 8); R32(e2, a2, b2, c2, d2, w8 , 13); + R31(d1, e1, a1, b1, c1, w0 , 13); R32(d2, e2, a2, b2, c2, w12, 5); + R31(c1, d1, e1, a1, b1, w6 , 6); R32(c2, d2, e2, a2, b2, w2 , 14); + R31(b1, c1, d1, e1, a1, w13, 5); R32(b2, c2, d2, e2, a2, w10, 13); + R31(a1, b1, c1, d1, e1, w11, 12); R32(a2, b2, c2, d2, e2, w0 , 13); + R31(e1, a1, b1, c1, d1, w5 , 7); R32(e2, a2, b2, c2, d2, w4 , 7); + R31(d1, e1, a1, b1, c1, w12, 5); R32(d2, e2, a2, b2, c2, w13, 5); + + R41(c1, d1, e1, a1, b1, w1 , 11); R42(c2, d2, e2, a2, b2, w8 , 15); + R41(b1, c1, d1, e1, a1, w9 , 12); R42(b2, c2, d2, e2, a2, w6 , 5); + R41(a1, b1, c1, d1, e1, w11, 14); R42(a2, b2, c2, d2, e2, w4 , 8); + R41(e1, a1, b1, c1, d1, w10, 15); R42(e2, a2, b2, c2, d2, w1 , 11); + R41(d1, e1, a1, b1, c1, w0 , 14); R42(d2, e2, a2, b2, c2, w3 , 14); + R41(c1, d1, e1, a1, b1, w8 , 15); R42(c2, d2, e2, a2, b2, w11, 14); + R41(b1, c1, d1, e1, a1, w12, 9); R42(b2, c2, d2, e2, a2, w15, 6); + R41(a1, b1, c1, d1, e1, w4 , 8); R42(a2, b2, c2, d2, e2, w0 , 14); + R41(e1, a1, b1, c1, d1, w13, 9); R42(e2, a2, b2, c2, d2, w5 , 6); + R41(d1, e1, a1, b1, c1, w3 , 14); R42(d2, e2, a2, b2, c2, w12, 9); + R41(c1, d1, e1, a1, b1, w7 , 5); R42(c2, d2, e2, a2, b2, w2 , 12); + R41(b1, c1, d1, e1, a1, w15, 6); R42(b2, c2, d2, e2, a2, w13, 9); + R41(a1, b1, c1, d1, e1, w14, 8); R42(a2, b2, c2, d2, e2, w9 , 12); + R41(e1, a1, b1, c1, d1, w5 , 6); R42(e2, a2, b2, c2, d2, w7 , 5); + R41(d1, e1, a1, b1, c1, w6 , 5); R42(d2, e2, a2, b2, c2, w10, 15); + R41(c1, d1, e1, a1, b1, w2 , 12); R42(c2, d2, e2, a2, b2, w14, 8); + + R51(b1, c1, d1, e1, a1, w4 , 9); R52(b2, c2, d2, e2, a2, w12, 8); + R51(a1, b1, c1, d1, e1, w0 , 15); R52(a2, b2, c2, d2, e2, w15, 5); + R51(e1, a1, b1, c1, d1, w5 , 5); R52(e2, a2, b2, c2, d2, w10, 12); + R51(d1, e1, a1, b1, c1, w9 , 11); R52(d2, e2, a2, b2, c2, w4 , 9); + R51(c1, d1, e1, a1, b1, w7 , 6); R52(c2, d2, e2, a2, b2, w1 , 12); + R51(b1, c1, d1, e1, a1, w12, 8); R52(b2, c2, d2, e2, a2, w5 , 5); + R51(a1, b1, c1, d1, e1, w2 , 13); R52(a2, b2, c2, d2, e2, w8 , 14); + R51(e1, a1, b1, c1, d1, w10, 12); R52(e2, a2, b2, c2, d2, w7 , 6); + R51(d1, e1, a1, b1, c1, w14, 5); R52(d2, e2, a2, b2, c2, w6 , 8); + R51(c1, d1, e1, a1, b1, w1 , 12); R52(c2, d2, e2, a2, b2, w2 , 13); + R51(b1, c1, d1, e1, a1, w3 , 13); R52(b2, c2, d2, e2, a2, w13, 6); + R51(a1, b1, c1, d1, e1, w8 , 14); R52(a2, b2, c2, d2, e2, w14, 5); + R51(e1, a1, b1, c1, d1, w11, 11); R52(e2, a2, b2, c2, d2, w0 , 15); + R51(d1, e1, a1, b1, c1, w6 , 8); R52(d2, e2, a2, b2, c2, w3 , 13); + R51(c1, d1, e1, a1, b1, w15, 5); R52(c2, d2, e2, a2, b2, w9 , 11); + R51(b1, c1, d1, e1, a1, w13, 6); R52(b2, c2, d2, e2, a2, w11, 11); + + uint32_t t = s[0]; + s[0] = s[1] + c1 + d2; + s[1] = s[2] + d1 + e2; + s[2] = s[3] + e1 + a2; + s[3] = s[4] + a1 + b2; + s[4] = t + b1 + c2; +} + +} // namespace ripemd160 + +} // namespace + +////// RIPEMD160 + +CRIPEMD160::CRIPEMD160() : bytes(0) { + ripemd160::Initialize(s); +} + +CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) { + const unsigned char *end = data + len; + size_t bufsize = bytes % 64; + if (bufsize && bufsize + len >= 64) { + // Fill the buffer, and process it. + memcpy(buf + bufsize, data, 64 - bufsize); + bytes += 64 - bufsize; + data += 64 - bufsize; + ripemd160::Transform(s, buf); + bufsize = 0; + } + while (end >= data + 64) { + // Process full chunks directly from the source. + ripemd160::Transform(s, data); + bytes += 64; + data += 64; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(buf + bufsize, data, end - data); + bytes += end - data; + } + return *this; +} + +void CRIPEMD160::Finalize(unsigned char *hash) { + static const unsigned char pad[64] = {0x80}; + unsigned char sizedesc[8]; + WriteLE32(sizedesc, bytes << 3); + WriteLE32(sizedesc+4, bytes >> 29); + Write(pad, 1 + ((119 - (bytes % 64)) % 64)); + Write(sizedesc, 8); + WriteLE32(hash, s[0]); + WriteLE32(hash+4, s[1]); + WriteLE32(hash+8, s[2]); + WriteLE32(hash+12, s[3]); + WriteLE32(hash+16, s[4]); +} + +CRIPEMD160& CRIPEMD160::Reset() { + bytes = 0; + ripemd160::Initialize(s); + return *this; +} diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h new file mode 100644 index 0000000000..cab1d0bb46 --- /dev/null +++ b/src/crypto/ripemd160.h @@ -0,0 +1,25 @@ +// Copyright (c) 2014 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 BITCOIN_RIPEMD160_H +#define BITCOIN_RIPEMD160_H + +#include +#include + +/** A hasher class for RIPEMD-160. */ +class CRIPEMD160 { +private: + uint32_t s[5]; + unsigned char buf[64]; + size_t bytes; + +public: + CRIPEMD160(); + CRIPEMD160& Write(const unsigned char *data, size_t len); + void Finalize(unsigned char *hash); + CRIPEMD160& Reset(); +}; + +#endif diff --git a/src/hash.h b/src/hash.h index 318399c334..39d42eefe2 100644 --- a/src/hash.h +++ b/src/hash.h @@ -7,14 +7,13 @@ #define BITCOIN_HASH_H #include "crypto/sha2.h" +#include "crypto/ripemd160.h" #include "serialize.h" #include "uint256.h" #include "version.h" #include -#include - /** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */ class CHash256 { private: @@ -45,7 +44,7 @@ public: void Finalize(unsigned char *hash) { unsigned char buf[32]; sha.Finalize(buf); - RIPEMD160(buf, 32, hash); + CRIPEMD160().Write(buf, 32).Finalize(hash); } CHash160& Write(const unsigned char *data, size_t len) { diff --git a/src/script.cpp b/src/script.cpp index c6574a6ee8..b383a00a6e 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -11,6 +11,7 @@ #include "keystore.h" #include "crypto/sha1.h" #include "crypto/sha2.h" +#include "crypto/ripemd160.h" #include "sync.h" #include "uint256.h" #include "util.h" @@ -803,7 +804,7 @@ bool EvalScript(vector >& stack, const CScript& script, co valtype& vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) - RIPEMD160(&vch[0], vch.size(), &vchHash[0]); + CRIPEMD160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_SHA1) CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); else if (opcode == OP_SHA256) From 7ecd9739d9439624399a4882a9f196ccf0c7ba4a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 3 May 2014 01:04:18 +0200 Subject: [PATCH 206/336] Move {Read,Write}{LE,BE}{32,64} to common.h and use builtins if possible --- src/Makefile.am | 1 + src/crypto/common.h | 46 ++++++++++++++++++++++++++++++++++++++++ src/crypto/ripemd160.cpp | 17 ++------------- src/crypto/sha1.cpp | 17 ++------------- src/crypto/sha2.cpp | 32 +--------------------------- 5 files changed, 52 insertions(+), 61 deletions(-) create mode 100644 src/crypto/common.h diff --git a/src/Makefile.am b/src/Makefile.am index d583a79032..01655b7011 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,6 +75,7 @@ BITCOIN_CORE_H = \ rpcserver.h \ script.h \ serialize.h \ + crypto/common.h \ crypto/sha2.h \ crypto/sha1.h \ crypto/ripemd160.h \ diff --git a/src/crypto/common.h b/src/crypto/common.h new file mode 100644 index 0000000000..e1bcd3ae11 --- /dev/null +++ b/src/crypto/common.h @@ -0,0 +1,46 @@ +// Copyright (c) 2014 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 BITCOIN_CRYPTO_COMMON_H +#define BITCOIN_CRYPTO_COMMON_H + +#include + +#ifdef WIN32 +uint32_t static inline ReadLE32(const unsigned char *ptr) { return *((uint32_t*)ptr); } +uint64_t static inline ReadLE64(const unsigned char *ptr) { return *((uint64_t*)ptr); } + +void static inline WriteLE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = x; } +void static inline WriteLE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = x; } + +uint32_t static inline ReadBE32(const unsigned char *ptr) { + return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]); +} + +uint64_t static inline ReadBE64(const unsigned char *ptr) { + return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 | + (uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]); +} + +void static inline WriteBE32(unsigned char *ptr, uint32_t x) { + ptr[0] = x >> 24; ptr[1] = x >> 16; ptr[2] = x >> 8; ptr[3] = x; +} + +void static inline WriteBE64(unsigned char *ptr, uint64_t x) { + ptr[0] = x >> 56; ptr[1] = x >> 48; ptr[2] = x >> 40; ptr[3] = x >> 32; + ptr[4] = x >> 24; ptr[5] = x >> 16; ptr[6] = x >> 8; ptr[7] = x; +} +#else +# include +uint32_t static inline ReadLE32(const unsigned char *ptr) { return le32toh(*((uint32_t*)ptr)); } +uint64_t static inline ReadLE64(const unsigned char *ptr) { return le64toh(*((uint64_t*)ptr)); } +void static inline WriteLE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = htole32(x); } +void static inline WriteLE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = htole64(x); } + +uint32_t static inline ReadBE32(const unsigned char *ptr) { return be32toh(*((uint32_t*)ptr)); } +uint64_t static inline ReadBE64(const unsigned char *ptr) { return be64toh(*((uint64_t*)ptr)); } +void static inline WriteBE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = htobe32(x); } +void static inline WriteBE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = htobe64(x); } +#endif +#endif diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index aa6874fa85..c5e6e2d696 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -4,24 +4,12 @@ #include "crypto/ripemd160.h" +#include "crypto/common.h" #include // Internal implementation code. namespace { -/** Read 4 bytes, and interpret them as a 32-bit unsigned little-endian integer. */ -uint32_t inline ReadLE32(const unsigned char *data) { - return ((uint32_t)data[0] | (uint32_t)data[1] << 8 | (uint32_t)data[2] << 16 | (uint32_t)data[3] << 24); -} - -/** Write a 32-bit unsigned little-endian integer. */ -void inline WriteLE32(unsigned char *data, uint32_t x) { - data[0] = x; - data[1] = x >> 8; - data[2] = x >> 16; - data[3] = x >> 24; -} - /// Internal RIPEMD-160 implementation. namespace ripemd160 { @@ -199,8 +187,7 @@ CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) { void CRIPEMD160::Finalize(unsigned char *hash) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; - WriteLE32(sizedesc, bytes << 3); - WriteLE32(sizedesc+4, bytes >> 29); + WriteLE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteLE32(hash, s[0]); diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index 4b2e3e19d1..e0f32b7d1d 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -4,24 +4,12 @@ #include "crypto/sha1.h" +#include "crypto/common.h" #include // Internal implementation code. namespace { -/** Read 4 bytes, and interpret them as a 32-bit unsigned big-endian integer. */ -uint32_t inline ReadBE32(const unsigned char *data) { - return ((uint32_t)data[0] << 24 | (uint32_t)data[1] << 16 | (uint32_t)data[2] << 8 | (uint32_t)data[3]); -} - -/** Write a 32-bit unsigned big-endian integer. */ -void inline WriteBE32(unsigned char *data, uint32_t x) { - data[0] = x >> 24; - data[1] = x >> 16; - data[2] = x >> 8; - data[3] = x; -} - /// Internal SHA-1 implementation. namespace sha1 { @@ -187,8 +175,7 @@ CSHA1& CSHA1::Write(const unsigned char *data, size_t len) { void CSHA1::Finalize(unsigned char *hash) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; - WriteBE32(sizedesc, bytes >> 29); - WriteBE32(sizedesc+4, bytes << 3); + WriteBE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteBE32(hash, s[0]); diff --git a/src/crypto/sha2.cpp b/src/crypto/sha2.cpp index 0d0c32883f..77f35f38d8 100644 --- a/src/crypto/sha2.cpp +++ b/src/crypto/sha2.cpp @@ -4,42 +4,12 @@ #include "crypto/sha2.h" +#include "crypto/common.h" #include // Internal implementation code. namespace { -/** Read 4 bytes, and interpret them as a 32-bit unsigned big-endian integer. */ -uint32_t inline ReadBE32(const unsigned char *data) { - return ((uint32_t)data[0] << 24 | (uint32_t)data[1] << 16 | (uint32_t)data[2] << 8 | (uint32_t)data[3]); -} - -/** Write a 32-bit unsigned big-endian integer. */ -void inline WriteBE32(unsigned char *data, uint32_t x) { - data[0] = x >> 24; - data[1] = x >> 16; - data[2] = x >> 8; - data[3] = x; -} - -/** Read 8 bytes, and interpret them as a 64-bit unsigned big-endian integer. */ -uint64_t inline ReadBE64(const unsigned char *data) { - return ((uint64_t)data[0] << 56 | (uint64_t)data[1] << 48 | (uint64_t)data[2] << 40 | (uint64_t)data[3] << 32 | - (uint64_t)data[4] << 24 | (uint64_t)data[5] << 16 | (uint64_t)data[6] << 8 | (uint64_t)data[7]); -} - -/** Write a 64-bit unsigned big-endian integer. */ -void inline WriteBE64(unsigned char *data, uint64_t x) { - data[0] = x >> 56; - data[1] = x >> 48; - data[2] = x >> 40; - data[3] = x >> 32; - data[4] = x >> 24; - data[5] = x >> 16; - data[6] = x >> 8; - data[7] = x; -} - /// Internal SHA-256 implementation. namespace sha256 { From 3820e01eb9ad0e502e92ebc44cb4623cf4f3d4c4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 31 May 2014 22:01:42 +0200 Subject: [PATCH 207/336] Extend and move all crypto tests to crypto_tests.cpp --- src/Makefile.test.include | 3 +- src/test/crypto_tests.cpp | 202 ++++++++++++++++++++++++++++++++++++++ src/test/sha1_tests.cpp | 27 ----- src/test/sha2_tests.cpp | 157 ----------------------------- 4 files changed, 203 insertions(+), 186 deletions(-) create mode 100644 src/test/crypto_tests.cpp delete mode 100644 src/test/sha1_tests.cpp delete mode 100644 src/test/sha2_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 7cf441bd6c..02fb3ba5fe 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -31,6 +31,7 @@ BITCOIN_TESTS =\ test/checkblock_tests.cpp \ test/Checkpoints_tests.cpp \ test/compress_tests.cpp \ + test/crypto_tests.cpp \ test/DoS_tests.cpp \ test/getarg_tests.cpp \ test/hash_tests.cpp \ @@ -45,8 +46,6 @@ BITCOIN_TESTS =\ test/script_P2SH_tests.cpp \ test/script_tests.cpp \ test/serialize_tests.cpp \ - test/sha1_tests.cpp \ - test/sha2_tests.cpp \ test/sigopcount_tests.cpp \ test/test_bitcoin.cpp \ test/transaction_tests.cpp \ diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp new file mode 100644 index 0000000000..d425f082c3 --- /dev/null +++ b/src/test/crypto_tests.cpp @@ -0,0 +1,202 @@ +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/ripemd160.h" +#include "crypto/sha1.h" +#include "crypto/sha2.h" +#include "util.h" + +#include + +#include + +BOOST_AUTO_TEST_SUITE(crypto_tests) + +template +void TestVector(const Hasher &h, const In &in, const Out &out) { + Out hash; + hash.resize(out.size()); + { + // Test that writing the whole input string at once works. + Hasher(h).Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); + BOOST_CHECK(hash == out); + } + for (int i=0; i<32; i++) { + // Test that writing the string broken up in random pieces works. + Hasher hasher(h); + size_t pos = 0; + while (pos < in.size()) { + size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + hasher.Write((unsigned char*)&in[pos], len); + pos += len; + if (pos > 0 && pos + 2 * out.size() > in.size()) { + // Test that writing the rest at once to a copy of a hasher works. + Hasher(hasher).Write((unsigned char*)&in[pos], in.size() - pos).Finalize(&hash[0]); + BOOST_CHECK(hash == out); + } + } + hasher.Finalize(&hash[0]); + BOOST_CHECK(hash == out); + } +} + +void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));} +void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));} +void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));} +void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));} + +void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { + std::vector key = ParseHex(hexkey); + TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); +} + +std::string LongTestString(void) { + std::string ret; + for (int i=0; i<200000; i++) { + ret += (unsigned char)(i); + ret += (unsigned char)(i >> 4); + ret += (unsigned char)(i >> 8); + ret += (unsigned char)(i >> 12); + ret += (unsigned char)(i >> 16); + } + return ret; +} + +const std::string test1 = LongTestString(); + +BOOST_AUTO_TEST_CASE(ripemd160_testvectors) { + TestRIPEMD160("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"); + TestRIPEMD160("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); + TestRIPEMD160("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"); + TestRIPEMD160("secure hash algorithm", "20397528223b6a5f4cbc2808aba0464e645544f9"); + TestRIPEMD160("RIPEMD160 is considered to be safe", "a7d78608c7af8a8e728778e81576870734122b66"); + TestRIPEMD160("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "12a053384a9c0c88e405a06c27dcf49ada62eb2b"); + TestRIPEMD160("For this sample, this 63-byte string will be used as input data", + "de90dbfee14b63fb5abf27c2ad4a82aaa5f27a11"); + TestRIPEMD160("This is exactly 64 bytes long, not counting the terminating byte", + "eda31d51d3a623b81e19eb02e24ff65d27d67b37"); + TestRIPEMD160(std::string(1000000, 'a'), "52783243c1697bdbe16d37f97f68f08325dc1528"); + TestRIPEMD160(test1, "464243587bd146ea835cdf57bdae582f25ec45f1"); +} + +BOOST_AUTO_TEST_CASE(sha1_testvectors) { + TestSHA1("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + TestSHA1("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"); + TestSHA1("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3"); + TestSHA1("secure hash algorithm", "d4d6d2f0ebe317513bbd8d967d89bac5819c2f60"); + TestSHA1("SHA1 is considered to be safe", "f2b6650569ad3a8720348dd6ea6c497dee3a842a"); + TestSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + TestSHA1("For this sample, this 63-byte string will be used as input data", + "4f0ea5cd0585a23d028abdc1a6684e5a8094dc49"); + TestSHA1("This is exactly 64 bytes long, not counting the terminating byte", + "fb679f23e7d1ce053313e66e127ab1b444397057"); + TestSHA1(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); + TestSHA1(test1, "b7755760681cbfd971451668f32af5774f4656b5"); +} + +BOOST_AUTO_TEST_CASE(sha256_testvectors) { + TestSHA256("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + TestSHA256("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + TestSHA256("message digest", + "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); + TestSHA256("secure hash algorithm", + "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d"); + TestSHA256("SHA256 is considered to be safe", + "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630"); + TestSHA256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + TestSHA256("For this sample, this 63-byte string will be used as input data", + "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"); + TestSHA256("This is exactly 64 bytes long, not counting the terminating byte", + "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"); + TestSHA256("As Bitcoin relies on 80 byte header hashes, we want to have an example for that.", + "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743"); + TestSHA256(std::string(1000000, 'a'), + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); + TestSHA256(test1, "a316d55510b49662420f49d145d42fb83f31ef8dc016aa4e32df049991a91e26"); +} + +BOOST_AUTO_TEST_CASE(sha512_testvectors) { + TestSHA512("", + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" + "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + TestSHA512("abc", + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + TestSHA512("message digest", + "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f33" + "09e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"); + TestSHA512("secure hash algorithm", + "7746d91f3de30c68cec0dd693120a7e8b04d8073cb699bdce1a3f64127bca7a3" + "d5db502e814bb63c063a7a5043b2df87c61133395f4ad1edca7fcf4b30c3236e"); + TestSHA512("SHA512 is considered to be safe", + "099e6468d889e1c79092a89ae925a9499b5408e01b66cb5b0a3bd0dfa51a9964" + "6b4a3901caab1318189f74cd8cf2e941829012f2449df52067d3dd5b978456c2"); + TestSHA512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335" + "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"); + TestSHA512("For this sample, this 63-byte string will be used as input data", + "b3de4afbc516d2478fe9b518d063bda6c8dd65fc38402dd81d1eb7364e72fb6e" + "6663cf6d2771c8f5a6da09601712fb3d2a36c6ffea3e28b0818b05b0a8660766"); + TestSHA512("This is exactly 64 bytes long, not counting the terminating byte", + "70aefeaa0e7ac4f8fe17532d7185a289bee3b428d950c14fa8b713ca09814a38" + "7d245870e007a80ad97c369d193e41701aa07f3221d15f0e65a1ff970cedf030"); + TestSHA512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" + "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"); + TestSHA512(std::string(1000000, 'a'), + "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" + "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); + TestSHA512(test1, + "40cac46c147e6131c5193dd5f34e9d8bb4951395f27b08c558c65ff4ba2de594" + "37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc"); +} + +BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { + // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 + TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4869205468657265", + "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde" + "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"); + TestHMACSHA512("4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554" + "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"); + TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "dddddddddddddddddddddddddddddddddddd", + "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39" + "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"); + TestHMACSHA512("0102030405060708090a0b0c0d0e0f10111213141516171819", + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", + "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db" + "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"); + TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaa", + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + "65204b6579202d2048617368204b6579204669727374", + "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352" + "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"); + TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaa", + "5468697320697320612074657374207573696e672061206c6172676572207468" + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + "647320746f20626520686173686564206265666f7265206265696e6720757365" + "642062792074686520484d414320616c676f726974686d2e", + "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" + "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sha1_tests.cpp b/src/test/sha1_tests.cpp deleted file mode 100644 index 88f2da0bbb..0000000000 --- a/src/test/sha1_tests.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2014 The Bitcoin Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "crypto/sha1.h" -#include "util.h" - -#include - -#include - -BOOST_AUTO_TEST_SUITE(sha1_tests) - -void SHA1TestVector(const std::string &in, const std::string &out) { - std::vector hash; - hash.resize(20); - CSHA1().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); - BOOST_CHECK_EQUAL(HexStr(hash), out); -} - -BOOST_AUTO_TEST_CASE(sha1_testvectors) { - SHA1TestVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"); - SHA1TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); - SHA1TestVector(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/sha2_tests.cpp b/src/test/sha2_tests.cpp deleted file mode 100644 index 1e48c973cf..0000000000 --- a/src/test/sha2_tests.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2014 The Bitcoin Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "crypto/sha2.h" -#include "util.h" - -#include - -#include - -BOOST_AUTO_TEST_SUITE(sha2_tests) - -void SHA256TestVector(const std::string &in, const std::string &out) { - std::vector hash; - hash.resize(32); - CSHA256().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); - BOOST_CHECK_EQUAL(HexStr(hash), out); -} - -void SHA512TestVector(const std::string &in, const std::string &out) { - std::vector hash; - hash.resize(64); - CSHA512().Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); - BOOST_CHECK_EQUAL(HexStr(hash), out); -} - -BOOST_AUTO_TEST_CASE(sha256_testvectors) { - SHA256TestVector("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - SHA256TestVector("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); - SHA256TestVector("message digest", "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); - SHA256TestVector("secure hash algorithm", "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d"); - SHA256TestVector("SHA256 is considered to be safe", "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630"); - SHA256TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); - SHA256TestVector("For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"); - SHA256TestVector("This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"); - SHA256TestVector("As Bitcoin relies on 80 byte header hashes, we want to have an example for that.", "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743"); -} - -BOOST_AUTO_TEST_CASE(sha512_testvectors) { - SHA512TestVector("abc", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); - SHA512TestVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"); - SHA512TestVector("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"); - SHA512TestVector(std::string(1000000, 'a'), "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); - SHA512TestVector("", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); -} - -typedef struct { - const char *pszKey; - const char *pszData; - const char *pszMAC; -} testvec_t; - -// test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 -static const testvec_t vtest[] = { - { - "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b" - "0b0b0b0b", - "4869205468657265", - "87aa7cdea5ef619d4ff0b4241a1d6cb0" - "2379f4e2ce4ec2787ad0b30545e17cde" - "daa833b7d6b8a702038b274eaea3f4e4" - "be9d914eeb61f1702e696c203a126854" - }, - { - "4a656665", - "7768617420646f2079612077616e7420" - "666f72206e6f7468696e673f", - "164b7a7bfcf819e2e395fbe73b56e0a3" - "87bd64222e831fd610270cd7ea250554" - "9758bf75c05a994a6d034f65f8f0e6fd" - "caeab1a34d4a6b4b636e070a38bce737" - }, - { - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaa", - "dddddddddddddddddddddddddddddddd" - "dddddddddddddddddddddddddddddddd" - "dddddddddddddddddddddddddddddddd" - "dddd", - "fa73b0089d56a284efb0f0756c890be9" - "b1b5dbdd8ee81a3655f83e33b2279d39" - "bf3e848279a722c806b485a47e67c807" - "b946a337bee8942674278859e13292fb" - }, - { - "0102030405060708090a0b0c0d0e0f10" - "111213141516171819", - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" - "cdcd", - "b0ba465637458c6990e5a8c5f61d4af7" - "e576d97ff94b872de76f8050361ee3db" - "a91ca5c11aa25eb4d679275cc5788063" - "a5f19741120c4f2de2adebeb10a298dd" - }, - { - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaa", - "54657374205573696e67204c61726765" - "72205468616e20426c6f636b2d53697a" - "65204b6579202d2048617368204b6579" - "204669727374", - "80b24263c7c1a3ebb71493c1dd7be8b4" - "9b46d1f41b4aeec1121b013783f8f352" - "6b56d037e05f2598bd0fd2215d6a1e52" - "95e64f73f63f0aec8b915a985d786598" - }, - { - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaa", - "54686973206973206120746573742075" - "73696e672061206c6172676572207468" - "616e20626c6f636b2d73697a65206b65" - "7920616e642061206c61726765722074" - "68616e20626c6f636b2d73697a652064" - "6174612e20546865206b6579206e6565" - "647320746f2062652068617368656420" - "6265666f7265206265696e6720757365" - "642062792074686520484d414320616c" - "676f726974686d2e", - "e37b6a775dc87dbaa4dfa9f96e5e3ffd" - "debd71f8867289865df5a32d20cdc944" - "b6022cac3c4982b10d5eeb55c3e4de15" - "134676fb6de0446065c97440fa8c6a58" - } -}; - -BOOST_AUTO_TEST_CASE(hmacsha512_testvectors) -{ - for (unsigned int n=0; n vchKey = ParseHex(vtest[n].pszKey); - std::vector vchData = ParseHex(vtest[n].pszData); - std::vector vchMAC = ParseHex(vtest[n].pszMAC); - unsigned char vchTemp[64]; - CHMAC_SHA512(&vchKey[0], vchKey.size()).Write(&vchData[0], vchData.size()).Finalize(&vchTemp[0]); - BOOST_CHECK(memcmp(&vchTemp[0], &vchMAC[0], 64) == 0); - } -} - -BOOST_AUTO_TEST_SUITE_END() From 54372482a8ffa363f5dd9ff1c80141a168109ed5 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 9 Jun 2014 14:58:30 -0400 Subject: [PATCH 208/336] build: move bitcoin-config.h to its own directory This allows us to include its path without making other header includes valid. --- configure.ac | 2 +- src/Makefile.am | 4 +++- src/config/.empty | 0 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/config/.empty diff --git a/configure.ac b/configure.ac index 81a32f9fb7..0caf653cad 100644 --- a/configure.ac +++ b/configure.ac @@ -111,7 +111,7 @@ AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[spec AC_CONFIG_SRCDIR([src]) -AC_CONFIG_HEADERS([src/bitcoin-config.h]) +AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) dnl Checks for programs. AC_PROG_CXX diff --git a/src/Makefile.am b/src/Makefile.am index 01655b7011..c666fb7662 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,7 +17,8 @@ $(LIBLEVELDB) $(LIBMEMENV): OPT="$(CXXFLAGS) $(CPPFLAGS)" endif -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BITCOIN_CONFIG_INCLUDES) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) noinst_LIBRARIES = \ libbitcoin_server.a \ @@ -219,6 +220,7 @@ EXTRA_DIST = leveldb clean-local: -$(MAKE) -C leveldb clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno + -rm -f config.h .rc.o: @test -f $(WINDRES) diff --git a/src/config/.empty b/src/config/.empty new file mode 100644 index 0000000000..e69de29bb2 From f2647cc0e997198d7ac7f3fe3d843e941b57dda8 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 9 Jun 2014 15:05:28 -0400 Subject: [PATCH 209/336] crypto: explicitly check for byte read/write functions Don't depend on hard-coded platform lists --- configure.ac | 7 +++- src/crypto/common.h | 79 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 0caf653cad..811ef1dd80 100644 --- a/configure.ac +++ b/configure.ac @@ -368,7 +368,12 @@ if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi -AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h]) +AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h]) + +AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,, + [#if HAVE_ENDIAN_H + #include + #endif]) dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) diff --git a/src/crypto/common.h b/src/crypto/common.h index e1bcd3ae11..8f675a16c5 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -5,42 +5,89 @@ #ifndef BITCOIN_CRYPTO_COMMON_H #define BITCOIN_CRYPTO_COMMON_H +#if defined(HAVE_CONFIG_H) +#include "bitcoin-config.h" +#endif #include +#if defined(HAVE_ENDIAN_H) +#include +#endif -#ifdef WIN32 -uint32_t static inline ReadLE32(const unsigned char *ptr) { return *((uint32_t*)ptr); } -uint64_t static inline ReadLE64(const unsigned char *ptr) { return *((uint64_t*)ptr); } +uint32_t static inline ReadLE32(const unsigned char *ptr) { +#if HAVE_DECL_LE32TOH == 1 + return le32toh(*((uint32_t*)ptr)); +#elif !defined(WORDS_BIGENDIAN) + return *((uint32_t*)ptr); +#else + return ((uint32_t)ptr[3] << 24 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[0]); +#endif +} -void static inline WriteLE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = x; } -void static inline WriteLE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = x; } +uint64_t static inline ReadLE64(const unsigned char *ptr) { + +#if HAVE_DECL_LE64TOH == 1 + return le64toh(*((uint64_t*)ptr)); +#elif !defined(WORDS_BIGENDIAN) + return *((uint64_t*)ptr); +#else + return ((uint64_t)ptr[7] << 56 | (uint64_t)ptr[6] << 48 | (uint64_t)ptr[5] << 40 | (uint64_t)ptr[4] << 32 | + (uint64_t)ptr[3] << 24 | (uint64_t)ptr[2] << 16 | (uint64_t)ptr[1] << 8 | (uint64_t)ptr[0]); +#endif +} + +void static inline WriteLE32(unsigned char *ptr, uint32_t x) { +#if HAVE_DECL_HTOLE32 == 1 + *((uint32_t*)ptr) = htole32(x); +#elif !defined(WORDS_BIGENDIAN) + *((uint32_t*)ptr) = x; +#else + ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x; +#endif +} + +void static inline WriteLE64(unsigned char *ptr, uint64_t x) { +#if HAVE_DECL_HTOLE64 == 1 + *((uint64_t*)ptr) = htole64(x); +#elif !defined(WORDS_BIGENDIAN) + *((uint64_t*)ptr) = x; +#else + ptr[7] = x >> 56; ptr[6] = x >> 48; ptr[5] = x >> 40; ptr[4] = x >> 32; + ptr[3] = x >> 24; ptr[2] = x >> 16; ptr[1] = x >> 8; ptr[0] = x; +#endif +} uint32_t static inline ReadBE32(const unsigned char *ptr) { +#if HAVE_DECL_BE32TOH == 1 + return be32toh(*((uint32_t*)ptr)); +#else return ((uint32_t)ptr[0] << 24 | (uint32_t)ptr[1] << 16 | (uint32_t)ptr[2] << 8 | (uint32_t)ptr[3]); +#endif } uint64_t static inline ReadBE64(const unsigned char *ptr) { +#if HAVE_DECL_BE64TOH == 1 + return be64toh(*((uint64_t*)ptr)); +#else return ((uint64_t)ptr[0] << 56 | (uint64_t)ptr[1] << 48 | (uint64_t)ptr[2] << 40 | (uint64_t)ptr[3] << 32 | (uint64_t)ptr[4] << 24 | (uint64_t)ptr[5] << 16 | (uint64_t)ptr[6] << 8 | (uint64_t)ptr[7]); +#endif } void static inline WriteBE32(unsigned char *ptr, uint32_t x) { +#if HAVE_DECL_HTOBE32 == 1 + *((uint32_t*)ptr) = htobe32(x); +#else ptr[0] = x >> 24; ptr[1] = x >> 16; ptr[2] = x >> 8; ptr[3] = x; +#endif } void static inline WriteBE64(unsigned char *ptr, uint64_t x) { +#if HAVE_DECL_HTOBE64 == 1 + *((uint64_t*)ptr) = htobe64(x); +#else ptr[0] = x >> 56; ptr[1] = x >> 48; ptr[2] = x >> 40; ptr[3] = x >> 32; ptr[4] = x >> 24; ptr[5] = x >> 16; ptr[6] = x >> 8; ptr[7] = x; +#endif } -#else -# include -uint32_t static inline ReadLE32(const unsigned char *ptr) { return le32toh(*((uint32_t*)ptr)); } -uint64_t static inline ReadLE64(const unsigned char *ptr) { return le64toh(*((uint64_t*)ptr)); } -void static inline WriteLE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = htole32(x); } -void static inline WriteLE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = htole64(x); } -uint32_t static inline ReadBE32(const unsigned char *ptr) { return be32toh(*((uint32_t*)ptr)); } -uint64_t static inline ReadBE64(const unsigned char *ptr) { return be64toh(*((uint64_t*)ptr)); } -void static inline WriteBE32(unsigned char *ptr, uint32_t x) { *((uint32_t*)ptr) = htobe32(x); } -void static inline WriteBE64(unsigned char *ptr, uint64_t x) { *((uint64_t*)ptr) = htobe64(x); } -#endif #endif From 4791b99e2dea0593775a8c75f62c8406d340191e Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 9 Jun 2014 15:17:27 -0400 Subject: [PATCH 210/336] crypto: create a separate lib for crypto functions This lib has no dependencies on other bitcoin functionality. Attempting to use bitcoin headers will result in a failure to compile. --- src/Makefile.am | 23 +++++++++++++++-------- src/Makefile.qt.include | 2 +- src/Makefile.qttest.include | 2 +- src/Makefile.test.include | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c666fb7662..3948ca0780 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,8 @@ BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BITCOIN_CONFIG_INCLUDES) $(BO noinst_LIBRARIES = \ libbitcoin_server.a \ libbitcoin_common.a \ - libbitcoin_cli.a + libbitcoin_cli.a \ + crypto/libbitcoin_crypto.a if ENABLE_WALLET BITCOIN_INCLUDES += $(BDB_CPPFLAGS) noinst_LIBRARIES += libbitcoin_wallet.a @@ -76,10 +77,6 @@ BITCOIN_CORE_H = \ rpcserver.h \ script.h \ serialize.h \ - crypto/common.h \ - crypto/sha2.h \ - crypto/sha1.h \ - crypto/ripemd160.h \ sync.h \ threadsafety.h \ tinyformat.h \ @@ -145,6 +142,16 @@ libbitcoin_wallet_a_SOURCES = \ walletdb.cpp \ $(BITCOIN_CORE_H) +crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES) +crypto_libbitcoin_crypto_a_SOURCES = \ + crypto/sha1.cpp \ + crypto/sha2.cpp \ + crypto/ripemd160.cpp \ + crypto/common.h \ + crypto/sha2.h \ + crypto/sha1.h \ + crypto/ripemd160.h + libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ base58.cpp \ @@ -157,9 +164,6 @@ libbitcoin_common_a_SOURCES = \ protocol.cpp \ rpcprotocol.cpp \ script.cpp \ - crypto/sha1.cpp \ - crypto/sha2.cpp \ - crypto/ripemd160.cpp \ sync.cpp \ util.cpp \ version.cpp \ @@ -183,6 +187,7 @@ nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h bitcoind_LDADD = \ libbitcoin_server.a \ libbitcoin_common.a \ + crypto/libbitcoin_crypto.a \ $(LIBLEVELDB) \ $(LIBMEMENV) if ENABLE_WALLET @@ -202,6 +207,7 @@ bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES) bitcoin_cli_LDADD = \ libbitcoin_cli.a \ libbitcoin_common.a \ + crypto/libbitcoin_crypto.a \ $(BOOST_LIBS) bitcoin_cli_SOURCES = bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) @@ -238,6 +244,7 @@ LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CLI=libbitcoin_cli.a +LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOINQT=qt/libbitcoinqt.a if ENABLE_TESTS diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 647434e1ef..091138dc38 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -355,7 +355,7 @@ qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif -qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index e0b49d0240..0aa31a406d 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -30,7 +30,7 @@ qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif -qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \ +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 02fb3ba5fe..64f997f4b5 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -63,7 +63,7 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) -test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \ +test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) From a0495bb68c6eff9c732d458bacab10490d6452b4 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 12 Jun 2014 13:34:29 +0200 Subject: [PATCH 211/336] Add ::OUTPUT_SIZE --- src/crypto/ripemd160.cpp | 2 +- src/crypto/ripemd160.h | 4 +++- src/crypto/sha1.cpp | 2 +- src/crypto/sha1.h | 4 +++- src/crypto/sha2.cpp | 6 +++--- src/crypto/sha2.h | 12 +++++++++--- src/hash.h | 16 ++++++++++------ src/test/crypto_tests.cpp | 1 + 8 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp index c5e6e2d696..24bd318d43 100644 --- a/src/crypto/ripemd160.cpp +++ b/src/crypto/ripemd160.cpp @@ -184,7 +184,7 @@ CRIPEMD160& CRIPEMD160::Write(const unsigned char *data, size_t len) { return *this; } -void CRIPEMD160::Finalize(unsigned char *hash) { +void CRIPEMD160::Finalize(unsigned char hash[OUTPUT_SIZE]) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteLE64(sizedesc, bytes << 3); diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h index cab1d0bb46..44bd4879a5 100644 --- a/src/crypto/ripemd160.h +++ b/src/crypto/ripemd160.h @@ -16,9 +16,11 @@ private: size_t bytes; public: + static const size_t OUTPUT_SIZE = 20; + CRIPEMD160(); CRIPEMD160& Write(const unsigned char *data, size_t len); - void Finalize(unsigned char *hash); + void Finalize(unsigned char hash[OUTPUT_SIZE]); CRIPEMD160& Reset(); }; diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp index e0f32b7d1d..304401a50f 100644 --- a/src/crypto/sha1.cpp +++ b/src/crypto/sha1.cpp @@ -172,7 +172,7 @@ CSHA1& CSHA1::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA1::Finalize(unsigned char *hash) { +void CSHA1::Finalize(unsigned char hash[OUTPUT_SIZE]) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteBE64(sizedesc, bytes << 3); diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h index 6efde78a5b..b16f2c88ce 100644 --- a/src/crypto/sha1.h +++ b/src/crypto/sha1.h @@ -16,9 +16,11 @@ private: size_t bytes; public: + static const size_t OUTPUT_SIZE = 20; + CSHA1(); CSHA1& Write(const unsigned char *data, size_t len); - void Finalize(unsigned char *hash); + void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA1& Reset(); }; diff --git a/src/crypto/sha2.cpp b/src/crypto/sha2.cpp index 77f35f38d8..99a251cb12 100644 --- a/src/crypto/sha2.cpp +++ b/src/crypto/sha2.cpp @@ -295,7 +295,7 @@ CSHA256& CSHA256::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA256::Finalize(unsigned char *hash) { +void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; WriteBE64(sizedesc, bytes << 3); @@ -348,7 +348,7 @@ CSHA512& CSHA512::Write(const unsigned char *data, size_t len) { return *this; } -void CSHA512::Finalize(unsigned char *hash) { +void CSHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) { static const unsigned char pad[128] = {0x80}; unsigned char sizedesc[16] = {0x00}; WriteBE64(sizedesc+8, bytes << 3); @@ -391,7 +391,7 @@ CHMAC_SHA512::CHMAC_SHA512(const unsigned char *key, size_t keylen) { inner.Write(rkey, 128); } -void CHMAC_SHA512::Finalize(unsigned char *hash) { +void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) { unsigned char temp[64]; inner.Finalize(temp); outer.Write(temp, 64).Finalize(hash); diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h index 001bfc647c..088d5e194c 100644 --- a/src/crypto/sha2.h +++ b/src/crypto/sha2.h @@ -16,9 +16,11 @@ private: size_t bytes; public: + static const size_t OUTPUT_SIZE = 32; + CSHA256(); CSHA256& Write(const unsigned char *data, size_t len); - void Finalize(unsigned char *hash); + void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA256& Reset(); }; @@ -30,9 +32,11 @@ private: size_t bytes; public: + static const size_t OUTPUT_SIZE = 64; + CSHA512(); CSHA512& Write(const unsigned char *data, size_t len); - void Finalize(unsigned char *hash); + void Finalize(unsigned char hash[OUTPUT_SIZE]); CSHA512& Reset(); }; @@ -43,12 +47,14 @@ private: CSHA512 inner; public: + static const size_t OUTPUT_SIZE = 64; + CHMAC_SHA512(const unsigned char *key, size_t keylen); CHMAC_SHA512& Write(const unsigned char *data, size_t len) { inner.Write(data, len); return *this; } - void Finalize(unsigned char *hash); + void Finalize(unsigned char hash[OUTPUT_SIZE]); }; #endif diff --git a/src/hash.h b/src/hash.h index 39d42eefe2..f2a0ebfe1f 100644 --- a/src/hash.h +++ b/src/hash.h @@ -19,10 +19,12 @@ class CHash256 { private: CSHA256 sha; public: - void Finalize(unsigned char *hash) { - unsigned char buf[32]; + static const size_t OUTPUT_SIZE = CSHA256::OUTPUT_SIZE; + + void Finalize(unsigned char hash[OUTPUT_SIZE]) { + unsigned char buf[sha.OUTPUT_SIZE]; sha.Finalize(buf); - sha.Reset().Write(buf, 32).Finalize(hash); + sha.Reset().Write(buf, sha.OUTPUT_SIZE).Finalize(hash); } CHash256& Write(const unsigned char *data, size_t len) { @@ -41,10 +43,12 @@ class CHash160 { private: CSHA256 sha; public: - void Finalize(unsigned char *hash) { - unsigned char buf[32]; + static const size_t OUTPUT_SIZE = CRIPEMD160::OUTPUT_SIZE; + + void Finalize(unsigned char hash[OUTPUT_SIZE]) { + unsigned char buf[sha.OUTPUT_SIZE]; sha.Finalize(buf); - CRIPEMD160().Write(buf, 32).Finalize(hash); + CRIPEMD160().Write(buf, sha.OUTPUT_SIZE).Finalize(hash); } CHash160& Write(const unsigned char *data, size_t len) { diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index d425f082c3..7bd98fa381 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -16,6 +16,7 @@ BOOST_AUTO_TEST_SUITE(crypto_tests) template void TestVector(const Hasher &h, const In &in, const Out &out) { Out hash; + BOOST_CHECK(out.size() == h.OUTPUT_SIZE); hash.resize(out.size()); { // Test that writing the whole input string at once works. From 040c2d3f5748fc41f80207d771a0a8c10ec79ba9 Mon Sep 17 00:00:00 2001 From: Drak Date: Sat, 21 Jun 2014 21:57:50 +0100 Subject: [PATCH 212/336] Fix formatting --- doc/release-process.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 5b96e53753..9cdc43b9be 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -50,8 +50,7 @@ Release Process wget 'ftp://ftp.simplesystems.org/pub/png/src/history/libpng16/libpng-1.6.8.tar.gz' wget 'https://fukuchi.org/works/qrencode/qrencode-3.4.3.tar.bz2' wget 'https://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2' - wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O \ - boost-mingw-gas-cross-compile-2013-03-03.patch + wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O boost-mingw-gas-cross-compile-2013-03-03.patch wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.0/single/qt-everywhere-opensource-src-5.2.0.tar.gz' wget 'https://download.qt-project.org/archive/qt/4.6/qt-everywhere-opensource-src-4.6.4.tar.gz' wget 'https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2' @@ -61,10 +60,8 @@ Release Process wget 'http://www.opensource.apple.com/tarballs/ld64/ld64-127.2.tar.gz' wget 'http://cdrkit.org/releases/cdrkit-1.1.11.tar.gz' wget 'https://github.com/theuni/libdmg-hfsplus/archive/libdmg-hfsplus-v0.1.tar.gz' - wget 'http://llvm.org/releases/3.2/clang+llvm-3.2-x86-linux-ubuntu-12.04.tar.gz' -O \ - clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz - wget 'https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff' -O \ - cdrkit-deterministic.patch + wget 'http://llvm.org/releases/3.2/clang+llvm-3.2-x86-linux-ubuntu-12.04.tar.gz' -O clang-llvm-3.2-x86-linux-ubuntu-12.04.tar.gz + wget 'https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff' -O cdrkit-deterministic.patch cd .. ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-linux.yml mv build/out/boost-*.zip inputs/ From 4949004d68dc08382df2c34ae519c1b1cfd60f1a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 7 Jun 2014 13:53:27 +0200 Subject: [PATCH 213/336] Add CMutableTransaction and make CTransaction immutable. In addition, introduce a cached hash inside CTransaction, to prevent recalculating it over and over again. --- src/chainparams.cpp | 2 +- src/core.cpp | 25 ++++++++- src/core.h | 93 ++++++++++++++++++++++------------ src/miner.cpp | 18 ++++--- src/qt/coincontroldialog.cpp | 2 +- src/rpcrawtransaction.cpp | 10 ++-- src/script.cpp | 6 +-- src/script.h | 5 +- src/test/DoS_tests.cpp | 12 ++--- src/test/accounting_tests.cpp | 12 ++++- src/test/miner_tests.cpp | 12 +++-- src/test/multisig_tests.cpp | 8 +-- src/test/pmt_tests.cpp | 4 +- src/test/script_P2SH_tests.cpp | 18 +++---- src/test/script_tests.cpp | 12 ++--- src/test/sighash_tests.cpp | 6 +-- src/test/transaction_tests.cpp | 14 ++--- src/test/wallet_tests.cpp | 10 ++-- src/wallet.cpp | 18 ++++--- 19 files changed, 181 insertions(+), 106 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 31eac62d48..afbae6fc57 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -127,7 +127,7 @@ public: // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) // vMerkleTree: 4a5e1e const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - CTransaction txNew; + CMutableTransaction txNew; txNew.vin.resize(1); txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); diff --git a/src/core.cpp b/src/core.cpp index 6039986e6c..6c5ee1c0f8 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -91,11 +91,34 @@ std::string CFeeRate::ToString() const return result; } -uint256 CTransaction::GetHash() const +CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {} +CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {} + +uint256 CMutableTransaction::GetHash() const { return SerializeHash(*this); } +void CTransaction::UpdateHash() const +{ + *const_cast(&hash) = SerializeHash(*this); +} + +CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { } + +CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) { + UpdateHash(); +} + +CTransaction& CTransaction::operator=(const CTransaction &tx) { + *const_cast(&nVersion) = tx.nVersion; + *const_cast*>(&vin) = tx.vin; + *const_cast*>(&vout) = tx.vout; + *const_cast(&nLockTime) = tx.nLockTime; + *const_cast(&hash) = tx.hash; + return *this; +} + int64_t CTransaction::GetValueOut() const { int64_t nValueOut = 0; diff --git a/src/core.h b/src/core.h index 0e59129349..1a20145ccf 100644 --- a/src/core.h +++ b/src/core.h @@ -203,49 +203,59 @@ public: }; +struct CMutableTransaction; + /** The basic transaction that is broadcasted on the network and contained in * blocks. A transaction can contain multiple inputs and outputs. */ class CTransaction { +private: + /** Memory only. */ + const uint256 hash; + void UpdateHash() const; + public: static CFeeRate minTxFee; static CFeeRate minRelayTxFee; static const int CURRENT_VERSION=1; - int nVersion; - std::vector vin; - std::vector vout; - unsigned int nLockTime; - CTransaction() - { - SetNull(); - } + // The local variables are made const to prevent unintended modification + // without updating the cached hash value. However, CTransaction is not + // actually immutable; deserialization and assignment are implemented, + // and bypass the constness. This is safe, as they update the entire + // structure, including the hash. + const int nVersion; + const std::vector vin; + const std::vector vout; + const unsigned int nLockTime; - IMPLEMENT_SERIALIZE - ( - READWRITE(this->nVersion); + /** Construct a CTransaction that qualifies as IsNull() */ + CTransaction(); + + /** Convert a CMutableTransaction into a CTransaction. */ + CTransaction(const CMutableTransaction &tx); + + CTransaction& operator=(const CTransaction& tx); + + IMPLEMENT_SERIALIZE( + READWRITE(*const_cast(&this->nVersion)); nVersion = this->nVersion; - READWRITE(vin); - READWRITE(vout); - READWRITE(nLockTime); + READWRITE(*const_cast*>(&vin)); + READWRITE(*const_cast*>(&vout)); + READWRITE(*const_cast(&nLockTime)); + if (fRead) + UpdateHash(); ) - void SetNull() - { - nVersion = CTransaction::CURRENT_VERSION; - vin.clear(); - vout.clear(); - nLockTime = 0; + bool IsNull() const { + return vin.empty() && vout.empty(); } - bool IsNull() const - { - return (vin.empty() && vout.empty()); + const uint256& GetHash() const { + return hash; } - uint256 GetHash() const; - // Return sum of txouts. int64_t GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because @@ -261,22 +271,43 @@ public: friend bool operator==(const CTransaction& a, const CTransaction& b) { - return (a.nVersion == b.nVersion && - a.vin == b.vin && - a.vout == b.vout && - a.nLockTime == b.nLockTime); + return a.hash == b.hash; } friend bool operator!=(const CTransaction& a, const CTransaction& b) { - return !(a == b); + return a.hash != b.hash; } - std::string ToString() const; void print() const; }; +/** A mutable version of CTransaction. */ +struct CMutableTransaction +{ + int nVersion; + std::vector vin; + std::vector vout; + unsigned int nLockTime; + + CMutableTransaction(); + CMutableTransaction(const CTransaction& tx); + + IMPLEMENT_SERIALIZE( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(vin); + READWRITE(vout); + READWRITE(nLockTime); + ) + + /** Compute the hash of this CMutableTransaction. This is computed on the + * fly, as opposed to GetHash() in CTransaction, which uses a cached result. + */ + uint256 GetHash() const; +}; + /** wrapper for CTxOut that provides a more compact serialization */ class CTxOutCompressor { diff --git a/src/miner.cpp b/src/miner.cpp index 7efca7cfff..37cdc7d840 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -86,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CBlock *pblock = &pblocktemplate->block; // pointer for convenience // Create coinbase tx - CTransaction txNew; + CMutableTransaction txNew; txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); txNew.vout.resize(1); txNew.vout[0].scriptPubKey = scriptPubKeyIn; - // Add our coinbase tx as first transaction - pblock->vtx.push_back(txNew); + // Add dummy coinbase tx as first transaction + pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end @@ -294,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) nLastBlockSize = nBlockSize; LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize); - pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees); + // Compute final coinbase transaction. + txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees); + txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0; + pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; // Fill in header @@ -302,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) UpdateTime(*pblock, pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); pblock->nNonce = 0; - pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0; pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); CBlockIndex indexDummy(*pblock); @@ -328,9 +330,11 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& } ++nExtraNonce; unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 - pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; - assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100); + CMutableTransaction txCoinbase(pblock->vtx[0]); + txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; + assert(txCoinbase.vin[0].scriptSig.size() <= 100); + pblock->vtx[0] = txCoinbase; pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 42d6da7d37..52bdf96731 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -440,7 +440,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // nPayAmount qint64 nPayAmount = 0; bool fDust = false; - CTransaction txDummy; + CMutableTransaction txDummy; foreach(const qint64 &amount, CoinControlDialog::payAmounts) { nPayAmount += amount; diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index dee7daeb2a..1b5d494beb 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -349,7 +349,7 @@ Value createrawtransaction(const Array& params, bool fHelp) Array inputs = params[0].get_array(); Object sendTo = params[1].get_obj(); - CTransaction rawTx; + CMutableTransaction rawTx; BOOST_FOREACH(const Value& input, inputs) { @@ -554,11 +554,11 @@ Value signrawtransaction(const Array& params, bool fHelp) vector txData(ParseHexV(params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); - vector txVariants; + vector txVariants; while (!ssData.empty()) { try { - CTransaction tx; + CMutableTransaction tx; ssData >> tx; txVariants.push_back(tx); } @@ -572,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp) // mergedTx will end up with all the signatures; it // starts as a clone of the rawtx: - CTransaction mergedTx(txVariants[0]); + CMutableTransaction mergedTx(txVariants[0]); bool fComplete = true; // Fetch previous transactions (inputs): @@ -713,7 +713,7 @@ Value signrawtransaction(const Array& params, bool fHelp) SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) + BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } diff --git a/src/script.cpp b/src/script.cpp index b383a00a6e..c83d26885a 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1636,7 +1636,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C } -bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType) +bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) { assert(nIn < txTo.vin.size()); CTxIn& txin = txTo.vin[nIn]; @@ -1671,7 +1671,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0); } -bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType) +bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) { assert(nIn < txTo.vin.size()); CTxIn& txin = txTo.vin[nIn]; @@ -1689,7 +1689,7 @@ static CScript PushAll(const vector& values) return result; } -static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, +static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn, const vector& vSolutions, vector& sigs1, vector& sigs2) { diff --git a/src/script.h b/src/script.h index a282e7dc04..bd6574627a 100644 --- a/src/script.h +++ b/src/script.h @@ -20,6 +20,7 @@ class CCoins; class CKeyStore; class CTransaction; +class CMutableTransaction; static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes @@ -805,8 +806,8 @@ bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); -bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); -bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); +bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL); bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType); // Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders, diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index fb06fb3435..3a45844411 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) // 50 orphan transactions: for (int i = 0; i < 50; i++) { - CTransaction tx; + CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; tx.vin[0].prevout.hash = GetRandHash(); @@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) { CTransaction txPrev = RandomOrphan(); - CTransaction tx; + CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; tx.vin[0].prevout.hash = txPrev.GetHash(); @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) { CTransaction txPrev = RandomOrphan(); - CTransaction tx; + CMutableTransaction tx; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); @@ -242,10 +242,10 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig) // 100 orphan transactions: static const int NPREV=100; - CTransaction orphans[NPREV]; + CMutableTransaction orphans[NPREV]; for (int i = 0; i < NPREV; i++) { - CTransaction& tx = orphans[i]; + CMutableTransaction& tx = orphans[i]; tx.vin.resize(1); tx.vin[0].prevout.n = 0; tx.vin[0].prevout.hash = GetRandHash(); @@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig) } // Create a transaction that depends on orphans: - CTransaction tx; + CMutableTransaction tx; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index e2a75da349..4bee0f6b6e 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -83,13 +83,21 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) wtx.mapValue["comment"] = "y"; - --wtx.nLockTime; // Just to change the hash :) + { + CMutableTransaction tx(wtx); + --tx.nLockTime; // Just to change the hash :) + *static_cast(&wtx) = CTransaction(tx); + } pwalletMain->AddToWallet(wtx); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[1]->nTimeReceived = (unsigned int)1333333336; wtx.mapValue["comment"] = "x"; - --wtx.nLockTime; // Just to change the hash :) + { + CMutableTransaction tx(wtx); + --tx.nLockTime; // Just to change the hash :) + *static_cast(&wtx) = CTransaction(tx); + } pwalletMain->AddToWallet(wtx); vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]); vpwtx[2]->nTimeReceived = (unsigned int)1333333329; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index bff6de41a3..47977cf295 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; CBlockTemplate *pblocktemplate; - CTransaction tx,tx2; + CMutableTransaction tx,tx2; CScript script; uint256 hash; @@ -68,10 +68,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 1; pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; - pblock->vtx[0].vin[0].scriptSig = CScript(); - pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce); - pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height()); - pblock->vtx[0].vout[0].scriptPubKey = CScript(); + CMutableTransaction txCoinbase(pblock->vtx[0]); + txCoinbase.vin[0].scriptSig = CScript(); + txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce); + txCoinbase.vin[0].scriptSig.push_back(chainActive.Height()); + txCoinbase.vout[0].scriptPubKey = CScript(); + pblock->vtx[0] = CTransaction(txCoinbase); if (txFirst.size() < 2) txFirst.push_back(new CTransaction(pblock->vtx[0])); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 3775abd633..452cf084a7 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(multisig_verify) CScript escrow; escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; - CTransaction txFrom; // Funding transaction + CMutableTransaction txFrom; // Funding transaction txFrom.vout.resize(3); txFrom.vout[0].scriptPubKey = a_and_b; txFrom.vout[1].scriptPubKey = a_or_b; txFrom.vout[2].scriptPubKey = escrow; - CTransaction txTo[3]; // Spending transaction + CMutableTransaction txTo[3]; // Spending transaction for (int i = 0; i < 3; i++) { txTo[i].vin.resize(1); @@ -270,13 +270,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign) CScript escrow; escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG; - CTransaction txFrom; // Funding transaction + CMutableTransaction txFrom; // Funding transaction txFrom.vout.resize(3); txFrom.vout[0].scriptPubKey = a_and_b; txFrom.vout[1].scriptPubKey = a_or_b; txFrom.vout[2].scriptPubKey = escrow; - CTransaction txTo[3]; // Spending transaction + CMutableTransaction txTo[3]; // Spending transaction for (int i = 0; i < 3; i++) { txTo[i].vin.resize(1); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 7d7e6681df..9dce4daac6 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -36,9 +36,9 @@ BOOST_AUTO_TEST_CASE(pmt_test1) // build a block with some dummy transactions CBlock block; for (unsigned int j=0; j vch(ch, ch + sizeof(ch) -1); CDataStream stream(vch, SER_DISK, CLIENT_VERSION); - CTransaction tx; + CMutableTransaction tx; stream >> tx; CValidationState state; BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid."); @@ -224,10 +224,10 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests) // paid to a TX_PUBKEY, the second 21 and 22 CENT outputs // paid to a TX_PUBKEYHASH. // -static std::vector +static std::vector SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet) { - std::vector dummyTransactions; + std::vector dummyTransactions; dummyTransactions.resize(2); // Add some keys to the keystore: @@ -261,9 +261,9 @@ BOOST_AUTO_TEST_CASE(test_Get) CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(coinsDummy); - std::vector dummyTransactions = SetupDummyInputs(keystore, coins); + std::vector dummyTransactions = SetupDummyInputs(keystore, coins); - CTransaction t1; + CMutableTransaction t1; t1.vin.resize(3); t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); t1.vin[0].prevout.n = 1; @@ -296,9 +296,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) CBasicKeyStore keystore; CCoinsView coinsDummy; CCoinsViewCache coins(coinsDummy); - std::vector dummyTransactions = SetupDummyInputs(keystore, coins); + std::vector dummyTransactions = SetupDummyInputs(keystore, coins); - CTransaction t; + CMutableTransaction t; t.vin.resize(1); t.vin[0].prevout.hash = dummyTransactions[0].GetHash(); t.vin[0].prevout.n = 1; diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 1993358826..86a83f5163 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -31,16 +31,18 @@ static vector vCoins; static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) { static int nextLockTime = 0; - CTransaction tx; + CMutableTransaction tx; tx.nLockTime = nextLockTime++; // so all transactions get different hashes tx.vout.resize(nInput+1); tx.vout[nInput].nValue = nValue; + if (fIsFromMe) { + // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(), + // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe() + tx.vin.resize(1); + } CWalletTx* wtx = new CWalletTx(&wallet, tx); if (fIsFromMe) { - // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(), - // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe() - wtx->vin.resize(1); wtx->fDebitCached = true; wtx->nDebitCached = 1; } diff --git a/src/wallet.cpp b/src/wallet.cpp index 3176cf893a..0e0a0e87d3 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1245,6 +1245,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } wtxNew.BindWallet(this); + CMutableTransaction txNew; { LOCK2(cs_main, cs_wallet); @@ -1252,8 +1253,8 @@ bool CWallet::CreateTransaction(const vector >& vecSend, nFeeRet = payTxFee.GetFeePerK(); while (true) { - wtxNew.vin.clear(); - wtxNew.vout.clear(); + txNew.vin.clear(); + txNew.vout.clear(); wtxNew.fFromMe = true; int64_t nTotalValue = nValue + nFeeRet; @@ -1267,7 +1268,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, strFailReason = _("Transaction amount too small"); return false; } - wtxNew.vout.push_back(txout); + txNew.vout.push_back(txout); } // Choose coins to use @@ -1331,8 +1332,8 @@ bool CWallet::CreateTransaction(const vector >& vecSend, else { // Insert change txn at random position: - vector::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1); - wtxNew.vout.insert(position, newTxOut); + vector::iterator position = txNew.vout.begin()+GetRandInt(txNew.vout.size()+1); + txNew.vout.insert(position, newTxOut); } } else @@ -1340,17 +1341,20 @@ bool CWallet::CreateTransaction(const vector >& vecSend, // Fill vin BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) - wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); + txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); // Sign int nIn = 0; BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) - if (!SignSignature(*this, *coin.first, wtxNew, nIn++)) + if (!SignSignature(*this, *coin.first, txNew, nIn++)) { strFailReason = _("Signing transaction failed"); return false; } + // Embed the constructed transaction data in wtxNew. + *static_cast(&wtxNew) = CTransaction(txNew); + // Limit size unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION); if (nBytes >= MAX_STANDARD_TX_SIZE) From d38da59bf68fbb37535e2579bfb7355a16baed0e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 9 Jun 2014 10:02:00 +0200 Subject: [PATCH 214/336] Code simplifications after CTransaction::GetHash() caching --- src/bloom.cpp | 3 +- src/bloom.h | 2 +- src/core.h | 6 ---- src/main.cpp | 59 ++++++++++++++++++--------------------- src/main.h | 6 ++-- src/miner.cpp | 4 +-- src/net.cpp | 10 +++---- src/net.h | 4 +-- src/rpcrawtransaction.cpp | 6 ++-- src/test/bloom_tests.cpp | 26 ++++++++--------- src/wallet.cpp | 15 +++++----- src/wallet.h | 4 +-- 12 files changed, 67 insertions(+), 78 deletions(-) diff --git a/src/bloom.cpp b/src/bloom.cpp index 1bfcbd406f..26e366179c 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -99,7 +99,7 @@ bool CBloomFilter::IsWithinSizeConstraints() const return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS; } -bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash) +bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) { bool fFound = false; // Match if the filter contains the hash of tx @@ -108,6 +108,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx, const uint256& ha return true; if (isEmpty) return false; + const uint256& hash = tx.GetHash(); if (contains(hash)) fFound = true; diff --git a/src/bloom.h b/src/bloom.h index 75e3f38c55..956bead87f 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -83,7 +83,7 @@ public: bool IsWithinSizeConstraints() const; // Also adds any outputs which match the filter to the filter (to match their spending txes) - bool IsRelevantAndUpdate(const CTransaction& tx, const uint256& hash); + bool IsRelevantAndUpdate(const CTransaction& tx); // Checks for empty and full filters to avoid wasting cpu void UpdateEmptyFull(); diff --git a/src/core.h b/src/core.h index 1a20145ccf..27fda95552 100644 --- a/src/core.h +++ b/src/core.h @@ -496,12 +496,6 @@ public: uint256 BuildMerkleTree() const; - const uint256 &GetTxHash(unsigned int nIndex) const { - assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first - assert(nIndex < vtx.size()); - return vMerkleTree[nIndex]; - } - std::vector GetMerkleBranch(int nIndex) const; static uint256 CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex); void print() const; diff --git a/src/main.cpp b/src/main.cpp index 006ec7cabc..d3f04b95fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -130,8 +130,8 @@ namespace { namespace { struct CMainSignals { - // Notifies listeners of updated transaction data (passing hash, transaction, and optionally the block it is found in. - boost::signals2::signal SyncTransaction; + // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. + boost::signals2::signal SyncTransaction; // Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). boost::signals2::signal EraseTransaction; // Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). @@ -146,7 +146,7 @@ struct CMainSignals { } void RegisterWallet(CWalletInterface* pwalletIn) { - g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3)); + g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2)); g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1)); g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1)); @@ -160,7 +160,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn) { g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.EraseTransaction.disconnect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1)); - g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3)); + g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2)); } void UnregisterAllWallets() { @@ -172,8 +172,8 @@ void UnregisterAllWallets() { g_signals.SyncTransaction.disconnect_all_slots(); } -void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) { - g_signals.SyncTransaction(hash, tx, pblock); +void SyncWithWallets(const CTransaction &tx, const CBlock *pblock) { + g_signals.SyncTransaction(tx, pblock); } ////////////////////////////////////////////////////////////////////////////// @@ -952,7 +952,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa pool.addUnchecked(hash, entry); } - g_signals.SyncTransaction(hash, tx, NULL); + g_signals.SyncTransaction(tx, NULL); return true; } @@ -1479,7 +1479,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev) -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) +void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight) { bool ret; // mark inputs spent @@ -1494,7 +1494,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach } // add outputs - ret = inputs.SetCoins(txhash, CCoins(tx, nHeight)); + ret = inputs.SetCoins(tx.GetHash(), CCoins(tx, nHeight)); assert(ret); } @@ -1767,8 +1767,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || (pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); if (fEnforceBIP30) { - for (unsigned int i = 0; i < block.vtx.size(); i++) { - uint256 hash = block.GetTxHash(i); + BOOST_FOREACH(const CTransaction& tx, block.vtx) { + const uint256& hash = tx.GetHash(); if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned()) return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"), REJECT_INVALID, "bad-txns-BIP30"); @@ -1829,11 +1829,11 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C } CTxUndo txundo; - UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i)); + UpdateCoins(tx, state, view, txundo, pindex->nHeight); if (!tx.IsCoinBase()) blockundo.vtxundo.push_back(txundo); - vPos.push_back(std::make_pair(block.GetTxHash(i), pos)); + vPos.push_back(std::make_pair(tx.GetHash(), pos)); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } int64_t nTime = GetTimeMicros() - nStart; @@ -1892,13 +1892,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C assert(ret); // Watch for transactions paying to me - for (unsigned int i = 0; i < block.vtx.size(); i++) - g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block); + BOOST_FOREACH(const CTransaction& tx, block.vtx) + g_signals.SyncTransaction(tx, &block); // Watch for changes to the previous coinbase transaction. static uint256 hashPrevBestCoinBase; g_signals.UpdatedTransaction(hashPrevBestCoinBase); - hashPrevBestCoinBase = block.GetTxHash(0); + hashPrevBestCoinBase = block.vtx[0].GetHash(); return true; } @@ -1996,7 +1996,7 @@ bool static DisconnectTip(CValidationState &state) { // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx.GetHash(), tx, NULL); + SyncWithWallets(tx, NULL); } return true; } @@ -2036,11 +2036,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew) { // Tell wallet about transactions that went from mempool // to conflicted: BOOST_FOREACH(const CTransaction &tx, txConflicted) { - SyncWithWallets(tx.GetHash(), tx, NULL); + SyncWithWallets(tx, NULL); } // ... and about transactions that got confirmed: BOOST_FOREACH(const CTransaction &tx, block.vtx) { - SyncWithWallets(tx.GetHash(), tx, &block); + SyncWithWallets(tx, &block); } return true; } @@ -2381,16 +2381,11 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo if (!CheckTransaction(tx, state)) return error("CheckBlock() : CheckTransaction failed"); - // Build the merkle tree already. We need it anyway later, and it makes the - // block cache the transaction hashes, which means they don't need to be - // recalculated many times during this block's validation. - block.BuildMerkleTree(); - // Check for duplicate txids. This is caught by ConnectInputs(), // but catching it earlier avoids a potential DoS attack: set uniqueTx; - for (unsigned int i = 0; i < block.vtx.size(); i++) { - uniqueTx.insert(block.GetTxHash(i)); + BOOST_FOREACH(const CTransaction &tx, block.vtx) { + uniqueTx.insert(tx.GetHash()); } if (uniqueTx.size() != block.vtx.size()) return state.DoS(100, error("CheckBlock() : duplicate transaction"), @@ -2406,7 +2401,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo REJECT_INVALID, "bad-blk-sigops", true); // Check merkle root - if (fCheckMerkleRoot && block.hashMerkleRoot != block.vMerkleTree.back()) + if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree()) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); @@ -2682,8 +2677,8 @@ CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter& filter) for (unsigned int i = 0; i < block.vtx.size(); i++) { - uint256 hash = block.vtx[i].GetHash(); - if (filter.IsRelevantAndUpdate(block.vtx[i], hash)) + const uint256& hash = block.vtx[i].GetHash(); + if (filter.IsRelevantAndUpdate(block.vtx[i])) { vMatch.push_back(true); vMatchedTxn.push_back(make_pair(i, hash)); @@ -3832,7 +3827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) { mempool.check(pcoinsTip); - RelayTransaction(tx, inv.hash); + RelayTransaction(tx); mapAlreadyAskedFor.erase(inv); vWorkQueue.push_back(inv.hash); vEraseQueue.push_back(inv.hash); @@ -3862,7 +3857,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); - RelayTransaction(orphanTx, orphanHash); + RelayTransaction(orphanTx); mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash)); vWorkQueue.push_back(orphanHash); vEraseQueue.push_back(orphanHash); @@ -3947,7 +3942,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CTransaction tx; bool fInMemPool = mempool.lookup(hash, tx); if (!fInMemPool) continue; // another thread removed since queryHashes, maybe... - if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx, hash)) || + if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx)) || (!pfrom->pfilter)) vInv.push_back(inv); if (vInv.size() == MAX_INV_SZ) { diff --git a/src/main.h b/src/main.h index 5a0aedcde1..7071f0094f 100644 --- a/src/main.h +++ b/src/main.h @@ -113,7 +113,7 @@ void UnregisterWallet(CWalletInterface* pwalletIn); /** Unregister all wallets from core */ void UnregisterAllWallets(); /** Push an updated transaction to all registered wallets */ -void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL); +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL); /** Register with a network node to receive its signals */ void RegisterNodeSignals(CNodeSignals& nodeSignals); @@ -294,7 +294,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach std::vector *pvChecks = NULL); // Apply the effects of this transaction on the UTXO set represented by view -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash); +void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); // Context-independent validity checks bool CheckTransaction(const CTransaction& tx, CValidationState& state); @@ -1129,7 +1129,7 @@ public: class CWalletInterface { protected: - virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0; + virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) =0; virtual void EraseFromWallet(const uint256 &hash) =0; virtual void SetBestChain(const CBlockLocator &locator) =0; virtual void UpdatedTransaction(const uint256 &hash) =0; diff --git a/src/miner.cpp b/src/miner.cpp index 37cdc7d840..63ce125067 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -254,8 +254,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; CTxUndo txundo; - uint256 hash = tx.GetHash(); - UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1, hash); + const uint256& hash = tx.GetHash(); + UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1); // Added pblock->vtx.push_back(tx); diff --git a/src/net.cpp b/src/net.cpp index 757a06aaed..fe6b07aa94 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1808,17 +1808,17 @@ instance_of_cnetcleanup; -void RelayTransaction(const CTransaction& tx, const uint256& hash) +void RelayTransaction(const CTransaction& tx) { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(10000); ss << tx; - RelayTransaction(tx, hash, ss); + RelayTransaction(tx, ss); } -void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss) +void RelayTransaction(const CTransaction& tx, const CDataStream& ss) { - CInv inv(MSG_TX, hash); + CInv inv(MSG_TX, tx.GetHash()); { LOCK(cs_mapRelay); // Expire old relay messages @@ -1840,7 +1840,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt LOCK(pnode->cs_filter); if (pnode->pfilter) { - if (pnode->pfilter->IsRelevantAndUpdate(tx, hash)) + if (pnode->pfilter->IsRelevantAndUpdate(tx)) pnode->PushInventory(inv); } else pnode->PushInventory(inv); diff --git a/src/net.h b/src/net.h index 14d578a72a..eec92f340c 100644 --- a/src/net.h +++ b/src/net.h @@ -726,8 +726,8 @@ public: class CTransaction; -void RelayTransaction(const CTransaction& tx, const uint256& hash); -void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss); +void RelayTransaction(const CTransaction& tx); +void RelayTransaction(const CTransaction& tx, const CDataStream& ss); /** Access to the (IP) address database (peers.dat) */ class CAddrDB diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 1b5d494beb..9771f8e685 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -770,7 +770,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) catch (std::exception &e) { throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); } - uint256 hashTx = tx.GetHash(); + const uint256 &hashTx = tx.GetHash(); CCoinsViewCache &view = *pcoinsTip; CCoins existingCoins; @@ -780,7 +780,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) // push to local node and sync with wallets CValidationState state; if (AcceptToMemoryPool(mempool, state, tx, false, NULL, !fOverrideFees)) - SyncWithWallets(hashTx, tx, NULL); + SyncWithWallets(tx, NULL); else { if(state.IsInvalid()) throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); @@ -790,7 +790,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) } else if (fHaveChain) { throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain"); } - RelayTransaction(tx, hashTx); + RelayTransaction(tx); return hashTx.GetHex(); } diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index abedd3093c..b56d998be2 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -118,33 +118,33 @@ BOOST_AUTO_TEST_CASE(bloom_match) CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(uint256("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match tx hash"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); // byte-reversed tx hash filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized tx hash"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input signature"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input signature"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match input pub key"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input pub key"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address"); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx, spendingTx.GetHash()), "Simple Bloom filter didn't add output"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx), "Simple Bloom filter didn't add output"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431")); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match output address"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0)); - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match COutPoint"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match COutPoint"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); COutPoint prevOutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0); @@ -154,23 +154,23 @@ BOOST_AUTO_TEST_CASE(bloom_match) memcpy(&data[32], &prevOutPoint.n, sizeof(unsigned int)); filter.insert(data); } - BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter didn't match manually serialized COutPoint"); + BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(uint256("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436")); - BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random tx hash"); + BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random tx hash"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431")); - BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched random address"); + BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random address"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(uint256("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1)); - BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about"); + BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about"); filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL); filter.insert(COutPoint(uint256("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0)); - BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx, tx.GetHash()), "Simple Bloom filter matched COutPoint for an output we didn't care about"); + BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about"); } BOOST_AUTO_TEST_CASE(merkle_block_1) diff --git a/src/wallet.cpp b/src/wallet.cpp index 0e0a0e87d3..7664d6c25c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -603,11 +603,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) // Add a transaction to the wallet, or update it. // pblock is optional, but should be provided if the transaction is known to be in a block. // If fUpdate is true, existing transactions will be updated. -bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate) +bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { { AssertLockHeld(cs_wallet); - bool fExisted = mapWallet.count(hash); + bool fExisted = mapWallet.count(tx.GetHash()); if (fExisted && !fUpdate) return false; if (fExisted || IsMine(tx) || IsFromMe(tx)) { @@ -621,10 +621,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& return false; } -void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock) +void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock) { LOCK2(cs_main, cs_wallet); - if (!AddToWalletIfInvolvingMe(hash, tx, pblock, true)) + if (!AddToWalletIfInvolvingMe(tx, pblock, true)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -870,7 +870,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) ReadBlockFromDisk(block, pindex); BOOST_FOREACH(CTransaction& tx, block.vtx) { - if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate)) + if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) ret++; } pindex = chainActive.Next(pindex); @@ -909,9 +909,8 @@ void CWalletTx::RelayWalletTransaction() if (!IsCoinBase()) { if (GetDepthInMainChain() == 0) { - uint256 hash = GetHash(); - LogPrintf("Relaying wtx %s\n", hash.ToString()); - RelayTransaction((CTransaction)*this, hash); + LogPrintf("Relaying wtx %s\n", GetHash().ToString()); + RelayTransaction((CTransaction)*this); } } } diff --git a/src/wallet.h b/src/wallet.h index 7df656fc25..424799b14e 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -244,8 +244,8 @@ public: void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false); - void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock); - bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate); + void SyncTransaction(const CTransaction& tx, const CBlock* pblock); + bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256 &hash); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); From 0655fac0b11c7fa1992f50537887728a0878a5eb Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sat, 10 May 2014 14:47:16 +0200 Subject: [PATCH 215/336] miner: indentation fixes, remove for (;;) - change a for (;;) into while (true), as we nowhere else use the first - init nNonceFound to 0 - fix indentation in BitcoinMiner try/catch block --- src/miner.cpp | 207 +++++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 102 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 7efca7cfff..3daf823fd8 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -49,7 +49,6 @@ public: } }; - uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; @@ -58,8 +57,10 @@ typedef boost::tuple TxPriority; class TxPriorityCompare { bool byFee; + public: TxPriorityCompare(bool _byFee) : byFee(_byFee) { } + bool operator()(const TxPriority& a, const TxPriority& b) { if (byFee) @@ -114,6 +115,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Collect memory pool transactions into the block int64_t nFees = 0; + { LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); @@ -269,7 +271,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (fPrintPriority) { LogPrintf("priority %.1f fee %s txid %s\n", - dPriority, feeRate.ToString(), tx.GetHash().ToString()); + dPriority, feeRate.ToString(), tx.GetHash().ToString()); } // Add transactions that depend on this one to the priority queue @@ -334,7 +336,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } - #ifdef ENABLE_WALLET ////////////////////////////////////////////////////////////////////////////// // @@ -349,7 +350,8 @@ int64_t nHPSTimerStart = 0; // nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at // zero. // -bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) { +bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash) +{ // Write the first 76 bytes of the block header to a double-SHA256 state. CHash256 hasher; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -357,7 +359,7 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas assert(ss.size() == 80); hasher.Write((unsigned char*)&ss[0], 76); - for (;;) { + while (true) { nNonce++; // Write the last 4 bytes of the block header (the nonce) to a copy of @@ -435,114 +437,115 @@ void static BitcoinMiner(CWallet *pwallet) CReserveKey reservekey(pwallet); unsigned int nExtraNonce = 0; - try { while (true) { - if (Params().MiningRequiresPeers()) { - // Busy-wait for the network to come online so we don't waste time mining - // on an obsolete chain. In regtest mode we expect to fly solo. - while (vNodes.empty()) - MilliSleep(1000); - } - - // - // Create new block - // - unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); - CBlockIndex* pindexPrev = chainActive.Tip(); - - auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); - if (!pblocktemplate.get()) - return; - CBlock *pblock = &pblocktemplate->block; - IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - - LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), - ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - - // - // Search - // - int64_t nStart = GetTime(); - uint256 hashTarget = uint256().SetCompact(pblock->nBits); - uint256 hash; - uint32_t nNonce = 0; - uint32_t nOldNonce = 0; - while (true) - { - bool fFound = ScanHash(pblock, nNonce, &hash); - uint32_t nHashesDone = nNonce - nOldNonce; - nOldNonce = nNonce; - - // Check if something found - if (fFound) - { - if (hash <= hashTarget) - { - // Found a solution - pblock->nNonce = nNonce; - assert(hash == pblock->GetHash()); - - SetThreadPriority(THREAD_PRIORITY_NORMAL); - CheckWork(pblock, *pwallet, reservekey); - SetThreadPriority(THREAD_PRIORITY_LOWEST); - - // In regression test mode, stop mining after a block is found. - if (Params().MineBlocksOnDemand()) - throw boost::thread_interrupted(); - - break; - } + try { + while (true) { + if (Params().MiningRequiresPeers()) { + // Busy-wait for the network to come online so we don't waste time mining + // on an obsolete chain. In regtest mode we expect to fly solo. + while (vNodes.empty()) + MilliSleep(1000); } - // Meter hashes/sec - static int64_t nHashCounter; - if (nHPSTimerStart == 0) - { - nHPSTimerStart = GetTimeMillis(); - nHashCounter = 0; - } - else - nHashCounter += nHashesDone; - if (GetTimeMillis() - nHPSTimerStart > 4000) - { - static CCriticalSection cs; + // + // Create new block + // + unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); + CBlockIndex* pindexPrev = chainActive.Tip(); + + auto_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); + if (!pblocktemplate.get()) + return; + CBlock *pblock = &pblocktemplate->block; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); + + LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), + ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); + + // + // Search + // + int64_t nStart = GetTime(); + uint256 hashTarget = uint256().SetCompact(pblock->nBits); + uint256 hash; + uint32_t nNonce = 0; + uint32_t nOldNonce = 0; + while (true) { + bool fFound = ScanHash(pblock, nNonce, &hash); + uint32_t nHashesDone = nNonce - nOldNonce; + nOldNonce = nNonce; + + // Check if something found + if (fFound) { - LOCK(cs); - if (GetTimeMillis() - nHPSTimerStart > 4000) + if (hash <= hashTarget) { - dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); - nHPSTimerStart = GetTimeMillis(); - nHashCounter = 0; - static int64_t nLogTime; - if (GetTime() - nLogTime > 30 * 60) + // Found a solution + pblock->nNonce = nNonce; + assert(hash == pblock->GetHash()); + + SetThreadPriority(THREAD_PRIORITY_NORMAL); + CheckWork(pblock, *pwallet, reservekey); + SetThreadPriority(THREAD_PRIORITY_LOWEST); + + // In regression test mode, stop mining after a block is found. + if (Params().MineBlocksOnDemand()) + throw boost::thread_interrupted(); + + break; + } + } + + // Meter hashes/sec + static int64_t nHashCounter; + if (nHPSTimerStart == 0) + { + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + } + else + nHashCounter += nHashesDone; + if (GetTimeMillis() - nHPSTimerStart > 4000) + { + static CCriticalSection cs; + { + LOCK(cs); + if (GetTimeMillis() - nHPSTimerStart > 4000) { - nLogTime = GetTime(); - LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0); + dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart); + nHPSTimerStart = GetTimeMillis(); + nHashCounter = 0; + static int64_t nLogTime; + if (GetTime() - nLogTime > 30 * 60) + { + nLogTime = GetTime(); + LogPrintf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0); + } } } } - } - // Check for stop or if block needs to be rebuilt - boost::this_thread::interruption_point(); - // Regtest mode doesn't require peers - if (vNodes.empty() && Params().MiningRequiresPeers()) - break; - if (nNonce >= 0xffff0000) - break; - if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) - break; - if (pindexPrev != chainActive.Tip()) - break; + // Check for stop or if block needs to be rebuilt + boost::this_thread::interruption_point(); + // Regtest mode doesn't require peers + if (vNodes.empty() && Params().MiningRequiresPeers()) + break; + if (nNonce >= 0xffff0000) + break; + if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) + break; + if (pindexPrev != chainActive.Tip()) + break; - // Update nTime every few seconds - UpdateTime(*pblock, pindexPrev); - if (Params().AllowMinDifficultyBlocks()) - { - // Changing pblock->nTime can change work required on testnet: - hashTarget.SetCompact(pblock->nBits); + // Update nTime every few seconds + UpdateTime(*pblock, pindexPrev); + if (Params().AllowMinDifficultyBlocks()) + { + // Changing pblock->nTime can change work required on testnet: + hashTarget.SetCompact(pblock->nBits); + } } } - } } + } catch (boost::thread_interrupted) { LogPrintf("BitcoinMiner terminated\n"); @@ -577,4 +580,4 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); } -#endif +#endif // ENABLE_WALLET From 2831a03b798e0eea724250a6ba15cb637800354d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sun, 22 Jun 2014 14:51:38 +0200 Subject: [PATCH 216/336] remove unused CNode::Cleanup() --- src/net.cpp | 5 ----- src/net.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 757a06aaed..ad0c634340 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -528,10 +528,6 @@ void CNode::CloseSocketDisconnect() pnodeSync = NULL; } -void CNode::Cleanup() -{ -} - void CNode::PushVersion() { int nBestHeight = g_signals.GetHeight().get_value_or(0); @@ -773,7 +769,6 @@ void ThreadSocketHandler() // close socket and cleanup pnode->CloseSocketDisconnect(); - pnode->Cleanup(); // hold in disconnected pool until all refs are released if (pnode->fNetworkNode || pnode->fInbound) diff --git a/src/net.h b/src/net.h index 14d578a72a..ace9dd895d 100644 --- a/src/net.h +++ b/src/net.h @@ -693,8 +693,6 @@ public: void Subscribe(unsigned int nChannel, unsigned int nHops=0); void CancelSubscribe(unsigned int nChannel); void CloseSocketDisconnect(); - void Cleanup(); - // Denial-of-service detection/prevention // The idea is to detect peers that are behaving From 3dc1464f0a87e26f3aa39c446eb4d102a8c84dc2 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sun, 22 Jun 2014 14:52:38 +0200 Subject: [PATCH 217/336] add missing vhListenSocket.clear(); to CNetCleanup() --- src/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net.cpp b/src/net.cpp index ad0c634340..e082980b04 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1784,6 +1784,7 @@ public: delete pnode; vNodes.clear(); vNodesDisconnected.clear(); + vhListenSocket.clear(); delete semOutbound; semOutbound = NULL; delete pnodeLocalHost; From b612bde521e42632e24735623b7cd715096a61a5 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 23 Jun 2014 08:06:52 +0200 Subject: [PATCH 218/336] remove unneded class CNodeCombinedStats; from rpcconsole.cpp - also 2 small style fixes --- src/qt/rpcconsole.cpp | 3 ++- src/qt/rpcconsole.h | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f7491f4a42..e1f40ddd09 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -231,6 +231,7 @@ RPCConsole::RPCConsole(QWidget *parent) : startExecutor(); setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS); + ui->detailWidget->hide(); clear(); @@ -581,7 +582,7 @@ void RPCConsole::peerLayoutChanged() if (fUnselect && selectedRow >= 0) { ui->peerWidget->selectionModel()->select(QItemSelection(selectedModelIndex.first(), selectedModelIndex.last()), - QItemSelectionModel::Deselect); + QItemSelectionModel::Deselect); } if (fReselect) diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 3fee34d00e..3aeff3eace 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -13,7 +13,6 @@ #include class ClientModel; -class CNodeCombinedStats; QT_BEGIN_NAMESPACE class QItemSelection; From fa126effc2a03e22708960344e62fc21259deb23 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 5 Jun 2014 10:10:52 +0200 Subject: [PATCH 219/336] Avoid undefined behavior using CFlatData in CScript serialization `&vch[vch.size()]` and even `&vch[0]` on vectors can cause assertion errors with VC in debug mode. This is the problem mentioned in #4239. The deeper problem with this is that we rely on undefined behavior. - Add `begin_ptr` and `end_ptr` functions that get the beginning and end pointer of vector in a reliable way that copes with empty vectors and doesn't reference outside the vector (see https://stackoverflow.com/questions/1339470/how-to-get-the-address-of-the-stdvector-buffer-start-most-elegantly/1339767#1339767). - Add a convenience constructor to CFlatData that wraps a vector. I added `begin_ptr` and `end_ptr` as separate functions as I imagine they will be useful in more places. --- src/script.h | 8 ++++---- src/serialize.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/script.h b/src/script.h index bd6574627a..ea988f0e40 100644 --- a/src/script.h +++ b/src/script.h @@ -770,12 +770,12 @@ public: void Serialize(Stream &s, int nType, int nVersion) const { std::vector compr; if (Compress(compr)) { - s << CFlatData(&compr[0], &compr[compr.size()]); + s << CFlatData(compr); return; } unsigned int nSize = script.size() + nSpecialScripts; s << VARINT(nSize); - s << CFlatData(&script[0], &script[script.size()]); + s << CFlatData(script); } template @@ -784,13 +784,13 @@ public: s >> VARINT(nSize); if (nSize < nSpecialScripts) { std::vector vch(GetSpecialSize(nSize), 0x00); - s >> REF(CFlatData(&vch[0], &vch[vch.size()])); + s >> REF(CFlatData(vch)); Decompress(nSize, vch); return; } nSize -= nSpecialScripts; script.resize(nSize); - s >> REF(CFlatData(&script[0], &script[script.size()])); + s >> REF(CFlatData(script)); } }; diff --git a/src/serialize.h b/src/serialize.h index 1341746592..5ac85554c6 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -37,6 +37,34 @@ inline T& REF(const T& val) return const_cast(val); } +/** Get begin pointer of vector (non-const version). + * @note These functions avoid the undefined case of indexing into an empty + * vector, as well as that of indexing after the end of the vector. + */ +template +inline T* begin_ptr(std::vector& v) +{ + return v.empty() ? NULL : &v[0]; +} +/** Get begin pointer of vector (const version) */ +template +inline const T* begin_ptr(const std::vector& v) +{ + return v.empty() ? NULL : &v[0]; +} +/** Get end pointer of vector (non-const version) */ +template +inline T* end_ptr(std::vector& v) +{ + return v.empty() ? NULL : (&v[0] + v.size()); +} +/** Get end pointer of vector (const version) */ +template +inline const T* end_ptr(const std::vector& v) +{ + return v.empty() ? NULL : (&v[0] + v.size()); +} + ///////////////////////////////////////////////////////////////// // // Templates for serializing to anything that looks like a stream, @@ -318,6 +346,12 @@ protected: char* pend; public: CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } + template + explicit CFlatData(std::vector &v) + { + pbegin = (char*)begin_ptr(v); + pend = (char*)end_ptr(v); + } char* begin() { return pbegin; } const char* begin() const { return pbegin; } char* end() { return pend; } From fcb0a1bb9cea0e627152e544b0701c039cc3f60e Mon Sep 17 00:00:00 2001 From: daniel Date: Tue, 27 May 2014 11:44:55 +0800 Subject: [PATCH 220/336] change "char pch[200000]" to "new char[200000]" --- src/util.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 30590912ff..1480b2ebf8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -168,15 +168,14 @@ void RandAddSeedPerfmon() #ifdef WIN32 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Seed with the entire set of perfmon data - unsigned char pdata[250000]; - memset(pdata, 0, sizeof(pdata)); - unsigned long nSize = sizeof(pdata); - long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); + std::vector vData(250000,0); + unsigned long nSize = vData.size(); + long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize); RegCloseKey(HKEY_PERFORMANCE_DATA); if (ret == ERROR_SUCCESS) { - RAND_add(pdata, nSize, nSize/100.0); - OPENSSL_cleanse(pdata, nSize); + RAND_add(begin_ptr(vData), nSize, nSize/100.0); + OPENSSL_cleanse(begin_ptr(vData), nSize); LogPrint("rand", "RandAddSeed() %lu bytes\n", nSize); } #endif @@ -1141,15 +1140,15 @@ void ShrinkDebugFile() if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) { // Restart the file with some of the end - char pch[200000]; - fseek(file, -sizeof(pch), SEEK_END); - int nBytes = fread(pch, 1, sizeof(pch), file); + std::vector vch(200000,0); + fseek(file, -vch.size(), SEEK_END); + int nBytes = fread(begin_ptr(vch), 1, vch.size(), file); fclose(file); file = fopen(pathLog.string().c_str(), "w"); if (file) { - fwrite(pch, 1, nBytes, file); + fwrite(begin_ptr(vch), 1, nBytes, file); fclose(file); } } From 17db9767c469629bd338942afa776cd8ad185b04 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 23 Jun 2014 12:04:17 +0200 Subject: [PATCH 221/336] doc: Remove unused section from release-process.md It is outdated information. If we ever resurrect gitian-downloader it can be brought back from history and updated. --- doc/release-process.md | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 9cdc43b9be..affe6ed13a 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -177,34 +177,6 @@ Commit your signature to gitian.sigs: ### 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=(new version, e.g. 0.8.0) - 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 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 -r bitcoin-${VERSION}-linux-gitian.zip * - cp bitcoin-${VERSION}-linux-gitian.zip ../ - popd - mkdir bitcoin-${VERSION}-win-gitian - pushd bitcoin-${VERSION}-win-gitian - unzip ../bitcoin-${VERSION}-win-gitian.zip - mkdir gitian - cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ - for signer in $(ls ../gitian.sigs/${VERSION}-win/); do - cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert - cp ../gitian.sigs/${VERSION}-win/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig - done - zip -r bitcoin-${VERSION}-win-gitian.zip * - cp bitcoin-${VERSION}-win-gitian.zip ../ - popd - - Upload gitian zips to SourceForge - Announce the release: From 6a5c124b849ac1e9e5cfb99e72ae483eeb3e8cad Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 21 May 2014 15:22:42 +0200 Subject: [PATCH 222/336] [Qt] don't allow translation of our example btc address --- src/qt/forms/sendcoinsentry.ui | 2 +- src/qt/forms/signverifymessagedialog.ui | 4 ++-- src/qt/guiutil.cpp | 4 +++- src/qt/signverifymessagedialog.cpp | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index e77de0d9b8..9d829970f0 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -51,7 +51,7 @@ - The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + The Bitcoin address to send the payment to diff --git a/src/qt/forms/signverifymessagedialog.ui b/src/qt/forms/signverifymessagedialog.ui index aa271b4f2a..53573ec821 100644 --- a/src/qt/forms/signverifymessagedialog.ui +++ b/src/qt/forms/signverifymessagedialog.ui @@ -45,7 +45,7 @@ - The address to sign the message with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + The Bitcoin address to sign the message with @@ -255,7 +255,7 @@ - The address the message was signed with (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L) + The Bitcoin address the message was signed with diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 4fe98251d9..81b9054252 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -91,7 +91,9 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) widget->setFont(bitcoinAddressFont()); #if QT_VERSION >= 0x040700 - widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); + // We don't want translators to use own addresses in translations + // and this is the only place, where this address is supplied. + widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg("1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L")); #endif widget->setValidator(new BitcoinAddressEntryValidator(parent)); widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 3e56412c7c..d4d021e21c 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -27,7 +27,6 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(QWidget *parent) : #if QT_VERSION >= 0x040700 ui->signatureOut_SM->setPlaceholderText(tr("Click \"Sign Message\" to generate signature")); - ui->addressIn_VM->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); #endif GUIUtil::setupAddressWidget(ui->addressIn_SM, this); From be873f64540d3c0b1227920eb466097ed738f452 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 23 Jun 2014 14:35:35 +0200 Subject: [PATCH 223/336] Issue warning if collecting RandSeed data failed --- src/util.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 1480b2ebf8..7946089571 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -176,7 +176,14 @@ void RandAddSeedPerfmon() { RAND_add(begin_ptr(vData), nSize, nSize/100.0); OPENSSL_cleanse(begin_ptr(vData), nSize); - LogPrint("rand", "RandAddSeed() %lu bytes\n", nSize); + LogPrint("rand", "%s: %lu bytes\n", __func__, nSize); + } else { + static bool warned = false; // Warn only once + if (!warned) + { + LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret); + warned = true; + } } #endif } From 3b1295e98878840c94db62223d1bc202d71a7366 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 23 Jun 2014 17:41:52 +0200 Subject: [PATCH 224/336] qa/rpc_tests: Wait for handshake to complete in connect_nodes This avoids a race condition in which the connection was made but the version handshake is not completed yet. In that case transactions won't be broadcasted to a peer yet, and the nodes will wait forever for their mempools to sync. --- qa/rpc-tests/util.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index eded098c7c..27c9f778f6 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -182,6 +182,10 @@ def wait_bitcoinds(): def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") + # poll until version handshake complete to avoid race conditions + # with transaction relaying + while any(peer['version'] == 0 for peer in from_connection.getpeerinfo()): + time.sleep(0.1) def find_output(node, txid, amount): """ From f3967bcc50ea95510f12a86e90dec4c8c78fff3b Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Mon, 23 Jun 2014 14:04:24 -0400 Subject: [PATCH 225/336] build: fix build weirdness after 54372482. bitcoin-config.h moved, but the old file is likely to still exist when reconfiguring or switching branches. This would've caused files to not rebuild correctly, and other strange problems. Make the path explicit so that the old one cannot be found. Core libs use config/bitcoin-config.h. Libs (like crypto) which don't want access to bitcoin's headers continue to use -Iconfig and #include bitcoin-config.h. --- src/Makefile.am | 2 +- src/clientversion.h | 2 +- src/compat/glibc_compat.cpp | 2 +- src/compat/glibc_sanity.cpp | 2 +- src/init.cpp | 2 +- src/main.h | 2 +- src/net.cpp | 2 +- src/netbase.h | 2 +- src/qt/addressbookpage.cpp | 2 +- src/qt/bitcoin.cpp | 2 +- src/qt/bitcoingui.h | 2 +- src/qt/notificator.h | 2 +- src/qt/optionsdialog.cpp | 2 +- src/qt/optionsmodel.cpp | 2 +- src/qt/receiverequestdialog.cpp | 2 +- src/qt/test/test_main.cpp | 2 +- src/util.h | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3948ca0780..5ecded442c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ $(LIBLEVELDB) $(LIBMEMENV): endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BITCOIN_CONFIG_INCLUDES) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) noinst_LIBRARIES = \ libbitcoin_server.a \ diff --git a/src/clientversion.h b/src/clientversion.h index 29b4aa3764..a30bbff06b 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -2,7 +2,7 @@ #define CLIENTVERSION_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #else // // client versioning and copyright year diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp index bb870c01f8..22f82e4259 100644 --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp index 6e5bae8a48..d93602e0fe 100644 --- a/src/compat/glibc_sanity.cpp +++ b/src/compat/glibc_sanity.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include diff --git a/src/init.cpp b/src/init.cpp index 12d2d1bb44..ff7a9011a5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "init.h" diff --git a/src/main.h b/src/main.h index 7071f0094f..27041a0026 100644 --- a/src/main.h +++ b/src/main.h @@ -7,7 +7,7 @@ #define BITCOIN_MAIN_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "chainparams.h" diff --git a/src/net.cpp b/src/net.cpp index 71e3e57fa7..811df43334 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "net.h" diff --git a/src/netbase.h b/src/netbase.h index 23cfb1f158..40a3d25676 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -6,7 +6,7 @@ #define BITCOIN_NETBASE_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "compat.h" diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 2dc56a5107..5df8f19729 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "addressbookpage.h" diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 387f6ede4b..76dddb103c 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "bitcoingui.h" diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 275fa35f39..e7a842df99 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -6,7 +6,7 @@ #define BITCOINGUI_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include diff --git a/src/qt/notificator.h b/src/qt/notificator.h index abab986992..3395e64350 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -6,7 +6,7 @@ #define NOTIFICATOR_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index abfd4123e0..12d54dff64 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "optionsdialog.h" diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4dafd9d2af..6d985abaf8 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "optionsmodel.h" diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index d8dad15c0d..cc2f00916f 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -22,7 +22,7 @@ #endif #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" /* for USE_QRCODE */ +#include "config/bitcoin-config.h" /* for USE_QRCODE */ #endif #ifdef USE_QRCODE diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 220da28cfe..03a2381c06 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,5 +1,5 @@ #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #ifdef ENABLE_WALLET diff --git a/src/util.h b/src/util.h index da1810a3d3..5eb6f03826 100644 --- a/src/util.h +++ b/src/util.h @@ -7,7 +7,7 @@ #define BITCOIN_UTIL_H #if defined(HAVE_CONFIG_H) -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "compat.h" From 7f3b4e95695d50a4970e6eb91faa956ab276f161 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Tue, 17 Jun 2014 14:18:13 -0400 Subject: [PATCH 226/336] Relax IsStandard rules for pay-to-script-hash transactions Relax the AreInputsStandard() tests for P2SH transactions -- allow any Script in a P2SH transaction to be relayed/mined, as long as it has 15 or fewer signature operations. Rationale: https://gist.github.com/gavinandresen/88be40c141bc67acb247 I don't have an easy way to test this, but the code changes are straightforward and I've updated the AreInputsStandard unit tests. --- src/main.cpp | 43 +++++++------ src/main.h | 2 + src/test/script_P2SH_tests.cpp | 114 ++++++++++++++++++++------------- 3 files changed, 95 insertions(+), 64 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d3f04b95fa..ecabd9ec2c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -582,15 +582,13 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) } // -// Check transaction inputs, and make sure any -// pay-to-script-hash transactions are evaluating IsStandard scripts +// Check transaction inputs to mitigate two +// potential denial-of-service attacks: // -// Why bother? To avoid denial-of-service attacks; an attacker -// can submit a standard HASH... OP_EQUAL transaction, -// which will get accepted into blocks. The redemption -// script can be anything; an attacker could use a very -// expensive-to-check-upon-redemption script like: -// DUP CHECKSIG DROP ... repeated 100 times... OP_1 +// 1. scriptSigs with extra data stuffed into them, +// not consumed by scriptPubKey (or P2SH script) +// 2. P2SH scripts with a crazy number of expensive +// CHECKSIG/CHECKMULTISIG operations // bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) { @@ -614,8 +612,9 @@ bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) // Transactions with extra stuff in their scriptSigs are // non-standard. Note that this EvalScript() call will // be quick, because if there are any operations - // beside "push data" in the scriptSig the - // IsStandard() call returns false + // beside "push data" in the scriptSig + // IsStandard() will have already returned false + // and this method isn't called. vector > stack; if (!EvalScript(stack, tx.vin[i].scriptSig, tx, i, false, 0)) return false; @@ -627,16 +626,20 @@ bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) CScript subscript(stack.back().begin(), stack.back().end()); vector > vSolutions2; txnouttype whichType2; - if (!Solver(subscript, whichType2, vSolutions2)) - return false; - if (whichType2 == TX_SCRIPTHASH) - return false; - - int tmpExpected; - tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); - if (tmpExpected < 0) - return false; - nArgsExpected += tmpExpected; + if (Solver(subscript, whichType2, vSolutions2)) + { + int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); + if (tmpExpected < 0) + return false; + nArgsExpected += tmpExpected; + } + else + { + // Any other Script with less than 15 sigops OK: + unsigned int sigops = subscript.GetSigOpCount(true); + // ... extra data left on the stack after execution is OK, too: + return (sigops <= MAX_P2SH_SIGOPS); + } } if (stack.size() != (unsigned int)nArgsExpected) diff --git a/src/main.h b/src/main.h index 27041a0026..ff1f742d1e 100644 --- a/src/main.h +++ b/src/main.h @@ -43,6 +43,8 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; +/** Maxiumum number of signature check operations in an IsStandard() P2SH script */ +static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of orphan transactions kept in memory */ static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; /** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */ diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index a75593a8b2..6ae2b9cf64 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -256,46 +256,61 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) CCoinsView coinsDummy; CCoinsViewCache coins(coinsDummy); CBasicKeyStore keystore; - CKey key[3]; + CKey key[6]; vector keys; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 6; i++) { key[i].MakeNewKey(true); keystore.AddKey(key[i]); - keys.push_back(key[i].GetPubKey()); } + for (int i = 0; i < 3; i++) + keys.push_back(key[i].GetPubKey()); CMutableTransaction txFrom; - txFrom.vout.resize(6); + txFrom.vout.resize(7); // First three are standard: CScript pay1; pay1.SetDestination(key[0].GetPubKey().GetID()); keystore.AddCScript(pay1); - CScript payScriptHash1; payScriptHash1.SetDestination(pay1.GetID()); CScript pay1of3; pay1of3.SetMultisig(1, keys); - txFrom.vout[0].scriptPubKey = payScriptHash1; + txFrom.vout[0].scriptPubKey.SetDestination(pay1.GetID()); // P2SH (OP_CHECKSIG) txFrom.vout[0].nValue = 1000; - txFrom.vout[1].scriptPubKey = pay1; + txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG txFrom.vout[1].nValue = 2000; - txFrom.vout[2].scriptPubKey = pay1of3; + txFrom.vout[2].scriptPubKey = pay1of3; // ordinary OP_CHECKMULTISIG txFrom.vout[2].nValue = 3000; - // Last three non-standard: - CScript empty; - keystore.AddCScript(empty); - txFrom.vout[3].scriptPubKey = empty; + // vout[3] is complicated 1-of-3 AND 2-of-3 + // ... that is OK if wrapped in P2SH: + CScript oneAndTwo; + oneAndTwo << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey(); + oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY; + oneAndTwo << OP_2 << key[3].GetPubKey() << key[4].GetPubKey() << key[5].GetPubKey(); + oneAndTwo << OP_3 << OP_CHECKMULTISIG; + keystore.AddCScript(oneAndTwo); + txFrom.vout[3].scriptPubKey.SetDestination(oneAndTwo.GetID()); txFrom.vout[3].nValue = 4000; - // Can't use SetPayToScriptHash, it checks for the empty Script. So: - txFrom.vout[4].scriptPubKey << OP_HASH160 << Hash160(empty) << OP_EQUAL; + + // vout[4] is max sigops: + CScript fifteenSigops; fifteenSigops << OP_1; + for (int i = 0; i < MAX_P2SH_SIGOPS; i++) + fifteenSigops << key[i%3].GetPubKey(); + fifteenSigops << OP_15 << OP_CHECKMULTISIG; + keystore.AddCScript(fifteenSigops); + txFrom.vout[4].scriptPubKey.SetDestination(fifteenSigops.GetID()); txFrom.vout[4].nValue = 5000; - CScript oneOfEleven; - oneOfEleven << OP_1; - for (int i = 0; i < 11; i++) - oneOfEleven << key[0].GetPubKey(); - oneOfEleven << OP_11 << OP_CHECKMULTISIG; - txFrom.vout[5].scriptPubKey.SetDestination(oneOfEleven.GetID()); - txFrom.vout[5].nValue = 6000; + + // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS + CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG; + keystore.AddCScript(sixteenSigops); + txFrom.vout[5].scriptPubKey.SetDestination(fifteenSigops.GetID()); + txFrom.vout[5].nValue = 5000; + CScript twentySigops; twentySigops << OP_CHECKMULTISIG; + keystore.AddCScript(twentySigops); + txFrom.vout[6].scriptPubKey.SetDestination(twentySigops.GetID()); + txFrom.vout[6].nValue = 6000; + coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0)); @@ -303,19 +318,24 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vout.resize(1); txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); - txTo.vin.resize(3); - txTo.vin[0].prevout.n = 0; - txTo.vin[0].prevout.hash = txFrom.GetHash(); + txTo.vin.resize(5); + for (int i = 0; i < 5; i++) + { + txTo.vin[i].prevout.n = i; + txTo.vin[i].prevout.hash = txFrom.GetHash(); + } BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0)); - txTo.vin[1].prevout.n = 1; - txTo.vin[1].prevout.hash = txFrom.GetHash(); BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1)); - txTo.vin[2].prevout.n = 2; - txTo.vin[2].prevout.hash = txFrom.GetHash(); BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2)); + // SignSignature doesn't know how to sign these. We're + // not testing validating signatures, so just create + // dummy signatures that DO include the correct P2SH scripts: + txTo.vin[3].scriptSig << OP_11 << OP_11 << static_cast >(oneAndTwo); + txTo.vin[4].scriptSig << static_cast >(fifteenSigops); BOOST_CHECK(::AreInputsStandard(txTo, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 1U); + // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U); // Make sure adding crap to the scriptSigs makes them non-standard: for (int i = 0; i < 3; i++) @@ -326,23 +346,29 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vin[i].scriptSig = t; } - CMutableTransaction txToNonStd; - txToNonStd.vout.resize(1); - txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); - txToNonStd.vout[0].nValue = 1000; - txToNonStd.vin.resize(2); - txToNonStd.vin[0].prevout.n = 4; - txToNonStd.vin[0].prevout.hash = txFrom.GetHash(); - txToNonStd.vin[0].scriptSig << Serialize(empty); - txToNonStd.vin[1].prevout.n = 5; - txToNonStd.vin[1].prevout.hash = txFrom.GetHash(); - txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven); + CMutableTransaction txToNonStd1; + txToNonStd1.vout.resize(1); + txToNonStd1.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); + txToNonStd1.vout[0].nValue = 1000; + txToNonStd1.vin.resize(1); + txToNonStd1.vin[0].prevout.n = 5; + txToNonStd1.vin[0].prevout.hash = txFrom.GetHash(); + txToNonStd1.vin[0].scriptSig << static_cast >(sixteenSigops); - BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd, coins), 11U); + BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U); - txToNonStd.vin[0].scriptSig.clear(); - BOOST_CHECK(!::AreInputsStandard(txToNonStd, coins)); + CMutableTransaction txToNonStd2; + txToNonStd2.vout.resize(1); + txToNonStd2.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID()); + txToNonStd2.vout[0].nValue = 1000; + txToNonStd2.vin.resize(1); + txToNonStd2.vin[0].prevout.n = 6; + txToNonStd2.vin[0].prevout.hash = txFrom.GetHash(); + txToNonStd2.vin[0].scriptSig << static_cast >(twentySigops); + + BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins)); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U); } BOOST_AUTO_TEST_SUITE_END() From df852d2bcc6573a3fcb3e59f82f7ea4dfa11290e Mon Sep 17 00:00:00 2001 From: jtimon Date: Mon, 10 Mar 2014 08:46:53 -0700 Subject: [PATCH 227/336] Refactor proof of work related functions out of main --- src/Makefile.am | 2 + src/main.cpp | 113 +------------------------------------ src/main.h | 10 ---- src/miner.cpp | 1 + src/pow.cpp | 123 +++++++++++++++++++++++++++++++++++++++++ src/pow.h | 23 ++++++++ src/rpcmining.cpp | 1 + src/test/DoS_tests.cpp | 1 + src/txdb.cpp | 5 +- 9 files changed, 155 insertions(+), 124 deletions(-) create mode 100644 src/pow.cpp create mode 100644 src/pow.h diff --git a/src/Makefile.am b/src/Makefile.am index 5ecded442c..7e7fa0c3ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,6 +71,7 @@ BITCOIN_CORE_H = \ netbase.h \ net.h \ noui.h \ + pow.h \ protocol.h \ rpcclient.h \ rpcprotocol.h \ @@ -121,6 +122,7 @@ libbitcoin_server_a_SOURCES = \ miner.cpp \ net.cpp \ noui.cpp \ + pow.cpp \ rpcblockchain.cpp \ rpcmining.cpp \ rpcmisc.cpp \ diff --git a/src/main.cpp b/src/main.cpp index d3f04b95fa..ea47601081 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include "checkqueue.h" #include "init.h" #include "net.h" +#include "pow.h" #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" @@ -1194,118 +1195,6 @@ int64_t GetBlockValue(int nHeight, int64_t nFees) return nSubsidy + nFees; } -static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks -static const int64_t nTargetSpacing = 10 * 60; -static const int64_t nInterval = nTargetTimespan / nTargetSpacing; - -// -// minimum amount of work that could possibly be required nTime after -// minimum work required was nBase -// -unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) -{ - const uint256 &bnLimit = Params().ProofOfWorkLimit(); - // Testnet has min-difficulty blocks - // after nTargetSpacing*2 time between blocks: - if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2) - return bnLimit.GetCompact(); - - uint256 bnResult; - bnResult.SetCompact(nBase); - while (nTime > 0 && bnResult < bnLimit) - { - // Maximum 400% adjustment... - bnResult *= 4; - // ... in best-case exactly 4-times-normal target time - nTime -= nTargetTimespan*4; - } - if (bnResult > bnLimit) - bnResult = bnLimit; - return bnResult.GetCompact(); -} - -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) -{ - unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); - - // Genesis block - if (pindexLast == NULL) - return nProofOfWorkLimit; - - // Only change once per interval - if ((pindexLast->nHeight+1) % nInterval != 0) - { - if (Params().AllowMinDifficultyBlocks()) - { - // Special difficulty rule for testnet: - // If the new block's timestamp is more than 2* 10 minutes - // then allow mining of a min-difficulty block. - if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2) - return nProofOfWorkLimit; - else - { - // Return the last non-special-min-difficulty-rules-block - const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) - pindex = pindex->pprev; - return pindex->nBits; - } - } - return pindexLast->nBits; - } - - // Go back by what we want to be 14 days worth of blocks - const CBlockIndex* pindexFirst = pindexLast; - for (int i = 0; pindexFirst && i < nInterval-1; i++) - pindexFirst = pindexFirst->pprev; - assert(pindexFirst); - - // Limit adjustment step - int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); - LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < nTargetTimespan/4) - nActualTimespan = nTargetTimespan/4; - if (nActualTimespan > nTargetTimespan*4) - nActualTimespan = nTargetTimespan*4; - - // Retarget - uint256 bnNew; - uint256 bnOld; - bnNew.SetCompact(pindexLast->nBits); - bnOld = bnNew; - bnNew *= nActualTimespan; - bnNew /= nTargetTimespan; - - if (bnNew > Params().ProofOfWorkLimit()) - bnNew = Params().ProofOfWorkLimit(); - - /// debug print - LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); - LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); - LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); - - return bnNew.GetCompact(); -} - -bool CheckProofOfWork(uint256 hash, unsigned int nBits) -{ - bool fNegative; - bool fOverflow; - uint256 bnTarget; - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); - - // Check range - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) - return error("CheckProofOfWork() : nBits below minimum work"); - - // Check proof of work matches claimed amount - if (hash > bnTarget) - return error("CheckProofOfWork() : hash doesn't match nBits"); - - return true; -} - bool IsInitialBlockDownload() { LOCK(cs_main); diff --git a/src/main.h b/src/main.h index 27041a0026..9858bcfd69 100644 --- a/src/main.h +++ b/src/main.h @@ -146,10 +146,6 @@ bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, bool fSendTrickle); /** Run an instance of the script checking thread */ void ThreadScriptCheck(); -/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ -bool CheckProofOfWork(uint256 hash, unsigned int nBits); -/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ -unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ @@ -159,7 +155,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, b /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(CValidationState &state); int64_t GetBlockValue(int nHeight, int64_t nFees); -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev); @@ -812,11 +807,6 @@ public: return (~bnTarget / (bnTarget + 1)) + 1; } - bool CheckIndex() const - { - return CheckProofOfWork(GetBlockHash(), nBits); - } - enum { nMedianTimeSpan=11 }; int64_t GetMedianTimePast() const diff --git a/src/miner.cpp b/src/miner.cpp index 63ce125067..2a4f8cfa52 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -9,6 +9,7 @@ #include "hash.h" #include "main.h" #include "net.h" +#include "pow.h" #ifdef ENABLE_WALLET #include "wallet.h" #endif diff --git a/src/pow.cpp b/src/pow.cpp new file mode 100644 index 0000000000..274a5d6f98 --- /dev/null +++ b/src/pow.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "pow.h" + +#include "chainparams.h" +#include "core.h" +#include "main.h" +#include "uint256.h" + +static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks +static const int64_t nTargetSpacing = 10 * 60; +static const int64_t nInterval = nTargetTimespan / nTargetSpacing; + +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) +{ + unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); + + // Genesis block + if (pindexLast == NULL) + return nProofOfWorkLimit; + + // Only change once per interval + if ((pindexLast->nHeight+1) % nInterval != 0) + { + if (Params().AllowMinDifficultyBlocks()) + { + // Special difficulty rule for testnet: + // If the new block's timestamp is more than 2* 10 minutes + // then allow mining of a min-difficulty block. + if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2) + return nProofOfWorkLimit; + else + { + // Return the last non-special-min-difficulty-rules-block + const CBlockIndex* pindex = pindexLast; + while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) + pindex = pindex->pprev; + return pindex->nBits; + } + } + return pindexLast->nBits; + } + + // Go back by what we want to be 14 days worth of blocks + const CBlockIndex* pindexFirst = pindexLast; + for (int i = 0; pindexFirst && i < nInterval-1; i++) + pindexFirst = pindexFirst->pprev; + assert(pindexFirst); + + // Limit adjustment step + int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); + LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); + if (nActualTimespan < nTargetTimespan/4) + nActualTimespan = nTargetTimespan/4; + if (nActualTimespan > nTargetTimespan*4) + nActualTimespan = nTargetTimespan*4; + + // Retarget + uint256 bnNew; + uint256 bnOld; + bnNew.SetCompact(pindexLast->nBits); + bnOld = bnNew; + bnNew *= nActualTimespan; + bnNew /= nTargetTimespan; + + if (bnNew > Params().ProofOfWorkLimit()) + bnNew = Params().ProofOfWorkLimit(); + + /// debug print + LogPrintf("GetNextWorkRequired RETARGET\n"); + LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); + LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); + LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); + + return bnNew.GetCompact(); +} + +bool CheckProofOfWork(uint256 hash, unsigned int nBits) +{ + bool fNegative; + bool fOverflow; + uint256 bnTarget; + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + + // Check range + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) + return error("CheckProofOfWork() : nBits below minimum work"); + + // Check proof of work matches claimed amount + if (hash > bnTarget) + return error("CheckProofOfWork() : hash doesn't match nBits"); + + return true; +} + +// +// minimum amount of work that could possibly be required nTime after +// minimum work required was nBase +// +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) +{ + const uint256 &bnLimit = Params().ProofOfWorkLimit(); + // Testnet has min-difficulty blocks + // after nTargetSpacing*2 time between blocks: + if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2) + return bnLimit.GetCompact(); + + uint256 bnResult; + bnResult.SetCompact(nBase); + while (nTime > 0 && bnResult < bnLimit) + { + // Maximum 400% adjustment... + bnResult *= 4; + // ... in best-case exactly 4-times-normal target time + nTime -= nTargetTimespan*4; + } + if (bnResult > bnLimit) + bnResult = bnLimit; + return bnResult.GetCompact(); +} diff --git a/src/pow.h b/src/pow.h new file mode 100644 index 0000000000..0ce5b48766 --- /dev/null +++ b/src/pow.h @@ -0,0 +1,23 @@ + +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 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 BITCOIN_POW_H +#define BITCOIN_POW_H + +#include + +class CBlockIndex; +class CBlockHeader; +class uint256; + +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); + +/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ +bool CheckProofOfWork(uint256 hash, unsigned int nBits); +/** Calculate the minimum amount of work a received block needs, without knowing its direct parent */ +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); + +#endif diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index a1410f0e41..f60070eb5b 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -9,6 +9,7 @@ #include "net.h" #include "main.h" #include "miner.h" +#include "pow.h" #ifdef ENABLE_WALLET #include "db.h" #include "wallet.h" diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 3a45844411..d512053051 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -11,6 +11,7 @@ #include "keystore.h" #include "main.h" #include "net.h" +#include "pow.h" #include "script.h" #include "serialize.h" diff --git a/src/txdb.cpp b/src/txdb.cpp index 4eab8525a5..92137f71ff 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -6,6 +6,7 @@ #include "txdb.h" #include "core.h" +#include "pow.h" #include "uint256.h" #include @@ -212,8 +213,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - if (!pindexNew->CheckIndex()) - return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString()); + if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits)) + return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString()); pcursor->Next(); } else { From fd704c7b2c5ab8b24b1829f000b829d7156b8b3c Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 18:29:34 +0100 Subject: [PATCH 228/336] move pow constants to chainparams --- src/chainparams.cpp | 7 +++++++ src/chainparams.h | 5 +++++ src/pow.cpp | 30 +++++++++++++----------------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index afbae6fc57..eb56af750e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -117,6 +117,8 @@ public: nRejectBlockOutdatedMajority = 950; nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 0; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; // Build the genesis block. Note that the output of the genesis coinbase cannot // be spent as it did not originally exist in the database. @@ -204,6 +206,9 @@ public: nEnforceBlockUpgradeMajority = 51; nRejectBlockOutdatedMajority = 75; nToCheckBlockUpgradeMajority = 100; + nMinerThreads = 0; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; strDataDir = "testnet3"; // Modify the testnet genesis block so the timestamp is valid for a later start. @@ -251,6 +256,8 @@ public: nRejectBlockOutdatedMajority = 950; nToCheckBlockUpgradeMajority = 1000; nMinerThreads = 1; + nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + nTargetSpacing = 10 * 60; bnProofOfWorkLimit = ~uint256(0) >> 1; genesis.nTime = 1296688602; genesis.nBits = 0x207fffff; diff --git a/src/chainparams.h b/src/chainparams.h index c0a6ebda6b..e9774bbfa2 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -70,6 +70,9 @@ public: bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; } /* Make standard checks */ bool RequireStandard() const { return fRequireStandard; } + int64_t TargetTimespan() const { return nTargetTimespan; } + int64_t TargetSpacing() const { return nTargetSpacing; } + int64_t Interval() const { return nTargetTimespan / nTargetSpacing; } const std::string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ @@ -95,6 +98,8 @@ protected: int nEnforceBlockUpgradeMajority; int nRejectBlockOutdatedMajority; int nToCheckBlockUpgradeMajority; + int64_t nTargetTimespan; + int64_t nTargetSpacing; std::string strDataDir; int nMinerThreads; std::vector vSeeds; diff --git a/src/pow.cpp b/src/pow.cpp index 274a5d6f98..952250decd 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -10,10 +10,6 @@ #include "main.h" #include "uint256.h" -static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks -static const int64_t nTargetSpacing = 10 * 60; -static const int64_t nInterval = nTargetTimespan / nTargetSpacing; - unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) { unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); @@ -23,20 +19,20 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return nProofOfWorkLimit; // Only change once per interval - if ((pindexLast->nHeight+1) % nInterval != 0) + if ((pindexLast->nHeight+1) % Params().Interval() != 0) { if (Params().AllowMinDifficultyBlocks()) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. - if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2) + if (pblock->nTime > pindexLast->nTime + Params().TargetSpacing()*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % nInterval != 0 && pindex->nBits == nProofOfWorkLimit) + while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -46,17 +42,17 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // Go back by what we want to be 14 days worth of blocks const CBlockIndex* pindexFirst = pindexLast; - for (int i = 0; pindexFirst && i < nInterval-1; i++) + for (int i = 0; pindexFirst && i < Params().Interval()-1; i++) pindexFirst = pindexFirst->pprev; assert(pindexFirst); // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < nTargetTimespan/4) - nActualTimespan = nTargetTimespan/4; - if (nActualTimespan > nTargetTimespan*4) - nActualTimespan = nTargetTimespan*4; + if (nActualTimespan < Params().TargetTimespan()/4) + nActualTimespan = Params().TargetTimespan()/4; + if (nActualTimespan > Params().TargetTimespan()*4) + nActualTimespan = Params().TargetTimespan()*4; // Retarget uint256 bnNew; @@ -64,14 +60,14 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; bnNew *= nActualTimespan; - bnNew /= nTargetTimespan; + bnNew /= Params().TargetTimespan(); if (bnNew > Params().ProofOfWorkLimit()) bnNew = Params().ProofOfWorkLimit(); /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); + LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan); LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); @@ -104,8 +100,8 @@ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) { const uint256 &bnLimit = Params().ProofOfWorkLimit(); // Testnet has min-difficulty blocks - // after nTargetSpacing*2 time between blocks: - if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2) + // after Params().TargetSpacing()*2 time between blocks: + if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2) return bnLimit.GetCompact(); uint256 bnResult; @@ -115,7 +111,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) // Maximum 400% adjustment... bnResult *= 4; // ... in best-case exactly 4-times-normal target time - nTime -= nTargetTimespan*4; + nTime -= Params().TargetTimespan()*4; } if (bnResult > bnLimit) bnResult = bnLimit; From 6dc90ed8fa34db164fac956eed600b2ba66640a0 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sun, 22 Jun 2014 20:17:15 +0200 Subject: [PATCH 229/336] replace 3 separate calls to WSAGetLastError() with 1 --- src/netbase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 4aa7367f39..3c50174e75 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -337,8 +337,9 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { + int nErr = WSAGetLastError(); // WSAEINVAL is here because some legacy version of winsock uses it - if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL) + if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { struct timeval timeout; timeout.tv_sec = nTimeout / 1000; From 1c750dbd40e23be1f17cf74cd73041a1050dc98d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 5 May 2014 20:32:56 +0200 Subject: [PATCH 230/336] remove -tor compatibility code (only allow -onion) - exit, if -tor option is found and give error to user --- src/init.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ff7a9011a5..585e4ca89a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -560,6 +560,9 @@ bool AppInit2(boost::thread_group& threadGroup) // Check for -debugnet (deprecated) if (GetBoolArg("-debugnet", false)) InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net")); + // Check for -tor - as this is a privacy risk to continue, exit here + if (GetBoolArg("-tor", false)) + return InitError(_("Error: Unsupported argument -tor found, use -onion.")); fBenchmark = GetBoolArg("-benchmark", false); // Checkmempool defaults to true in regtest mode @@ -766,19 +769,15 @@ bool AppInit2(boost::thread_group& threadGroup) } // -onion can override normal proxy, -noonion disables tor entirely - // -tor here is a temporary backwards compatibility measure - if (mapArgs.count("-tor")) - printf("Notice: option -tor has been replaced with -onion and will be removed in a later version.\n"); if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") && - !(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && - (fProxy || mapArgs.count("-onion") || mapArgs.count("-tor"))) { + (fProxy || mapArgs.count("-onion"))) { CService addrOnion; - if (!mapArgs.count("-onion") && !mapArgs.count("-tor")) + if (!mapArgs.count("-onion")) addrOnion = addrProxy; else - addrOnion = mapArgs.count("-onion")?CService(mapArgs["-onion"], 9050):CService(mapArgs["-tor"], 9050); + addrOnion = CService(mapArgs["-onion"], 9050); if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs.count("-onion")?mapArgs["-onion"]:mapArgs["-tor"])); + return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); SetProxy(NET_TOR, addrOnion, 5); SetReachable(NET_TOR); } From 5fbb4c9b58e0ed960d19436bb951b76cae398212 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 16:36:14 +0200 Subject: [PATCH 231/336] [Qt] fix links in about window not opening - closes #4402 --- src/qt/forms/helpmessagedialog.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt/forms/helpmessagedialog.ui b/src/qt/forms/helpmessagedialog.ui index d8ab27c238..81dbd90b12 100644 --- a/src/qt/forms/helpmessagedialog.ui +++ b/src/qt/forms/helpmessagedialog.ui @@ -60,6 +60,9 @@ Qt::PlainText + + true + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse From e9f2460c587e1a7116e6af671bf9987d8825bfb0 Mon Sep 17 00:00:00 2001 From: Drak Date: Tue, 24 Jun 2014 18:06:52 +0100 Subject: [PATCH 232/336] Add dependencies for Mac OSX gitian builds --- doc/release-process.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/release-process.md b/doc/release-process.md index affe6ed13a..d12b41772e 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -52,6 +52,7 @@ Release Process wget 'https://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2' wget 'https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch' -O boost-mingw-gas-cross-compile-2013-03-03.patch wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.0/single/qt-everywhere-opensource-src-5.2.0.tar.gz' + wget 'https://download.qt-project.org/official_releases/qt/5.2/5.2.1/single/qt-everywhere-opensource-src-5.2.1.tar.gz' wget 'https://download.qt-project.org/archive/qt/4.6/qt-everywhere-opensource-src-4.6.4.tar.gz' wget 'https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2' wget 'https://github.com/mingwandroid/toolchain4/archive/10cc648683617cca8bcbeae507888099b41b530c.tar.gz' @@ -100,6 +101,10 @@ Release Process 751c579830d173ef3e6f194e83d18b92ebef6df03289db13ab77a52b6bc86ef0 qt-win64-5.2.0-gitian-r3.zip e2e403e1a08869c7eed4d4293bce13d51ec6a63592918b90ae215a0eceb44cb4 protobuf-win32-2.5.0-gitian-r4.zip a0999037e8b0ef9ade13efd88fee261ba401f5ca910068b7e0cd3262ba667db0 protobuf-win64-2.5.0-gitian-r4.zip + 512bc0622c883e2e0f4cbc3fedfd8c2402d06c004ce6fb32303cc2a6f405b6df osx-native-depends-r3.tar.gz + 927e4b222be6d590b4bc2fc185872a5d0ca5c322adb983764d3ed84be6bdbc81 osx-depends-r4.tar.gz + ec95abef1df2b096a970359787c01d8c45e2a4475b7ae34e12c022634fbdba8a osx-depends-qt-5.2.1-r4.tar.gz + Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32: From e3aedbae9be362d11c420a917959156adf73e2f3 Mon Sep 17 00:00:00 2001 From: Whit J Date: Tue, 24 Jun 2014 17:23:05 -0700 Subject: [PATCH 233/336] Consistent lettering --- src/qt/askpassphrasedialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 2a6d6abc35..a448d5a9a0 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -37,7 +37,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : case Encrypt: // Ask passphrase x2 ui->passLabel1->hide(); ui->passEdit1->hide(); - ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of 10 or more random characters, or eight or more words.")); + ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of ten or more random characters, or eight or more words.")); setWindowTitle(tr("Encrypt wallet")); break; case Unlock: // Ask passphrase From b79f59b9952b071128d42759cc06425dffe041d0 Mon Sep 17 00:00:00 2001 From: Drak Date: Tue, 24 Jun 2014 23:52:05 +0100 Subject: [PATCH 234/336] Update .gitignore Removing old file ignores so they show up in `git status` --- .gitignore | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 85ddf3871f..564fe68fd9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,10 +13,10 @@ autom4te.cache/ config.log config.status configure -src/bitcoin-config.h -src/bitcoin-config.h.in +src/config/bitcoin-config.h +src/config/bitcoin-config.h.in +src/config/stamp-h1 src/build-aux/ -src/stamp-h1 share/setup.nsi share/qt/Info.plist From 14f888ca804386b111b07e8988753d67f507ba30 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 19 Jun 2014 15:08:37 +0200 Subject: [PATCH 235/336] Move network-time related functions to timedata.cpp/h The network time-offset-mangement functions from util.cpp are moved to timedata.(cpp|h). This breaks the dependency of util on netbase. --- src/Makefile.am | 2 + src/addrman.h | 1 + src/alert.cpp | 1 + src/qt/transactiondesc.cpp | 1 + src/qt/transactionrecord.cpp | 1 + src/rpcmisc.cpp | 1 + src/rpcnet.cpp | 1 + src/rpcwallet.cpp | 1 + src/timedata.cpp | 91 ++++++++++++++++++++++++++++++++++++ src/timedata.h | 17 +++++++ src/util.cpp | 77 ------------------------------ src/util.h | 4 -- src/wallet.cpp | 1 + 13 files changed, 118 insertions(+), 81 deletions(-) create mode 100644 src/timedata.cpp create mode 100644 src/timedata.h diff --git a/src/Makefile.am b/src/Makefile.am index 7e7fa0c3ca..cd54b0496a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,6 +80,7 @@ BITCOIN_CORE_H = \ serialize.h \ sync.h \ threadsafety.h \ + timedata.h \ tinyformat.h \ txdb.h \ txmempool.h \ @@ -129,6 +130,7 @@ libbitcoin_server_a_SOURCES = \ rpcnet.cpp \ rpcrawtransaction.cpp \ rpcserver.cpp \ + timedata.cpp \ txdb.cpp \ txmempool.cpp \ $(JSON_H) \ diff --git a/src/addrman.h b/src/addrman.h index 5328a93b45..c4c296560e 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -8,6 +8,7 @@ #include "netbase.h" #include "protocol.h" #include "sync.h" +#include "timedata.h" #include "util.h" #include diff --git a/src/alert.cpp b/src/alert.cpp index 638f0d7a1c..258a2b52c4 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -8,6 +8,7 @@ #include "chainparams.h" #include "key.h" #include "net.h" +#include "timedata.h" #include "ui_interface.h" #include "util.h" diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 61da3373fd..e48dbcac9d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -12,6 +12,7 @@ #include "main.h" #include "paymentserver.h" #include "transactionrecord.h" +#include "timedata.h" #include "ui_interface.h" #include "wallet.h" diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 5a3728f498..eec2b57e8c 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -5,6 +5,7 @@ #include "transactionrecord.h" #include "base58.h" +#include "timedata.h" #include "wallet.h" #include diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 5181aa23d8..2694e2bcf1 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -9,6 +9,7 @@ #include "net.h" #include "netbase.h" #include "rpcserver.h" +#include "timedata.h" #include "util.h" #ifdef ENABLE_WALLET #include "wallet.h" diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 6fc86eedfb..a54872ccc4 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -9,6 +9,7 @@ #include "netbase.h" #include "protocol.h" #include "sync.h" +#include "timedata.h" #include "util.h" #include diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index f376ab6b63..4f27cef087 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -8,6 +8,7 @@ #include "init.h" #include "net.h" #include "netbase.h" +#include "timedata.h" #include "util.h" #include "wallet.h" #include "walletdb.h" diff --git a/src/timedata.cpp b/src/timedata.cpp new file mode 100644 index 0000000000..8a095d26dc --- /dev/null +++ b/src/timedata.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "timedata.h" + +#include "netbase.h" +#include "sync.h" +#include "ui_interface.h" +#include "util.h" + +#include + +using namespace std; + +static CCriticalSection cs_nTimeOffset; +static int64_t nTimeOffset = 0; + +// +// "Never go to sea with two chronometers; take one or three." +// Our three time sources are: +// - System clock +// - Median of other nodes clocks +// - The user (asking the user to fix the system clock if the first two disagree) +// +// +int64_t GetTimeOffset() +{ + LOCK(cs_nTimeOffset); + return nTimeOffset; +} + +int64_t GetAdjustedTime() +{ + return GetTime() + GetTimeOffset(); +} + +void AddTimeData(const CNetAddr& ip, int64_t nTime) +{ + int64_t nOffsetSample = nTime - GetTime(); + + LOCK(cs_nTimeOffset); + // Ignore duplicates + static set setKnown; + if (!setKnown.insert(ip).second) + return; + + // Add data + static CMedianFilter vTimeOffsets(200,0); + vTimeOffsets.input(nOffsetSample); + LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); + if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) + { + int64_t nMedian = vTimeOffsets.median(); + std::vector vSorted = vTimeOffsets.sorted(); + // Only let other nodes change our time by so much + if (abs64(nMedian) < 70 * 60) + { + nTimeOffset = nMedian; + } + else + { + nTimeOffset = 0; + + static bool fDone; + if (!fDone) + { + // If nobody has a time different than ours but within 5 minutes of ours, give a warning + bool fMatch = false; + BOOST_FOREACH(int64_t nOffset, vSorted) + if (nOffset != 0 && abs64(nOffset) < 5 * 60) + fMatch = true; + + if (!fMatch) + { + fDone = true; + string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly."); + strMiscWarning = strMessage; + LogPrintf("*** %s\n", strMessage); + uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); + } + } + } + if (fDebug) { + BOOST_FOREACH(int64_t n, vSorted) + LogPrintf("%+d ", n); + LogPrintf("| "); + } + LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); + } +} diff --git a/src/timedata.h b/src/timedata.h new file mode 100644 index 0000000000..0e7bdc2c1f --- /dev/null +++ b/src/timedata.h @@ -0,0 +1,17 @@ +// Copyright (c) 2014 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 BITCOIN_TIMEDATA_H +#define BITCOIN_TIMEDATA_H + +#include + +class CNetAddr; + +/* Functions to keep track of adjusted P2P time */ +int64_t GetTimeOffset(); +int64_t GetAdjustedTime(); +void AddTimeData(const CNetAddr& ip, int64_t nTime); + +#endif diff --git a/src/util.cpp b/src/util.cpp index 30590912ff..a19c015da6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6,7 +6,6 @@ #include "util.h" #include "chainparams.h" -#include "netbase.h" #include "sync.h" #include "ui_interface.h" #include "uint256.h" @@ -1157,13 +1156,6 @@ void ShrinkDebugFile() fclose(file); } -// -// "Never go to sea with two chronometers; take one or three." -// Our three time sources are: -// - System clock -// - Median of other nodes clocks -// - The user (asking the user to fix the system clock if the first two disagree) -// static int64_t nMockTime = 0; // For unit testing int64_t GetTime() @@ -1178,75 +1170,6 @@ void SetMockTime(int64_t nMockTimeIn) nMockTime = nMockTimeIn; } -static CCriticalSection cs_nTimeOffset; -static int64_t nTimeOffset = 0; - -int64_t GetTimeOffset() -{ - LOCK(cs_nTimeOffset); - return nTimeOffset; -} - -int64_t GetAdjustedTime() -{ - return GetTime() + GetTimeOffset(); -} - -void AddTimeData(const CNetAddr& ip, int64_t nTime) -{ - int64_t nOffsetSample = nTime - GetTime(); - - LOCK(cs_nTimeOffset); - // Ignore duplicates - static set setKnown; - if (!setKnown.insert(ip).second) - return; - - // Add data - static CMedianFilter vTimeOffsets(200,0); - vTimeOffsets.input(nOffsetSample); - LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); - if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) - { - int64_t nMedian = vTimeOffsets.median(); - std::vector vSorted = vTimeOffsets.sorted(); - // Only let other nodes change our time by so much - if (abs64(nMedian) < 70 * 60) - { - nTimeOffset = nMedian; - } - else - { - nTimeOffset = 0; - - static bool fDone; - if (!fDone) - { - // If nobody has a time different than ours but within 5 minutes of ours, give a warning - bool fMatch = false; - BOOST_FOREACH(int64_t nOffset, vSorted) - if (nOffset != 0 && abs64(nOffset) < 5 * 60) - fMatch = true; - - if (!fMatch) - { - fDone = true; - string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin will not work properly."); - strMiscWarning = strMessage; - LogPrintf("*** %s\n", strMessage); - uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); - } - } - } - if (fDebug) { - BOOST_FOREACH(int64_t n, vSorted) - LogPrintf("%+d ", n); - LogPrintf("| "); - } - LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); - } -} - uint32_t insecure_rand_Rz = 11; uint32_t insecure_rand_Rw = 11; void seed_insecure_rand(bool fDeterministic) diff --git a/src/util.h b/src/util.h index 5eb6f03826..6057c72e66 100644 --- a/src/util.h +++ b/src/util.h @@ -32,7 +32,6 @@ #include #include -class CNetAddr; class uint256; static const int64_t COIN = 100000000; @@ -191,11 +190,8 @@ uint64_t GetRand(uint64_t nMax); uint256 GetRandHash(); int64_t GetTime(); void SetMockTime(int64_t nMockTimeIn); -int64_t GetAdjustedTime(); -int64_t GetTimeOffset(); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); -void AddTimeData(const CNetAddr& ip, int64_t nTime); void runCommand(std::string strCommand); diff --git a/src/wallet.cpp b/src/wallet.cpp index e74980e9e7..f6fd6e958d 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -9,6 +9,7 @@ #include "checkpoints.h" #include "coincontrol.h" #include "net.h" +#include "timedata.h" #include #include From 84ce18ca9339901f65d77a5821eb65f771316558 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 19 Jun 2014 15:10:04 +0200 Subject: [PATCH 236/336] Remove unnecessary dependencies for bitcoin-cli This commit removes all the unnecessary dependencies (key, core, netbase, sync, ...) from bitcoin-cli. To do this it shards the chain parameters into BaseParams, which contains just the RPC port and data directory (as used by utils and bitcoin-cli) and Params, with the rest. --- src/Makefile.am | 58 +++++++++++++------ src/Makefile.qt.include | 4 +- src/Makefile.qttest.include | 2 +- src/Makefile.test.include | 2 +- src/bitcoin-cli.cpp | 9 ++- src/chainparams.cpp | 36 ++++-------- src/chainparams.h | 19 ++---- src/chainparamsbase.cpp | 93 ++++++++++++++++++++++++++++++ src/chainparamsbase.h | 52 +++++++++++++++++ src/checkpoints.cpp | 4 +- src/qt/bitcoin.cpp | 2 +- src/qt/paymentserver.cpp | 8 +-- src/qt/test/paymentservertests.cpp | 1 + src/rpcmining.cpp | 2 +- src/rpcmisc.cpp | 2 +- src/rpcserver.cpp | 2 +- src/test/base58_tests.cpp | 12 ++-- src/test/test_bitcoin.cpp | 1 + src/util.cpp | 12 ++-- 19 files changed, 232 insertions(+), 89 deletions(-) create mode 100644 src/chainparamsbase.cpp create mode 100644 src/chainparamsbase.h diff --git a/src/Makefile.am b/src/Makefile.am index cd54b0496a..2d2ae2a4c1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,10 +20,19 @@ endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +LIBBITCOIN_SERVER=libbitcoin_server.a +LIBBITCOIN_WALLET=libbitcoin_wallet.a +LIBBITCOIN_COMMON=libbitcoin_common.a +LIBBITCOIN_CLI=libbitcoin_cli.a +LIBBITCOIN_UTIL=libbitcoin_util.a +LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a +LIBBITCOINQT=qt/libbitcoinqt.a + noinst_LIBRARIES = \ libbitcoin_server.a \ libbitcoin_common.a \ libbitcoin_cli.a \ + libbitcoin_util.a \ crypto/libbitcoin_crypto.a if ENABLE_WALLET BITCOIN_INCLUDES += $(BDB_CPPFLAGS) @@ -50,6 +59,7 @@ BITCOIN_CORE_H = \ base58.h \ bloom.h \ chainparams.h \ + chainparamsbase.h \ checkpoints.h \ checkqueue.h \ clientversion.h \ @@ -107,8 +117,9 @@ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ $(abs_top_srcdir) -libbitcoin_common_a-version.$(OBJEXT): obj/build.h +libbitcoin_util_a-version.$(OBJEXT): obj/build.h +# server: shared between bitcoind and bitcoin-qt libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_server_a_SOURCES = \ addrman.cpp \ @@ -136,6 +147,8 @@ libbitcoin_server_a_SOURCES = \ $(JSON_H) \ $(BITCOIN_CORE_H) +# wallet: shared between bitcoind and bitcoin-qt, but only linked +# when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_wallet_a_SOURCES = \ db.cpp \ @@ -146,6 +159,7 @@ libbitcoin_wallet_a_SOURCES = \ walletdb.cpp \ $(BITCOIN_CORE_H) +# crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ @@ -156,6 +170,7 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.h \ crypto/ripemd160.h +# common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ base58.cpp \ @@ -166,8 +181,16 @@ libbitcoin_common_a_SOURCES = \ key.cpp \ netbase.cpp \ protocol.cpp \ - rpcprotocol.cpp \ script.cpp \ + $(BITCOIN_CORE_H) + +# util: shared between all executables. +# This library *must* be included to make sure that the glibc +# backward-compatibility objects and their sanity checks are linked. +libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) +libbitcoin_util_a_SOURCES = \ + chainparamsbase.cpp \ + rpcprotocol.cpp \ sync.cpp \ util.cpp \ version.cpp \ @@ -176,22 +199,24 @@ libbitcoin_common_a_SOURCES = \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT -libbitcoin_common_a_SOURCES += compat/glibc_compat.cpp -libbitcoin_common_a_SOURCES += compat/glibcxx_compat.cpp +libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp +libbitcoin_util_a_SOURCES += compat/glibcxx_compat.cpp endif +# cli: shared between bitcoin-cli and bitcoin-qt libbitcoin_cli_a_SOURCES = \ rpcclient.cpp \ $(BITCOIN_CORE_H) -nodist_libbitcoin_common_a_SOURCES = $(srcdir)/obj/build.h +nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # bitcoind_LDADD = \ - libbitcoin_server.a \ - libbitcoin_common.a \ - crypto/libbitcoin_crypto.a \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBMEMENV) if ENABLE_WALLET @@ -209,11 +234,13 @@ bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES) # bitcoin-cli binary # bitcoin_cli_LDADD = \ - libbitcoin_cli.a \ - libbitcoin_common.a \ - crypto/libbitcoin_crypto.a \ + $(LIBBITCOIN_CLI) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) \ $(BOOST_LIBS) -bitcoin_cli_SOURCES = bitcoin-cli.cpp +bitcoin_cli_SOURCES = \ + bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # @@ -244,13 +271,6 @@ clean-local: @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( @@ -60,12 +60,11 @@ static bool AppInitRPC(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } - // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) - if (!SelectParamsFromCommandLine()) { + // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) + if (!SelectBaseParamsFromCommandLine()) { fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } - if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n"; @@ -104,7 +103,7 @@ Object CallRPC(const string& strMethod, const Array& params) bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started do { - bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))); + bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort()))); if (fConnected) break; if (fWait) MilliSleep(1000); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index eb56af750e..63067a153d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -99,7 +99,7 @@ unsigned int pnSeed[] = class CMainParams : public CChainParams { public: CMainParams() { - networkID = CChainParams::MAIN; + networkID = CBaseChainParams::MAIN; strNetworkID = "main"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -110,7 +110,6 @@ public: pchMessageStart[3] = 0xd9; vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; - nRPCPort = 8332; bnProofOfWorkLimit = ~uint256(0) >> 32; nSubsidyHalvingInterval = 210000; nEnforceBlockUpgradeMajority = 750; @@ -191,7 +190,7 @@ static CMainParams mainParams; class CTestNetParams : public CMainParams { public: CTestNetParams() { - networkID = CChainParams::TESTNET; + networkID = CBaseChainParams::TESTNET; strNetworkID = "test"; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -202,14 +201,12 @@ public: pchMessageStart[3] = 0x07; vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"); nDefaultPort = 18333; - nRPCPort = 18332; nEnforceBlockUpgradeMajority = 51; nRejectBlockOutdatedMajority = 75; nToCheckBlockUpgradeMajority = 100; nMinerThreads = 0; nTargetTimespan = 14 * 24 * 60 * 60; // two weeks nTargetSpacing = 10 * 60; - strDataDir = "testnet3"; // Modify the testnet genesis block so the timestamp is valid for a later start. genesis.nTime = 1296688602; @@ -245,7 +242,7 @@ static CTestNetParams testNetParams; class CRegTestParams : public CTestNetParams { public: CRegTestParams() { - networkID = CChainParams::REGTEST; + networkID = CBaseChainParams::REGTEST; strNetworkID = "regtest"; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; @@ -264,7 +261,6 @@ public: genesis.nNonce = 2; hashGenesisBlock = genesis.GetHash(); nDefaultPort = 18444; - strDataDir = "regtest"; assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. @@ -279,21 +275,23 @@ public: }; static CRegTestParams regTestParams; -static CChainParams *pCurrentParams = &mainParams; +static CChainParams *pCurrentParams = 0; const CChainParams &Params() { + assert(pCurrentParams); return *pCurrentParams; } -void SelectParams(CChainParams::Network network) { +void SelectParams(CBaseChainParams::Network network) { + SelectBaseParams(network); switch (network) { - case CChainParams::MAIN: + case CBaseChainParams::MAIN: pCurrentParams = &mainParams; break; - case CChainParams::TESTNET: + case CBaseChainParams::TESTNET: pCurrentParams = &testNetParams; break; - case CChainParams::REGTEST: + case CBaseChainParams::REGTEST: pCurrentParams = ®TestParams; break; default: @@ -303,19 +301,9 @@ void SelectParams(CChainParams::Network network) { } bool SelectParamsFromCommandLine() { - bool fRegTest = GetBoolArg("-regtest", false); - bool fTestNet = GetBoolArg("-testnet", false); - - if (fTestNet && fRegTest) { + if (!SelectBaseParamsFromCommandLine()) return false; - } - if (fRegTest) { - SelectParams(CChainParams::REGTEST); - } else if (fTestNet) { - SelectParams(CChainParams::TESTNET); - } else { - SelectParams(CChainParams::MAIN); - } + SelectParams(BaseParams().NetworkID()); return true; } diff --git a/src/chainparams.h b/src/chainparams.h index e9774bbfa2..446256ba82 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -7,6 +7,7 @@ #define BITCOIN_CHAIN_PARAMS_H #include "core.h" +#include "chainparamsbase.h" #include "protocol.h" #include "uint256.h" @@ -29,14 +30,6 @@ struct CDNSSeedData { class CChainParams { public: - enum Network { - MAIN, - TESTNET, - REGTEST, - - MAX_NETWORK_TYPES - }; - enum Base58Type { PUBKEY_ADDRESS, SCRIPT_ADDRESS, @@ -73,17 +66,15 @@ public: int64_t TargetTimespan() const { return nTargetTimespan; } int64_t TargetSpacing() const { return nTargetSpacing; } int64_t Interval() const { return nTargetTimespan / nTargetSpacing; } - const std::string& DataDir() const { return strDataDir; } /* Make miner stop after a block is found. In RPC, don't return * until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } - Network NetworkID() const { return networkID; } + CBaseChainParams::Network NetworkID() const { return networkID; } /* Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } const std::vector& DNSSeeds() const { return vSeeds; } const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } const std::vector& FixedSeeds() const { return vFixedSeeds; } - int RPCPort() const { return nRPCPort; } protected: CChainParams() {} @@ -92,7 +83,6 @@ protected: // Raw pub key bytes for the broadcast alert signing key. std::vector vAlertPubKey; int nDefaultPort; - int nRPCPort; uint256 bnProofOfWorkLimit; int nSubsidyHalvingInterval; int nEnforceBlockUpgradeMajority; @@ -100,11 +90,10 @@ protected: int nToCheckBlockUpgradeMajority; int64_t nTargetTimespan; int64_t nTargetSpacing; - std::string strDataDir; int nMinerThreads; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; - Network networkID; + CBaseChainParams::Network networkID; std::string strNetworkID; CBlock genesis; std::vector vFixedSeeds; @@ -123,7 +112,7 @@ protected: const CChainParams &Params(); /** Sets the params returned by Params() to those for the given network. */ -void SelectParams(CChainParams::Network network); +void SelectParams(CBaseChainParams::Network network); /** * Looks for -regtest or -testnet and then calls SelectParams as appropriate. diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp new file mode 100644 index 0000000000..19a9e72cc9 --- /dev/null +++ b/src/chainparamsbase.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "chainparamsbase.h" + +#include "assert.h" +#include "util.h" + +#include + +using namespace boost::assign; + +// +// Main network +// + +class CBaseMainParams : public CBaseChainParams { +public: + CBaseMainParams() { + networkID = CBaseChainParams::MAIN; + nRPCPort = 8332; + } +}; +static CBaseMainParams mainParams; + +// +// Testnet (v3) +// +class CBaseTestNetParams : public CBaseMainParams { +public: + CBaseTestNetParams() { + networkID = CBaseChainParams::TESTNET; + nRPCPort = 18332; + strDataDir = "testnet3"; + } +}; +static CBaseTestNetParams testNetParams; + +// +// Regression test +// +class CBaseRegTestParams : public CBaseTestNetParams { +public: + CBaseRegTestParams() { + networkID = CBaseChainParams::REGTEST; + strDataDir = "regtest"; + } +}; +static CBaseRegTestParams regTestParams; + +static CBaseChainParams *pCurrentBaseParams = 0; + +const CBaseChainParams &BaseParams() { + assert(pCurrentBaseParams); + return *pCurrentBaseParams; +} + +void SelectBaseParams(CBaseChainParams::Network network) { + switch (network) { + case CBaseChainParams::MAIN: + pCurrentBaseParams = &mainParams; + break; + case CBaseChainParams::TESTNET: + pCurrentBaseParams = &testNetParams; + break; + case CBaseChainParams::REGTEST: + pCurrentBaseParams = ®TestParams; + break; + default: + assert(false && "Unimplemented network"); + return; + } +} + +bool SelectBaseParamsFromCommandLine() { + bool fRegTest = GetBoolArg("-regtest", false); + bool fTestNet = GetBoolArg("-testnet", false); + + if (fTestNet && fRegTest) { + return false; + } + + if (fRegTest) { + SelectBaseParams(CBaseChainParams::REGTEST); + } else if (fTestNet) { + SelectBaseParams(CBaseChainParams::TESTNET); + } else { + SelectBaseParams(CBaseChainParams::MAIN); + } + return true; +} diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h new file mode 100644 index 0000000000..4a3b268909 --- /dev/null +++ b/src/chainparamsbase.h @@ -0,0 +1,52 @@ +// Copyright (c) 2014 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 BITCOIN_CHAIN_PARAMS_BASE_H +#define BITCOIN_CHAIN_PARAMS_BASE_H + +#include +#include + +/** + * CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind) + * of a given instance of the Bitcoin system. + */ +class CBaseChainParams +{ +public: + enum Network { + MAIN, + TESTNET, + REGTEST, + + MAX_NETWORK_TYPES + }; + + const std::string& DataDir() const { return strDataDir; } + int RPCPort() const { return nRPCPort; } + Network NetworkID() const { return networkID; } +protected: + CBaseChainParams() {} + + int nRPCPort; + std::string strDataDir; + Network networkID; +}; + +/** + * Return the currently selected parameters. This won't change after app startup + * outside of the unit tests. + */ +const CBaseChainParams &BaseParams(); + +/** Sets the params returned by Params() to those for the given network. */ +void SelectBaseParams(CBaseChainParams::Network network); + +/** + * Looks for -regtest or -testnet and then calls SelectParams as appropriate. + * Returns false if an invalid combination is given. + */ +bool SelectBaseParamsFromCommandLine(); + +#endif diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 926949e06a..75ac418916 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -83,9 +83,9 @@ namespace Checkpoints }; const CCheckpointData &Checkpoints() { - if (Params().NetworkID() == CChainParams::TESTNET) + if (Params().NetworkID() == CBaseChainParams::TESTNET) return dataTestnet; - else if (Params().NetworkID() == CChainParams::MAIN) + else if (Params().NetworkID() == CBaseChainParams::MAIN) return data; else return dataRegtest; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 76dddb103c..89305e9f35 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -546,7 +546,7 @@ int main(int argc, char *argv[]) if (!PaymentServer::ipcParseCommandLine(argc, argv)) exit(0); #endif - bool isaTestNet = Params().NetworkID() != CChainParams::MAIN; + bool isaTestNet = Params().NetworkID() != CBaseChainParams::MAIN; // Allow for separate UI settings for testnets if (isaTestNet) QApplication::setApplicationName(QAPP_APP_NAME_TESTNET); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 49923a1afc..fbb11617fe 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -199,10 +199,10 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { CBitcoinAddress address(r.address.toStdString()); - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if (!address.IsValid()) { - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); } } } @@ -214,9 +214,9 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) if (readPaymentRequest(arg, request)) { if (request.getDetails().network() == "main") - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); else - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); } } else diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 7dee7a9cda..e92a7d2b1a 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -56,6 +56,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vectorGetOldestKeyPoolTime())); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 93da81e429..c5d09cf577 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -600,7 +600,7 @@ void StartRPCThreads() std::vector vEndpoints; bool bBindAny = false; - int defaultPort = GetArg("-rpcport", Params().RPCPort()); + int defaultPort = GetArg("-rpcport", BaseParams().RPCPort()); if (!mapArgs.count("-rpcallowip")) // Default to loopback if not allowing external IPs { vEndpoints.push_back(ip::tcp::endpoint(asio::ip::address_v6::loopback(), defaultPort)); diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index b81a19cfd8..0ac3e9a363 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -142,9 +142,9 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); else - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if(isPrivkey) { bool isCompressed = find_value(metadata, "isCompressed").get_bool(); @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); } } - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); } // Goal: check that generated keys match test vectors @@ -198,9 +198,9 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) - SelectParams(CChainParams::TESTNET); + SelectParams(CBaseChainParams::TESTNET); else - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); if(isPrivkey) { bool isCompressed = find_value(metadata, "isCompressed").get_bool(); @@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) CTxDestination nodest = CNoDestination(); BOOST_CHECK(!dummyAddr.Set(nodest)); - SelectParams(CChainParams::MAIN); + SelectParams(CBaseChainParams::MAIN); } // Goal: check that base58 parsing code is robust against a variety of corrupted data diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 2d993e24db..8cae0a4c34 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -31,6 +31,7 @@ struct TestingSetup { TestingSetup() { fPrintToDebugLog = false; // don't want to write to debug.log file + SelectParams(CBaseChainParams::MAIN); noui_connect(); #ifdef ENABLE_WALLET bitdb.MakeMock(); diff --git a/src/util.cpp b/src/util.cpp index a19c015da6..7a0e2cc800 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5,7 +5,7 @@ #include "util.h" -#include "chainparams.h" +#include "chainparamsbase.h" #include "sync.h" #include "ui_interface.h" #include "uint256.h" @@ -918,7 +918,7 @@ boost::filesystem::path GetDefaultDataDir() #endif } -static boost::filesystem::path pathCached[CChainParams::MAX_NETWORK_TYPES+1]; +static boost::filesystem::path pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1]; static CCriticalSection csPathCached; const boost::filesystem::path &GetDataDir(bool fNetSpecific) @@ -927,8 +927,8 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) LOCK(csPathCached); - int nNet = CChainParams::MAX_NETWORK_TYPES; - if (fNetSpecific) nNet = Params().NetworkID(); + int nNet = CBaseChainParams::MAX_NETWORK_TYPES; + if (fNetSpecific) nNet = BaseParams().NetworkID(); fs::path &path = pathCached[nNet]; @@ -947,7 +947,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) path = GetDefaultDataDir(); } if (fNetSpecific) - path /= Params().DataDir(); + path /= BaseParams().DataDir(); fs::create_directories(path); @@ -956,7 +956,7 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) void ClearDatadirCache() { - std::fill(&pathCached[0], &pathCached[CChainParams::MAX_NETWORK_TYPES+1], + std::fill(&pathCached[0], &pathCached[CBaseChainParams::MAX_NETWORK_TYPES+1], boost::filesystem::path()); } From 75c82d4923174a126e1b87be6a43f274d2cc4c9b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 25 Jun 2014 10:03:00 +0200 Subject: [PATCH 237/336] Move coins.cpp and keystore.cpp to libbitcoin_common Prepare for introduction of `bitcoin-tx` tool. --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 2d2ae2a4c1..3643e60201 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -126,9 +126,7 @@ libbitcoin_server_a_SOURCES = \ alert.cpp \ bloom.cpp \ checkpoints.cpp \ - coins.cpp \ init.cpp \ - keystore.cpp \ leveldbwrapper.cpp \ main.cpp \ miner.cpp \ @@ -173,12 +171,14 @@ crypto_libbitcoin_crypto_a_SOURCES = \ # common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_common_a_SOURCES = \ - base58.cpp \ allocators.cpp \ + base58.cpp \ chainparams.cpp \ + coins.cpp \ core.cpp \ hash.cpp \ key.cpp \ + keystore.cpp \ netbase.cpp \ protocol.cpp \ script.cpp \ From 8969828d069e4e55108618a493749535edc12ec7 Mon Sep 17 00:00:00 2001 From: gubatron Date: Sat, 7 Jun 2014 02:20:22 -0400 Subject: [PATCH 238/336] [Qt] New status bar Unit Display Control and related changes. - New status bar control shows the current Unit of Display. When clicked (left,or right button) it shows a context menu that allows the user to switch the current Unit of Display (BTC, mBTC, uBTC) - Recent Requests and Transaction Table headers are now updated when unit of display is changed, because their "Amount" column now displays the current unit of display. - Takes care of issue #3970 Units in transaction export csv file. - Small refactors for reusability. - Demo Video https://www.youtube.com/watch?v=wwcr0Yh68go&list=UUG3jF2hgofmLWP0tRPisQAQ - changes after Diapolo's feedback. Have not been able to build after last pool, issues with boost on MacOSX, will test on Ubuntu these changes. - removed return statement on switch - renamed onDisplayUnitsChanged(int) to updateDisplayUnit(int) - now getAmountColumnTitle(int unit) takes a simple unit parameter. moved to BitcoinUnits. --- src/qt/bitcoingui.cpp | 78 +++++++++++++++++++++++++++++ src/qt/bitcoingui.h | 37 ++++++++++++++ src/qt/bitcoinunits.cpp | 10 ++++ src/qt/bitcoinunits.h | 2 + src/qt/optionsmodel.cpp | 17 +++++-- src/qt/optionsmodel.h | 2 + src/qt/recentrequeststablemodel.cpp | 27 +++++++++- src/qt/recentrequeststablemodel.h | 6 +++ src/qt/transactiontablemodel.cpp | 11 +++- src/qt/transactiontablemodel.h | 2 + src/qt/transactionview.cpp | 2 +- 11 files changed, 187 insertions(+), 7 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 30f5ec8939..f2fb8c877e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +51,8 @@ #include #include + + #if QT_VERSION < 0x050000 #include #include @@ -156,10 +160,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks); frameBlocksLayout->setContentsMargins(3,0,3,0); frameBlocksLayout->setSpacing(3); + unitDisplayControl = new UnitDisplayStatusBarControl(); labelEncryptionIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(unitDisplayControl); + frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelEncryptionIcon); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelConnectionsIcon); @@ -420,6 +427,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel) walletFrame->setClientModel(clientModel); } #endif + + this->unitDisplayControl->setOptionsModel(clientModel->getOptionsModel()); } } @@ -1000,3 +1009,72 @@ void BitcoinGUI::unsubscribeFromCoreSignals() // Disconnect signals from client uiInterface.ThreadSafeMessageBox.disconnect(boost::bind(ThreadSafeMessageBox, this, _1, _2, _3)); } + +UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel() +{ + optionsModel = 0; + createContextMenu(); + setStyleSheet("font:11pt; color: #333333"); + setToolTip(tr("Unit to show amounts in. Click to select another unit.")); +} + +/** So that it responds to left-button clicks */ +void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) +{ + onDisplayUnitsClicked(event->pos()); +} + +/** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */ +void UnitDisplayStatusBarControl::createContextMenu() +{ + menu = new QMenu(); + foreach(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + { + QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this); + menuAction->setData(QVariant(u)); + menu->addAction(menuAction); + } + connect(menu,SIGNAL(triggered(QAction*)),this,SLOT(onMenuSelection(QAction*))); + + // what happens on right click. + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(onDisplayUnitsClicked(const QPoint&))); +} + +/** Lets the control know about the Options Model (and its signals) */ +void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel) +{ + if (optionsModel) + { + this->optionsModel = optionsModel; + + // be aware of a display unit change reported by the OptionsModel object. + connect(optionsModel,SIGNAL(displayUnitChanged(int)),this,SLOT(updateDisplayUnit(int))); + + // initialize the display units label with the current value in the model. + updateDisplayUnit(optionsModel->getDisplayUnit()); + } +} + +/** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ +void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits) +{ + setText(BitcoinUnits::name(newUnits)); +} + +/** Shows context menu with Display Unit options by the mouse coordinates */ +void UnitDisplayStatusBarControl::onDisplayUnitsClicked(const QPoint& point) +{ + QPoint globalPos = mapToGlobal(point); + menu->exec(globalPos); +} + +/** Tells underlying optionsModel to update its current display unit. */ +void UnitDisplayStatusBarControl::onMenuSelection(QAction* action) +{ + if (action) + { + optionsModel->setDisplayUnit(action->data()); + } +} + diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index e7a842df99..705e629a69 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -9,12 +9,16 @@ #include "config/bitcoin-config.h" #endif +#include #include #include +#include +#include #include class ClientModel; class Notificator; +class OptionsModel; class RPCConsole; class SendCoinsRecipient; class WalletFrame; @@ -22,9 +26,13 @@ class WalletModel; class CWallet; +class UnitDisplayStatusBarControl; + QT_BEGIN_NAMESPACE class QAction; class QLabel; +class QMenu; +class QPoint; class QProgressBar; class QProgressDialog; QT_END_NAMESPACE @@ -69,6 +77,7 @@ private: ClientModel *clientModel; WalletFrame *walletFrame; + UnitDisplayStatusBarControl *unitDisplayControl; QLabel *labelEncryptionIcon; QLabel *labelConnectionsIcon; QLabel *labelBlocksIcon; @@ -198,4 +207,32 @@ private slots: void showProgress(const QString &title, int nProgress); }; +class UnitDisplayStatusBarControl : public QLabel +{ + Q_OBJECT + +public: + explicit UnitDisplayStatusBarControl(); + /** Lets the control know about the Options Model (and its signals) */ + void setOptionsModel(OptionsModel *optionsModel); + +protected: + /** So that it responds to left-button clicks */ + void mousePressEvent(QMouseEvent *event); + +private: + OptionsModel *optionsModel; + QMenu* menu; + /** Shows context menu with Display Unit options by the mouse coordinates */ + void onDisplayUnitsClicked(const QPoint& point); + /** Creates context menu, its actions, and wires up all the relevant signals for mouse events. */ + void createContextMenu(); + +private slots: + /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ + void updateDisplayUnit(int newUnits); + /** Tells underlying optionsModel to update its current display unit. */ + void onMenuSelection(QAction* action); +}; + #endif // BITCOINGUI_H diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 2fed443cf2..4ba6aba551 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -169,6 +169,16 @@ bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out) return ok; } +QString BitcoinUnits::getAmountColumnTitle(int unit) +{ + QString amountTitle = QObject::tr("Amount"); + if (BitcoinUnits::valid(unit)) + { + amountTitle += " ("+BitcoinUnits::name(unit) + ")"; + } + return amountTitle; +} + int BitcoinUnits::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index 46517fc07b..451b52ee21 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -54,6 +54,8 @@ public: static QString formatWithUnit(int unit, qint64 amount, bool plussign=false); //! Parse string to coin amount static bool parse(int unit, const QString &value, qint64 *val_out); + //! Gets title for amount column including current display unit if optionsModel reference available */ + static QString getAmountColumnTitle(int unit); ///@} //! @name AbstractListModel implementation diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 6d985abaf8..09553a2587 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -308,9 +308,7 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in break; #endif case DisplayUnit: - nDisplayUnit = value.toInt(); - settings.setValue("nDisplayUnit", nDisplayUnit); - emit displayUnitChanged(nDisplayUnit); + setDisplayUnit(value); break; case DisplayAddresses: bDisplayAddresses = value.toBool(); @@ -356,11 +354,24 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in break; } } + emit dataChanged(index, index); return successful; } +/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */ +void OptionsModel::setDisplayUnit(const QVariant &value) +{ + if (!value.isNull()) + { + QSettings settings; + nDisplayUnit = value.toInt(); + settings.setValue("nDisplayUnit", nDisplayUnit); + emit displayUnitChanged(nDisplayUnit); + } +} + bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const { // Directly query current base proxy, because diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 2596682d07..89c2ec7453 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -52,6 +52,8 @@ public: int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); + /** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */ + void setDisplayUnit(const QVariant &value); /* Explicit getters */ bool getMinimizeToTray() { return fMinimizeToTray; } diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 844d62518c..b5a998f9f5 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -21,7 +21,9 @@ RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel addNewRequest(request); /* These columns must match the indices in the ColumnIndex enumeration */ - columns << tr("Date") << tr("Label") << tr("Message") << tr("Amount"); + columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle(); + + connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); } RecentRequestsTableModel::~RecentRequestsTableModel() @@ -101,6 +103,24 @@ QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orien return QVariant(); } +/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ +void RecentRequestsTableModel::updateAmountColumnTitle() +{ + columns[Amount] = getAmountTitle(); + emit headerDataChanged(Qt::Horizontal,Amount,Amount); +} + +/** Gets title for amount column including current display unit if optionsModel reference available. */ +QString RecentRequestsTableModel::getAmountTitle() +{ + QString amountTitle = tr("Amount"); + if (this->walletModel->getOptionsModel() != NULL) + { + amountTitle += " ("+BitcoinUnits::name(this->walletModel->getOptionsModel()->getDisplayUnit()) + ")"; + } + return amountTitle; +} + QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED(parent); @@ -185,6 +205,11 @@ void RecentRequestsTableModel::sort(int column, Qt::SortOrder order) emit dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); } +void RecentRequestsTableModel::updateDisplayUnit() +{ + updateAmountColumnTitle(); +} + bool RecentRequestEntryLessThan::operator()(RecentRequestEntry &left, RecentRequestEntry &right) const { RecentRequestEntry *pLeft = &left; diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h index d4cc5078aa..4f0b241259 100644 --- a/src/qt/recentrequeststablemodel.h +++ b/src/qt/recentrequeststablemodel.h @@ -91,12 +91,18 @@ public: public slots: void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + void updateDisplayUnit(); private: WalletModel *walletModel; QStringList columns; QList list; int64_t nReceiveRequestsMaxId; + + /** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ + void updateAmountColumnTitle(); + /** Gets title for amount column including current display unit if optionsModel reference available. */ + QString getAmountTitle(); }; #endif diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b9fcd0d6b0..e34238d805 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -235,8 +235,7 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren walletModel(parent), priv(new TransactionTablePriv(wallet, this)) { - columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount"); - + columns << QString() << tr("Date") << tr("Type") << tr("Address") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); priv->refreshWallet(); connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); @@ -247,6 +246,13 @@ TransactionTableModel::~TransactionTableModel() delete priv; } +/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ +void TransactionTableModel::updateAmountColumnTitle() +{ + columns[Amount] = BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit()); + emit headerDataChanged(Qt::Horizontal,Amount,Amount); +} + void TransactionTableModel::updateTransaction(const QString &hash, int status) { uint256 updated; @@ -624,5 +630,6 @@ QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex void TransactionTableModel::updateDisplayUnit() { // emit dataChanged to update Amount column with the current unit + updateAmountColumnTitle(); emit dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 333e6bc6ed..e8b6ed065d 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -87,6 +87,8 @@ public slots: void updateTransaction(const QString &hash, int status); void updateConfirmations(); void updateDisplayUnit(); + /** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */ + void updateAmountColumnTitle(); friend class TransactionTablePriv; }; diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index d4d29416ca..d6d210a561 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -309,7 +309,7 @@ void TransactionView::exportClicked() writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole); writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole); writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole); - writer.addColumn(tr("Amount"), 0, TransactionTableModel::FormattedAmountRole); + writer.addColumn(BitcoinUnits::getAmountColumnTitle(model->getOptionsModel()->getDisplayUnit()), 0, TransactionTableModel::FormattedAmountRole); writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole); if(!writer.write()) { From a90689ff9880cc76668d04beda5a5d97f2f4a76b Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 25 Jun 2014 14:21:29 -0400 Subject: [PATCH 239/336] Remove timing-based signature cache unit test Two changes: First removes a unit test that fails in my development environment (OSX, compiled -g3 with clang). sipa says that's not terribly surprising; the CMutableTransaction change makes signing a little more expensive but verification quicker. The unit test timed sign+verify-uncached versus verify-cached-five-times. He also says the test will be invalid when libsec256kp1 is integrated (because validation is super-optimized over signing). core.h change fixes a compiler warning (clang -Wall : CMutableTransaction defined as struct, declared as class in script.h). --- src/script.h | 2 +- src/test/DoS_tests.cpp | 87 ------------------------------------------ 2 files changed, 1 insertion(+), 88 deletions(-) diff --git a/src/script.h b/src/script.h index ea988f0e40..7ab471f6e6 100644 --- a/src/script.h +++ b/src/script.h @@ -20,7 +20,7 @@ class CCoins; class CKeyStore; class CTransaction; -class CMutableTransaction; +struct CMutableTransaction; static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index d512053051..5e17555e7a 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -231,91 +231,4 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) BOOST_CHECK(mapOrphanTransactionsByPrev.empty()); } -BOOST_AUTO_TEST_CASE(DoS_checkSig) -{ - // Test signature caching code (see key.cpp Verify() methods) - - CKey key; - key.MakeNewKey(true); - CBasicKeyStore keystore; - keystore.AddKey(key); - unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; - - // 100 orphan transactions: - static const int NPREV=100; - CMutableTransaction orphans[NPREV]; - for (int i = 0; i < NPREV; i++) - { - CMutableTransaction& tx = orphans[i]; - tx.vin.resize(1); - tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); - tx.vin[0].scriptSig << OP_1; - tx.vout.resize(1); - tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); - - AddOrphanTx(tx); - } - - // Create a transaction that depends on orphans: - CMutableTransaction tx; - tx.vout.resize(1); - tx.vout[0].nValue = 1*CENT; - tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID()); - tx.vin.resize(NPREV); - for (unsigned int j = 0; j < tx.vin.size(); j++) - { - tx.vin[j].prevout.n = 0; - tx.vin[j].prevout.hash = orphans[j].GetHash(); - } - // Creating signatures primes the cache: - boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time(); - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(SignSignature(keystore, orphans[j], tx, j)); - boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time(); - boost::posix_time::time_duration msdiff = mst2 - mst1; - long nOneValidate = msdiff.total_milliseconds(); - if (fDebug) printf("DoS_Checksig sign: %ld\n", nOneValidate); - - // ... now validating repeatedly should be quick: - // 2.8GHz machine, -g build: Sign takes ~760ms, - // uncached Verify takes ~250ms, cached Verify takes ~50ms - // (for 100 single-signature inputs) - mst1 = boost::posix_time::microsec_clock::local_time(); - for (unsigned int i = 0; i < 5; i++) - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL)); - mst2 = boost::posix_time::microsec_clock::local_time(); - msdiff = mst2 - mst1; - long nManyValidate = msdiff.total_milliseconds(); - if (fDebug) printf("DoS_Checksig five: %ld\n", nManyValidate); - - BOOST_CHECK_MESSAGE(nManyValidate < nOneValidate, "Signature cache timing failed"); - - // Empty a signature, validation should fail: - CScript save = tx.vin[0].scriptSig; - tx.vin[0].scriptSig = CScript(); - BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL)); - tx.vin[0].scriptSig = save; - - // Swap signatures, validation should fail: - std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); - BOOST_CHECK(!VerifySignature(CCoins(orphans[0], MEMPOOL_HEIGHT), tx, 0, flags, SIGHASH_ALL)); - BOOST_CHECK(!VerifySignature(CCoins(orphans[1], MEMPOOL_HEIGHT), tx, 1, flags, SIGHASH_ALL)); - std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig); - - // Exercise -maxsigcachesize code: - mapArgs["-maxsigcachesize"] = "10"; - // Generate a new, different signature for vin[0] to trigger cache clear: - CScript oldSig = tx.vin[0].scriptSig; - BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0)); - BOOST_CHECK(tx.vin[0].scriptSig != oldSig); - for (unsigned int j = 0; j < tx.vin.size(); j++) - BOOST_CHECK(VerifySignature(CCoins(orphans[j], MEMPOOL_HEIGHT), tx, j, flags, SIGHASH_ALL)); - mapArgs.erase("-maxsigcachesize"); - - LimitOrphanTxSize(0); -} - BOOST_AUTO_TEST_SUITE_END() From e10dcf27b4fb324a85b5650c7acd2ea5a52e822f Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 14:17:43 +0200 Subject: [PATCH 240/336] ensure clean and consistent "namespace" usage - remove some missplaced ; - ensure end of a namespace is clearly visible - use same formatting when using namespace --- src/base58.cpp | 4 +++- src/checkpoints.cpp | 7 ++++--- src/checkpoints.h | 7 ++++--- src/init.h | 2 +- src/key.cpp | 3 +-- src/main.cpp | 11 +++++++---- src/net.h | 3 +-- src/script.cpp | 5 +++-- src/util.cpp | 3 ++- 9 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index 1bd64684e5..c9e91beef1 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -186,6 +186,7 @@ int CBase58Data::CompareTo(const CBase58Data& b58) const { } namespace { + class CBitcoinAddressVisitor : public boost::static_visitor { private: CBitcoinAddress *addr; @@ -196,7 +197,8 @@ namespace { bool operator()(const CScriptID &id) const { return addr->Set(id); } bool operator()(const CNoDestination &no) const { return false; } }; -}; + +} // anon namespace bool CBitcoinAddress::Set(const CKeyID &id) { SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20); diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 75ac418916..80479b47fb 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -12,8 +12,8 @@ #include // for 'map_list_of()' #include -namespace Checkpoints -{ +namespace Checkpoints { + typedef std::map MapCheckpoints; // How many times we expect transactions after the last checkpoint to @@ -161,4 +161,5 @@ namespace Checkpoints } return NULL; } -} + +} // namespace Checkpoints diff --git a/src/checkpoints.h b/src/checkpoints.h index 1b4aacee20..2cf8d41b9d 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -13,8 +13,8 @@ class uint256; /** Block-chain checkpoints are compiled-in sanity checks. * They are updated every release or three. */ -namespace Checkpoints -{ +namespace Checkpoints { + // Returns true if block passes checkpoint checks bool CheckBlock(int nHeight, const uint256& hash); @@ -27,6 +27,7 @@ namespace Checkpoints double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true); extern bool fEnabled; -} + +} //namespace Checkpoints #endif diff --git a/src/init.h b/src/init.h index 52daa47616..626525c9ad 100644 --- a/src/init.h +++ b/src/init.h @@ -12,7 +12,7 @@ class CWallet; namespace boost { class thread_group; -}; +} // namespace boost extern CWallet* pwalletMain; diff --git a/src/key.cpp b/src/key.cpp index 96b1ac439c..784085da34 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -377,8 +377,7 @@ const unsigned char vchMaxModHalfOrder[32] = { const unsigned char vchZero[0] = {}; - -}; // end of anonymous namespace +} // anon namespace bool CKey::Check(const unsigned char *vch) { return CompareBigEndian(vch, 32, vchZero, 0) > 0 && diff --git a/src/main.cpp b/src/main.cpp index ea47601081..9832259964 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,6 +72,7 @@ const string strMessageMagic = "Bitcoin Signed Message:\n"; // Internal stuff namespace { + struct CBlockIndexWorkComparator { bool operator()(CBlockIndex *pa, CBlockIndex *pb) { @@ -120,7 +121,8 @@ namespace { }; map::iterator> > mapBlocksInFlight; map::iterator> > mapBlocksToDownload; -} + +} // anon namespace ////////////////////////////////////////////////////////////////////////////// // @@ -130,6 +132,7 @@ namespace { // These functions dispatch to one or all registered wallets namespace { + struct CMainSignals { // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. boost::signals2::signal SyncTransaction; @@ -144,7 +147,8 @@ struct CMainSignals { // Tells listeners to broadcast their data. boost::signals2::signal Broadcast; } g_signals; -} + +} // anon namespace void RegisterWallet(CWalletInterface* pwalletIn) { g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2)); @@ -274,7 +278,6 @@ void MarkBlockAsReceived(const uint256 &hash, NodeId nodeFrom = -1) { state->nLastBlockReceive = GetTimeMicros(); mapBlocksInFlight.erase(itInFlight); } - } // Requires cs_main. @@ -310,7 +313,7 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256 &hash) { mapBlocksInFlight[hash] = std::make_pair(nodeid, it); } -} +} // anon namespace bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { LOCK(cs_main); diff --git a/src/net.h b/src/net.h index 41dc618571..2ee798d468 100644 --- a/src/net.h +++ b/src/net.h @@ -28,14 +28,13 @@ #include #include - class CAddrMan; class CBlockIndex; class CNode; namespace boost { class thread_group; -} +} // namespace boost /** Time between pings automatically sent out for latency probing and keepalive (in seconds). */ static const int PING_INTERVAL = 2 * 60; diff --git a/src/script.cpp b/src/script.cpp index c83d26885a..dfba4da46e 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -974,6 +974,7 @@ bool EvalScript(vector >& stack, const CScript& script, co namespace { + /** Wrapper that serializes like CTransaction, but with the modifications * required for the signature hash done in-place */ @@ -1066,7 +1067,8 @@ public: ::Serialize(s, txTo.nLockTime, nType, nVersion); } }; -} + +} // anon namespace uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) { @@ -1092,7 +1094,6 @@ uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsig return ss.GetHash(); } - // Valid signature cache, to avoid doing expensive ECDSA signature checking // twice for every transaction (once when accepted into memory pool, and // again when accepted into the block chain) diff --git a/src/util.cpp b/src/util.cpp index 7a0e2cc800..7efcc577cf 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -77,11 +77,12 @@ // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options // http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION namespace boost { + namespace program_options { std::string to_internal(const std::string&); } -} +} // namespace boost using namespace std; From 9e9ca2b6710a0a0e600b9412b54d22b6b1f706b2 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 09:03:18 +0200 Subject: [PATCH 241/336] small cleanup of #ifdefs in BindListenPort() - SO_NOSIGPIPE isn't available on WIN32 so merge the 2 non-WIN32 blocks - use predefined names from header for IPV6_PROTECTION_LEVEL and PROTECTION_LEVEL_UNRESTRICTED --- src/net.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 811df43334..8f47489c8b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -36,6 +36,17 @@ #define MSG_NOSIGNAL 0 #endif +// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h. +// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version. +#ifdef WIN32 +#ifndef PROTECTION_LEVEL_UNRESTRICTED +#define PROTECTION_LEVEL_UNRESTRICTED 10 +#endif +#ifndef IPV6_PROTECTION_LEVEL +#define IPV6_PROTECTION_LEVEL 23 +#endif +#endif + using namespace std; using namespace boost; @@ -1587,18 +1598,16 @@ bool BindListenPort(const CService &addrBind, string& strError) return false; } +#ifndef WIN32 #ifdef SO_NOSIGPIPE // Different way of disabling SIGPIPE on BSD setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); #endif - -#ifndef WIN32 // Allow binding if the port is still in TIME_WAIT state after - // the program was closed and restarted. Not an issue on windows. + // the program was closed and restarted. Not an issue on windows! setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); #endif - #ifdef WIN32 // Set to non-blocking, incoming connections will also inherit this if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR) @@ -1622,10 +1631,8 @@ bool BindListenPort(const CService &addrBind, string& strError) #endif #endif #ifdef WIN32 - int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */; - int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */; - // this call is allowed to fail - setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int)); + int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED; + setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)); #endif } From 5d59921237ecb5a301ac37e0b97eb9c371a43d11 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 09:09:45 +0200 Subject: [PATCH 242/336] add missing BOOST_FOREACH indentation in ThreadSocketHandler() --- src/net.cpp | 81 +++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 8f47489c8b..934c45ca4c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -827,7 +827,6 @@ void ThreadSocketHandler() uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount); } - // // Find which sockets have data to receive // @@ -849,6 +848,7 @@ void ThreadSocketHandler() hSocketMax = max(hSocketMax, hListenSocket); have_fds = true; } + { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -909,58 +909,59 @@ void ThreadSocketHandler() MilliSleep(timeout.tv_usec/1000); } - // // Accept new connections // BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) - if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) { - struct sockaddr_storage sockaddr; - socklen_t len = sizeof(sockaddr); - SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); - CAddress addr; - int nInbound = 0; + if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) + { + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); + CAddress addr; + int nInbound = 0; - if (hSocket != INVALID_SOCKET) - if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) - LogPrintf("Warning: Unknown socket family\n"); + if (hSocket != INVALID_SOCKET) + if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) + LogPrintf("Warning: Unknown socket family\n"); - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->fInbound) - nInbound++; - } - - if (hSocket == INVALID_SOCKET) - { - int nErr = WSAGetLastError(); - if (nErr != WSAEWOULDBLOCK) - LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); - } - else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS) - { - closesocket(hSocket); - } - else if (CNode::IsBanned(addr)) - { - LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); - closesocket(hSocket); - } - else - { - LogPrint("net", "accepted connection %s\n", addr.ToString()); - CNode* pnode = new CNode(hSocket, addr, "", true); - pnode->AddRef(); { LOCK(cs_vNodes); - vNodes.push_back(pnode); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->fInbound) + nInbound++; + } + + if (hSocket == INVALID_SOCKET) + { + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK) + LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); + } + else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS) + { + closesocket(hSocket); + } + else if (CNode::IsBanned(addr)) + { + LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); + closesocket(hSocket); + } + else + { + LogPrint("net", "accepted connection %s\n", addr.ToString()); + CNode* pnode = new CNode(hSocket, addr, "", true); + pnode->AddRef(); + + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + } } } } - // // Service each socket // From cf04d83624e2ca66d094b6026e48bdf86693d7de Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 14:41:26 +0200 Subject: [PATCH 243/336] add OpenSSL RAND_cleanup() on OpenSSL shutdown - to securely erase the memory used by the PNRG - also rework 2 comments in OpenSSL init --- src/util.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 7a0e2cc800..5c1ed23b73 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -121,15 +121,17 @@ public: CRYPTO_set_locking_callback(locking_callback); #ifdef WIN32 - // Seed random number generator with screen scrape and other hardware sources + // Seed OpenSSL PRNG with current contents of the screen RAND_screen(); #endif - // Seed random number generator with performance counter + // Seed OpenSSL PRNG with performance counter RandAddSeed(); } ~CInit() { + // Securely erase the memory used by the PRNG + RAND_cleanup(); // Shutdown OpenSSL library multithreading support CRYPTO_set_locking_callback(NULL); for (int i = 0; i < CRYPTO_num_locks(); i++) From 86fe1b864b109869659f140af07047163637a673 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Thu, 26 Jun 2014 11:49:51 +0200 Subject: [PATCH 244/336] update coding.md to reflect changes by pull - also mention alphabetical include ordering --- doc/coding.md | 73 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/doc/coding.md b/doc/coding.md index 69388c9ce2..2f332e92f0 100644 --- a/doc/coding.md +++ b/doc/coding.md @@ -4,44 +4,65 @@ Coding Please be consistent with the existing coding style. Block style: +```c++ + bool Function(char* psz, int n) + { + // Comment summarising what this section of code does + for (int i = 0; i < n; i++) + { + // When something fails, return early + if (!Something()) + return false; + ... + } - bool Function(char* psz, int n) - { - // Comment summarising what this section of code does - for (int i = 0; i < n; i++) - { - // When something fails, return early - if (!Something()) - return false; - ... - } - - // Success return is usually at the end - return true; - } - + // Success return is usually at the end + return true; + } +``` - ANSI/Allman block style - 4 space indenting, no tabs - No extra spaces inside parenthesis; please don't do ( this ) - No space after function names, one space after if, for and while +- Includes need to be ordered alphabetically, separate own and foreign headers with a new-line (example key.cpp): +```c++ +#include "key.h" +#include "crypto/sha2.h" +#include "util.h" + +#include +``` +- Class or struct keywords in header files need to be ordered alphabetically: +```c++ +class CAlpha; +class CBeta; +``` +- When using namespace keyword use the following form: +```c++ +namespace Foo { + +... + +} // Foo +``` Variable names begin with the type in lowercase, like nSomeVariable. Please don't put the first word of the variable name in lowercase like someVariable. Common types: - n integer number: short, unsigned short, int, unsigned int, int64, uint64, sometimes char if used as a number - d double, float - f flag - hash uint256 - p pointer or array, one p for each level of indirection - psz pointer to null terminated string - str string object - v vector or similar list objects - map map or multimap - set set or multiset - bn CBigNum + n integer number: short, unsigned short, int, unsigned int, int64, uint64, sometimes char if used as a number + d double, float + f flag + hash uint256 + p pointer or array, one p for each level of indirection + psz pointer to null terminated string + str string object + v vector or similar list objects + map map or multimap + set set or multiset + bn CBigNum Doxygen comments ----------------- From 2a72d4591f5adf25fcb4d0433b390ba6c37f57a9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 11 Jul 2012 18:52:41 +0000 Subject: [PATCH 245/336] JSON-RPC method: prioritisetransaction Accepts the transaction into mined blocks at a higher (or lower) priority --- src/main.cpp | 10 ++++++++++ src/miner.cpp | 14 +++++++++++--- src/rpcclient.cpp | 2 ++ src/rpcmining.cpp | 14 ++++++++++++++ src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + src/txmempool.cpp | 29 +++++++++++++++++++++++++++++ src/txmempool.h | 6 ++++++ 8 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ea47601081..e06c519ee2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -789,6 +789,16 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode) { + { + LOCK(mempool.cs); + uint256 hash = tx.GetHash(); + double dPriorityDelta = 0; + int64_t nFeeDelta = 0; + mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); + if (dPriorityDelta > 0 || nFeeDelta > 0) + return 0; + } + // Base fee is either minTxFee or minRelayTxFee CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee; diff --git a/src/miner.cpp b/src/miner.cpp index 19b4694357..69e53756e0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -3,6 +3,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + #include "miner.h" #include "core.h" @@ -186,6 +188,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); dPriority = tx.ComputePriority(dPriority, nTxSize); + uint256 hash = tx.GetHash(); + mempool.ApplyDeltas(hash, dPriority, nTotalIn); + CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); if (porphan) @@ -227,10 +232,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; // Skip free transactions if we're past the minimum block size: - if (fSortedByFee && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + const uint256& hash = tx.GetHash(); + double dPriorityDelta = 0; + int64_t nFeeDelta = 0; + mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); + if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; - // Prioritize by fee once past the priority size or we run out of high-priority + // Prioritise by fee once past the priority size or we run out of high-priority // transactions: if (!fSortedByFee && ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority))) @@ -257,7 +266,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; CTxUndo txundo; - const uint256& hash = tx.GetHash(); UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1); // Added diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 3a06e33016..30881b9b1a 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -72,6 +72,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 2) ConvertTo(params[2]); if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); + if (strMethod == "prioritisetransaction" && n > 1) ConvertTo(params[1]); + if (strMethod == "prioritisetransaction" && n > 2) ConvertTo(params[2]); if (strMethod == "getblocktemplate" && n > 0) ConvertTo(params[0]); if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); if (strMethod == "sendmany" && n > 1) ConvertTo(params[1]); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 0072557f87..98caf704ee 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -247,6 +247,20 @@ Value getmininginfo(const Array& params, bool fHelp) } +Value prioritisetransaction(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "prioritisetransaction \n" + "Accepts the transaction into mined blocks at a higher (or lower) priority"); + + uint256 hash; + hash.SetHex(params[0].get_str()); + mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), params[2].get_int64()); + return true; +} + + Value getblocktemplate(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index c5d09cf577..6552de8c49 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -254,6 +254,7 @@ static const CRPCCommand vRPCCommands[] = { "getblocktemplate", &getblocktemplate, true, false, false }, { "getmininginfo", &getmininginfo, true, false, false }, { "getnetworkhashps", &getnetworkhashps, true, false, false }, + { "prioritisetransaction", &prioritisetransaction, true, false, false }, { "submitblock", &submitblock, false, true, false }, /* Raw transactions */ diff --git a/src/rpcserver.h b/src/rpcserver.h index 5271542385..1966a65b50 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -130,6 +130,7 @@ extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHe extern json_spirit::Value getnetworkhashps(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gethashespersec(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value prioritisetransaction(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value estimatefee(const json_spirit::Array& params, bool fHelp); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 4bf01d4848..52f82ef040 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -447,6 +447,7 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned i std::list dummy; remove(tx, dummy, false); removeConflicts(tx, conflicts); + ClearPrioritisation(tx.GetHash()); } } @@ -564,6 +565,34 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) return true; } +void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, int64_t nFeeDelta) +{ + { + LOCK(cs); + std::pair &deltas = mapDeltas[hash]; + deltas.first += dPriorityDelta; + deltas.second += nFeeDelta; + } + LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash.c_str(), dPriorityDelta, nFeeDelta); +} + +void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta) +{ + LOCK(cs); + std::map >::iterator pos = mapDeltas.find(hash); + if (pos == mapDeltas.end()) + return; + const std::pair &deltas = pos->second; + dPriorityDelta += deltas.first; + nFeeDelta += deltas.second; +} + +void CTxMemPool::ClearPrioritisation(const uint256 hash) +{ + LOCK(cs); + mapDeltas.erase(hash); +} + CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } diff --git a/src/txmempool.h b/src/txmempool.h index b2915aa842..f7dbb126a0 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -71,6 +71,7 @@ public: mutable CCriticalSection cs; std::map mapTx; std::map mapNextTx; + std::map > mapDeltas; CTxMemPool(); ~CTxMemPool(); @@ -95,6 +96,11 @@ public: unsigned int GetTransactionsUpdated() const; void AddTransactionsUpdated(unsigned int n); + /** Affect CreateNewBlock prioritisation of transactions */ + void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, int64_t nFeeDelta); + void ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta); + void ClearPrioritisation(const uint256 hash); + unsigned long size() { LOCK(cs); From 8ae973c00cfb02161bb2c2a6c839e510cd409278 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 24 Jun 2014 15:27:37 +0200 Subject: [PATCH 246/336] Allocate more space if necessary in RandSeedAddPerfMon Currently we use a fixed buffer of 250000 bytes to request HKEY_PERFORMANCE_DATA. In many cases this is not enough, causing the entropy collection to be skipped. Use a loop that grows the buffer as specified in the RegQueryValueEx documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724911%28v=vs.85%29.aspx (as the size of the performance data can differ for every call, the normal solution of requesting the size then allocating that can't work) --- src/util.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 7946089571..a96963689a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -169,8 +169,17 @@ void RandAddSeedPerfmon() // Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Seed with the entire set of perfmon data std::vector vData(250000,0); - unsigned long nSize = vData.size(); - long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize); + long ret = 0; + unsigned long nSize = 0; + const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data + while (true) + { + nSize = vData.size(); + ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize); + if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize) + break; + vData.resize(std::max((vData.size()*3)/2, nMaxSize)); // Grow size of buffer exponentially + } RegCloseKey(HKEY_PERFORMANCE_DATA); if (ret == ERROR_SUCCESS) { From e44fea55ea73f46bc9460597c7001e77acb58db7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 21 Feb 2014 04:06:12 +0000 Subject: [PATCH 247/336] Add an option to allow users to disable relaying/mining data carrier transactions --- src/init.cpp | 2 ++ src/script.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index a03629d07a..c7170b0f2d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -309,6 +309,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n"; strUsage += " -testnet " + _("Use the test network") + "\n"; + strUsage += "\n" + _("Node relay options:") + "\n"; + strUsage += " -datacarrier " + _("Relay and mine data carrier transactions (default: 1)") + "\n"; strUsage += "\n" + _("Block creation options:") + "\n"; strUsage += " -blockminsize= " + _("Set minimum block size in bytes (default: 0)") + "\n"; strUsage += " -blockmaxsize= " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n"; diff --git a/src/script.cpp b/src/script.cpp index c83d26885a..bc4705abe7 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1208,7 +1208,8 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector Date: Thu, 26 Jun 2014 15:51:07 +0100 Subject: [PATCH 248/336] Simplify build instructions --- doc/build-unix.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index 1d75c206e5..9d4b662d07 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -61,10 +61,8 @@ Dependency Build Instructions: Ubuntu & Debian ---------------------------------------------- Build requirements: - sudo apt-get install build-essential - sudo apt-get install libtool autotools-dev autoconf - sudo apt-get install libssl-dev - + sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev + for Ubuntu 12.04 and later: sudo apt-get install libboost-all-dev @@ -95,8 +93,7 @@ To enable the change run for other Ubuntu & Debian: - sudo apt-get install libdb4.8-dev - sudo apt-get install libdb4.8++-dev + sudo apt-get install libdb4.8-dev libdb4.8++-dev Optional: From caf6150e9785da408f1e603ae70eae25b5202d98 Mon Sep 17 00:00:00 2001 From: Huang Le <4tarhl@gmail.com> Date: Fri, 27 Jun 2014 02:55:39 +0800 Subject: [PATCH 249/336] Use async name resolving to improve net thread responsiveness In the LookupIntern(), things changed are: 1. Call getaddrinfo_a() instead of getaddrinfo() if available, the former is a sync version of the latter; 2. Try using inet_pton()/inet_addr() to convert the input text to a network addr structure at first, if success the extra name resolving thread inside getaddrinfo_a() could be avoided; 3. An interruption point added in the waiting loop for return from getaddrinfo_a(), which completes the improve for thread responsiveness. A easy way to see the effect is to kick off a 'bitcoind stop' immediately after 'bitcoind -daemon', before the change it would take several, or even tens of, minutes on a bad network situation to wait for the running bitcoind to exit, now it costs only seconds. Signed-off-by: Huang Le <4tarhl@gmail.com> --- configure.ac | 2 ++ src/netbase.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 811ef1dd80..3abf94f136 100644 --- a/configure.ac +++ b/configure.ac @@ -369,6 +369,8 @@ if test x$TARGET_OS = xdarwin; then fi AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h]) +AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define this symbol if you have getaddrinfo_a])]) +AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define this symbol if you have inet_pton])]) AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,, [#if HAVE_ENDIAN_H diff --git a/src/netbase.cpp b/src/netbase.cpp index 3c50174e75..f47b0f3563 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -3,6 +3,18 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifdef HAVE_CONFIG_H +#include "bitcoin-config.h" +#endif + +#ifdef HAVE_INET_PTON +#include +#endif + +#ifdef HAVE_GETADDRINFO_A +#include +#endif + #include "netbase.h" #include "hash.h" @@ -71,9 +83,30 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign } } +#ifdef HAVE_GETADDRINFO_A + struct in_addr ipv4_addr; +#ifdef HAVE_INET_PTON + if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) { + vIP.push_back(CNetAddr(ipv4_addr)); + return true; + } + + struct in6_addr ipv6_addr; + if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) { + vIP.push_back(CNetAddr(ipv6_addr)); + return true; + } +#else + ipv4_addr.s_addr = inet_addr(pszName); + if (ipv4_addr.s_addr != INADDR_NONE) { + vIP.push_back(CNetAddr(ipv4_addr)); + return true; + } +#endif +#endif + struct addrinfo aiHint; memset(&aiHint, 0, sizeof(struct addrinfo)); - aiHint.ai_socktype = SOCK_STREAM; aiHint.ai_protocol = IPPROTO_TCP; aiHint.ai_family = AF_UNSPEC; @@ -82,8 +115,33 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign #else aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; #endif + struct addrinfo *aiRes = NULL; +#ifdef HAVE_GETADDRINFO_A + struct gaicb gcb, *query = &gcb; + memset(query, 0, sizeof(struct gaicb)); + gcb.ar_name = pszName; + gcb.ar_request = &aiHint; + int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL); + if (nErr) + return false; + + do { + // Should set the timeout limit to a resonable value to avoid + // generating unnecessary checking call during the polling loop, + // while it can still response to stop request quick enough. + // 2 seconds looks fine in our situation. + struct timespec ts = { 2, 0 }; + gai_suspend(&query, 1, &ts); + boost::this_thread::interruption_point(); + + nErr = gai_error(query); + if (0 == nErr) + aiRes = query->ar_result; + } while (nErr == EAI_INPROGRESS); +#else int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes); +#endif if (nErr) return false; From c598f2acdb281823f39c17f3dbfb079e17cb14a1 Mon Sep 17 00:00:00 2001 From: Whit J Date: Thu, 26 Jun 2014 18:31:40 -0700 Subject: [PATCH 250/336] Fixed captitalization in bitcoin-cli-res.rc --- src/bitcoin-cli-res.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc index f8bfb3a881..a4a0c47ea5 100644 --- a/src/bitcoin-cli-res.rc +++ b/src/bitcoin-cli-res.rc @@ -5,7 +5,7 @@ #define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR -#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core developers" +#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION From e35b37b1b8252c3d3f66001ba1efccd263307add Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 26 Jun 2014 22:12:36 -0400 Subject: [PATCH 251/336] RPC client: Simplify command line string-to-JSON-value conversion code By default, all command line parameters are converted into JSON string values. There is no need to manually specify the incoming type. A binary decision "parse as string or JSON?" is all that's necessary. Convert to a simple class, initialized at runtime startup, which offers a quick lookup to answer "parse as JSON?" conversion question. Future parameter conversions need only to indicate the method name and zero-based index of the parameter needing JSON parsing. --- src/rpcclient.cpp | 179 ++++++++++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 77 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 30881b9b1a..501940a730 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include "rpcclient.h" #include "rpcprotocol.h" @@ -15,94 +16,118 @@ using namespace std; using namespace json_spirit; -template -void ConvertTo(Value& value, bool fAllowNull=false) +class CRPCConvertParam { - if (fAllowNull && value.type() == null_type) - return; - if (value.type() == str_type) - { - // reinterpret string as unquoted json value - Value value2; - string strJSON = value.get_str(); - if (!read_string(strJSON, value2)) - throw runtime_error(string("Error parsing JSON:")+strJSON); - ConvertTo(value2, fAllowNull); - value = value2; +public: + std::string methodName; // method whose params want conversion + int paramIdx; // 0-based idx of param to convert +}; + +static const CRPCConvertParam vRPCConvertParams[] = +{ + { "stop", 0 }, + { "getaddednodeinfo", 0 }, + { "setgenerate", 0 }, + { "setgenerate", 1 }, + { "getnetworkhashps", 0 }, + { "getnetworkhashps", 1 }, + { "sendtoaddress", 1 }, + { "settxfee", 0 }, + { "getreceivedbyaddress", 1 }, + { "getreceivedbyaccount", 1 }, + { "listreceivedbyaddress", 0 }, + { "listreceivedbyaddress", 1 }, + { "listreceivedbyaccount", 0 }, + { "listreceivedbyaccount", 1 }, + { "getbalance", 1 }, + { "getblockhash", 0 }, + { "move", 2 }, + { "move", 3 }, + { "sendfrom", 2 }, + { "sendfrom", 3 }, + { "listtransactions", 1 }, + { "listtransactions", 2 }, + { "listaccounts", 0 }, + { "walletpassphrase", 1 }, + { "getblocktemplate", 0 }, + { "listsinceblock", 1 }, + { "sendmany", 1 }, + { "sendmany", 2 }, + { "addmultisigaddress", 0 }, + { "addmultisigaddress", 1 }, + { "createmultisig", 0 }, + { "createmultisig", 1 }, + { "listunspent", 0 }, + { "listunspent", 1 }, + { "listunspent", 2 }, + { "getblock", 1 }, + { "getrawtransaction", 1 }, + { "createrawtransaction", 0 }, + { "createrawtransaction", 1 }, + { "signrawtransaction", 1 }, + { "signrawtransaction", 2 }, + { "sendrawtransaction", 1 }, + { "gettxout", 1 }, + { "gettxout", 2 }, + { "lockunspent", 0 }, + { "lockunspent", 1 }, + { "importprivkey", 2 }, + { "verifychain", 0 }, + { "verifychain", 1 }, + { "keypoolrefill", 0 }, + { "getrawmempool", 0 }, + { "estimatefee", 0 }, + { "estimatepriority", 0 }, +}; + +class CRPCConvertTable +{ +private: + std::set > members; + +public: + CRPCConvertTable(); + + bool convert(const std::string& method, int idx) { + return (members.count(std::make_pair(method, idx)) > 0); } - else - { - value = value.get_value(); +}; + +CRPCConvertTable::CRPCConvertTable() +{ + const unsigned int n_elem = + (sizeof(vRPCConvertParams) / sizeof(vRPCConvertParams[0])); + + for (unsigned int i = 0; i < n_elem; i++) { + members.insert(std::make_pair(vRPCConvertParams[i].methodName, + vRPCConvertParams[i].paramIdx)); } } +static CRPCConvertTable rpcCvtTable; + // Convert strings to command-specific RPC representation Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams) { Array params; - BOOST_FOREACH(const std::string ¶m, strParams) - params.push_back(param); - int n = params.size(); + for (unsigned int idx = 0; idx < strParams.size(); idx++) { + const std::string& strVal = strParams[idx]; - // - // Special case non-string parameter types - // - if (strMethod == "stop" && n > 0) ConvertTo(params[0]); - if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo(params[0]); - if (strMethod == "setgenerate" && n > 0) ConvertTo(params[0]); - if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); - if (strMethod == "getnetworkhashps" && n > 0) ConvertTo(params[0]); - if (strMethod == "getnetworkhashps" && n > 1) ConvertTo(params[1]); - if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "settxfee" && n > 0) ConvertTo(params[0]); - if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "listreceivedbyaddress" && n > 0) ConvertTo(params[0]); - if (strMethod == "listreceivedbyaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo(params[0]); - if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo(params[1]); - if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); - if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); - if (strMethod == "move" && n > 2) ConvertTo(params[2]); - if (strMethod == "move" && n > 3) ConvertTo(params[3]); - if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); - if (strMethod == "sendfrom" && n > 3) ConvertTo(params[3]); - if (strMethod == "listtransactions" && n > 1) ConvertTo(params[1]); - if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); - if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); - if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); - if (strMethod == "prioritisetransaction" && n > 1) ConvertTo(params[1]); - if (strMethod == "prioritisetransaction" && n > 2) ConvertTo(params[2]); - if (strMethod == "getblocktemplate" && n > 0) ConvertTo(params[0]); - if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); - if (strMethod == "sendmany" && n > 1) ConvertTo(params[1]); - if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); - if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); - if (strMethod == "addmultisigaddress" && n > 1) ConvertTo(params[1]); - if (strMethod == "createmultisig" && n > 0) ConvertTo(params[0]); - if (strMethod == "createmultisig" && n > 1) ConvertTo(params[1]); - if (strMethod == "listunspent" && n > 0) ConvertTo(params[0]); - if (strMethod == "listunspent" && n > 1) ConvertTo(params[1]); - if (strMethod == "listunspent" && n > 2) ConvertTo(params[2]); - if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); - if (strMethod == "getrawtransaction" && n > 1) ConvertTo(params[1]); - if (strMethod == "createrawtransaction" && n > 0) ConvertTo(params[0]); - if (strMethod == "createrawtransaction" && n > 1) ConvertTo(params[1]); - if (strMethod == "signrawtransaction" && n > 1) ConvertTo(params[1], true); - if (strMethod == "signrawtransaction" && n > 2) ConvertTo(params[2], true); - if (strMethod == "sendrawtransaction" && n > 1) ConvertTo(params[1], true); - if (strMethod == "gettxout" && n > 1) ConvertTo(params[1]); - if (strMethod == "gettxout" && n > 2) ConvertTo(params[2]); - if (strMethod == "lockunspent" && n > 0) ConvertTo(params[0]); - if (strMethod == "lockunspent" && n > 1) ConvertTo(params[1]); - if (strMethod == "importprivkey" && n > 2) ConvertTo(params[2]); - if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); - if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); - if (strMethod == "keypoolrefill" && n > 0) ConvertTo(params[0]); - if (strMethod == "getrawmempool" && n > 0) ConvertTo(params[0]); - if (strMethod == "estimatefee" && n > 0) ConvertTo(params[0]); - if (strMethod == "estimatepriority" && n > 0) ConvertTo(params[0]); + // insert string value directly + if (!rpcCvtTable.convert(strMethod, idx)) { + params.push_back(strVal); + } + + // parse string as JSON, insert bool/number/object/etc. value + else { + Value jVal; + if (!read_string(strVal, jVal)) + throw runtime_error(string("Error parsing JSON:")+strVal); + params.push_back(jVal); + } + + } return params; } From c912e22db08d0a44ad6fd027c09bbdf79c34dbbc Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 4 Jun 2014 11:24:43 -0400 Subject: [PATCH 252/336] RPC cleanup: Improve HTTP server replies 1) support varying content types 2) support only sending the header 3) properly deliver error message as content, if HTTP error 4) move AcceptedConnection class to header, for wider use --- src/rpcprotocol.cpp | 17 ++++++++++++++--- src/rpcprotocol.h | 14 +++++++++++++- src/rpcserver.cpp | 10 ---------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 2718f81783..bfa799f84f 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -54,7 +54,8 @@ static string rfc1123Time() return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime()); } -string HTTPReply(int nStatus, const string& strMsg, bool keepalive) +string HTTPReply(int nStatus, const string& strMsg, bool keepalive, + bool headersOnly, const char *contentType) { if (nStatus == HTTP_UNAUTHORIZED) return strprintf("HTTP/1.0 401 Authorization Required\r\n" @@ -73,6 +74,7 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive) "\r\n" "

401 Unauthorized.

\r\n" "\r\n", rfc1123Time(), FormatFullVersion()); + const char *cStatus; if (nStatus == HTTP_OK) cStatus = "OK"; else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request"; @@ -80,12 +82,19 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive) else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; else cStatus = ""; + + bool useInternalContent = false; + if (nStatus != HTTP_OK) { + contentType = "text/plain"; + useInternalContent = true; + } + return strprintf( "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" "Connection: %s\r\n" "Content-Length: %u\r\n" - "Content-Type: application/json\r\n" + "Content-Type: %s\r\n" "Server: bitcoin-json-rpc/%s\r\n" "\r\n" "%s", @@ -94,8 +103,10 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive) rfc1123Time(), keepalive ? "keep-alive" : "close", strMsg.size(), + contentType, FormatFullVersion(), - strMsg); + headersOnly ? "" : + useInternalContent ? cStatus : strMsg.c_str()); } bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index 11bdd171d9..8d415efb1b 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -71,6 +71,16 @@ enum RPCErrorCode RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked }; +class AcceptedConnection +{ +public: + virtual ~AcceptedConnection() {} + + virtual std::iostream& stream() = 0; + virtual std::string peer_address_to_string() const = 0; + virtual void close() = 0; +}; + // // IOStream device that speaks SSL but can also speak non-SSL // @@ -141,7 +151,9 @@ private: }; std::string HTTPPost(const std::string& strMsg, const std::map& mapRequestHeaders); -std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive); +std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive, + bool headerOnly = false, + const char *contentType = "application/json"); bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, std::string& http_method, std::string& http_uri); int ReadHTTPStatus(std::basic_istream& stream, int &proto); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 6552de8c49..b85b17c812 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -393,16 +393,6 @@ bool ClientAllowed(const boost::asio::ip::address& address) return false; } -class AcceptedConnection -{ -public: - virtual ~AcceptedConnection() {} - - virtual std::iostream& stream() = 0; - virtual std::string peer_address_to_string() const = 0; - virtual void close() = 0; -}; - template class AcceptedConnectionImpl : public AcceptedConnection { From 854d013012c2d457d5296227d212b053cbea5239 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 4 Jun 2014 11:38:33 -0400 Subject: [PATCH 253/336] RPC code movement: separate out JSON-RPC execution logic from HTTP server logic --- src/rpcserver.cpp | 129 ++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 57 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index b85b17c812..49bc05e5d6 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -809,6 +809,71 @@ static string JSONRPCExecBatch(const Array& vReq) return write_string(Value(ret), false) + "\n"; } +static bool HTTPReq_JSONRPC(AcceptedConnection *conn, + string& strRequest, + map& mapHeaders, + bool fRun) +{ + // Check authorization + if (mapHeaders.count("authorization") == 0) + { + conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + return false; + } + + if (!HTTPAuthorized(mapHeaders)) + { + LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string()); + /* 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) + MilliSleep(250); + + conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + return false; + } + + JSONRequest jreq; + try + { + // Parse request + Value valRequest; + if (!read_string(strRequest, valRequest)) + throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); + + string strReply; + + // singleton request + if (valRequest.type() == obj_type) { + jreq.parse(valRequest); + + Value result = tableRPC.execute(jreq.strMethod, jreq.params); + + // Send reply + strReply = JSONRPCReply(result, Value::null, jreq.id); + + // array of requests + } else if (valRequest.type() == array_type) + strReply = JSONRPCExecBatch(valRequest.get_array()); + else + throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); + + conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush; + } + catch (Object& objError) + { + ErrorReply(conn->stream(), objError, jreq.id); + return false; + } + catch (std::exception& e) + { + ErrorReply(conn->stream(), JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); + return false; + } + return true; +} + void ServiceConnection(AcceptedConnection *conn) { bool fRun = true; @@ -825,67 +890,17 @@ void ServiceConnection(AcceptedConnection *conn) // Read HTTP message headers and body ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto); - if (strURI != "/") { - conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; - break; - } - - // Check authorization - if (mapHeaders.count("authorization") == 0) - { - conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; - break; - } - if (!HTTPAuthorized(mapHeaders)) - { - LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", conn->peer_address_to_string()); - /* 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) - MilliSleep(250); - - conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; - break; - } + // HTTP Keep-Alive is false; close connection immediately if (mapHeaders["connection"] == "close") fRun = false; - JSONRequest jreq; - try - { - // Parse request - Value valRequest; - if (!read_string(strRequest, valRequest)) - throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); - - string strReply; - - // singleton request - if (valRequest.type() == obj_type) { - jreq.parse(valRequest); - - Value result = tableRPC.execute(jreq.strMethod, jreq.params); - - // Send reply - strReply = JSONRPCReply(result, Value::null, jreq.id); - - // array of requests - } else if (valRequest.type() == array_type) - strReply = JSONRPCExecBatch(valRequest.get_array()); - else - throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error"); - - conn->stream() << HTTPReply(HTTP_OK, strReply, fRun) << std::flush; + if (strURI == "/") { + if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun)) + break; } - catch (Object& objError) - { - ErrorReply(conn->stream(), objError, jreq.id); - break; - } - catch (std::exception& e) - { - ErrorReply(conn->stream(), JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); + + else { + conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; break; } } From ed5769f536f663a8deb8e8b7a68681cebaa52bdd Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 27 Jun 2014 00:10:53 -0400 Subject: [PATCH 254/336] Move AcceptedConnection class to rpcserver.h. Also, add parens to HTTPReply() to assist readability. --- src/rpcprotocol.cpp | 4 ++-- src/rpcprotocol.h | 10 ---------- src/rpcserver.h | 10 ++++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index bfa799f84f..2cb4a35c4b 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -105,8 +105,8 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive, strMsg.size(), contentType, FormatFullVersion(), - headersOnly ? "" : - useInternalContent ? cStatus : strMsg.c_str()); + (headersOnly ? "" : + (useInternalContent ? cStatus : strMsg.c_str()))); } bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index 8d415efb1b..f1317e9c28 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -71,16 +71,6 @@ enum RPCErrorCode RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked }; -class AcceptedConnection -{ -public: - virtual ~AcceptedConnection() {} - - virtual std::iostream& stream() = 0; - virtual std::string peer_address_to_string() const = 0; - virtual void close() = 0; -}; - // // IOStream device that speaks SSL but can also speak non-SSL // diff --git a/src/rpcserver.h b/src/rpcserver.h index 1966a65b50..fcd293663f 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -21,6 +21,16 @@ class CBlockIndex; class CNetAddr; +class AcceptedConnection +{ +public: + virtual ~AcceptedConnection() {} + + virtual std::iostream& stream() = 0; + virtual std::string peer_address_to_string() const = 0; + virtual void close() = 0; +}; + /* Start RPC threads */ void StartRPCThreads(); /* Alternative to StartRPCThreads for the GUI, when no server is From 49d86c7477ba1dbbbd08f452d0e7d710b22bad92 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 27 Jun 2014 10:05:46 +0200 Subject: [PATCH 255/336] rpc-tests: Fix rpcbind_test after 0193fb8 Port number for RPC is no longer static as multiple tests could be running at once. --- qa/rpc-tests/rpcbind_test.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index a31f8d98ef..a823404e00 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -39,7 +39,7 @@ def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected): stop_nodes(nodes) wait_bitcoinds() -def run_allowip_test(tmpdir, allow_ips, rpchost): +def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport): ''' Start a node with rpcwallow IP, and request getinfo at a non-localhost IP. @@ -48,7 +48,7 @@ def run_allowip_test(tmpdir, allow_ips, rpchost): nodes = start_nodes(1, tmpdir, [base_args]) try: # connect to node through non-loopback interface - url = "http://rt:rt@%s:%d" % (rpchost, START_RPC_PORT,) + url = "http://rt:rt@%s:%d" % (rpchost, rpcport,) node = AuthServiceProxy(url) node.getinfo() finally: @@ -69,15 +69,17 @@ def run_test(tmpdir): assert(not 'This test requires at least one non-loopback IPv4 interface') print("Using interface %s for testing" % non_loopback_ip) + defaultport = rpc_port(0) + # check default without rpcallowip (IPv4 and IPv6 localhost) run_bind_test(tmpdir, None, '127.0.0.1', [], - [('127.0.0.1', 11100), ('::1', 11100)]) + [('127.0.0.1', defaultport), ('::1', defaultport)]) # check default with rpcallowip (IPv6 any) run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [], - [('::0', 11100)]) + [('::0', defaultport)]) # check only IPv4 localhost (explicit) run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], - [('127.0.0.1', START_RPC_PORT)]) + [('127.0.0.1', defaultport)]) # check only IPv4 localhost (explicit) with alternative port run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], [('127.0.0.1', 32171)]) @@ -86,18 +88,18 @@ def run_test(tmpdir): [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) # check only IPv6 localhost (explicit) run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'], - [('::1', 11100)]) + [('::1', defaultport)]) # check both IPv4 and IPv6 localhost (explicit) run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], - [('127.0.0.1', START_RPC_PORT), ('::1', START_RPC_PORT)]) + [('127.0.0.1', defaultport), ('::1', defaultport)]) # check only non-loopback interface run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip], - [(non_loopback_ip, START_RPC_PORT)]) + [(non_loopback_ip, defaultport)]) # Check that with invalid rpcallowip, we are denied - run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip) + run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip, defaultport) try: - run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip) + run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip, defaultport) assert(not 'Connection not denied by rpcallowip as expected') except ValueError: pass From 40a158e100c517c73d9a75434e48cfe904ea00cc Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 27 Jun 2014 11:13:25 +0200 Subject: [PATCH 256/336] minor code format fix in rpc-related files --- src/rpcmisc.cpp | 2 +- src/rpcserver.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index a300de2680..5b470516a1 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -22,10 +22,10 @@ #include "json/json_spirit_utils.h" #include "json/json_spirit_value.h" -using namespace std; using namespace boost; using namespace boost::assign; using namespace json_spirit; +using namespace std; Value getinfo(const Array& params, bool fHelp) { diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 49bc05e5d6..54043458d5 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -25,10 +25,10 @@ #include #include "json/json_spirit_writer_template.h" -using namespace std; using namespace boost; using namespace boost::asio; using namespace json_spirit; +using namespace std; static std::string strRPCUserColonPass; @@ -897,9 +897,7 @@ void ServiceConnection(AcceptedConnection *conn) if (strURI == "/") { if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun)) break; - } - - else { + } else { conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; break; } From 33c62c9c0b25998beb361e6f42e1fd0beebcf05b Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 27 Jun 2014 15:09:41 +0200 Subject: [PATCH 257/336] set shutdown title to main window title - this ensures we don't show Bitcoin-Qt as that is still our internal application name - fixes #4427 --- src/qt/utilitydialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index eb647d0170..5fb0da145d 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -117,6 +117,7 @@ void ShutdownWindow::showShutdownWindow(BitcoinGUI *window) tr("Bitcoin Core is shutting down...") + "

" + tr("Do not shut down the computer until this window disappears."))); shutdownWindow->setLayout(layout); + shutdownWindow->setWindowTitle(window->windowTitle()); // Center shutdown window at where main window was const QPoint global = window->mapToGlobal(window->rect().center()); From 8fbf03995df9a2003be603be1a930bc3373d56e0 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Wed, 25 Jun 2014 16:21:29 -0700 Subject: [PATCH 258/336] CBloomFilter::clear() method --- src/bloom.cpp | 7 +++++++ src/bloom.h | 2 ++ src/test/bloom_tests.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/src/bloom.cpp b/src/bloom.cpp index 26e366179c..85a2ddc189 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -94,6 +94,13 @@ bool CBloomFilter::contains(const uint256& hash) const return contains(data); } +void CBloomFilter::clear() +{ + vData.assign(vData.size(),0); + isFull = false; + isEmpty = true; +} + bool CBloomFilter::IsWithinSizeConstraints() const { return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS; diff --git a/src/bloom.h b/src/bloom.h index 956bead87f..d0caf9e9fa 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -78,6 +78,8 @@ public: bool contains(const COutPoint& outpoint) const; bool contains(const uint256& hash) const; + void clear(); + // True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS // (catch a filter which was just deserialized which was too big) bool IsWithinSizeConstraints() const; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index b56d998be2..5c6c7d8588 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -45,6 +45,10 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize) expected[i] = (char)vch[i]; BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end()); + + BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!"); + filter.clear(); + BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter should be empty!"); } BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak) From d640a3ceab4f4372c2a0f738c1286cfde4b41b50 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Wed, 25 Jun 2014 23:41:44 -0700 Subject: [PATCH 259/336] Relay double-spends, subject to anti-DOS Allows network wallets and other clients to see transactions that respend a prevout already spent in an unconfirmed transaction in this node's mempool. Knowledge of an attempted double-spend is of interest to recipients of the first spend. In some cases, it will allow these recipients to withhold goods or services upon being alerted of a double-spend that deprives them of payment. As before, respends are not added to the mempool. Anti-Denial-of-Service-Attack provisions: - Use a bloom filter to relay only one respend per mempool prevout - Rate-limit respend relays to a default of 100 thousand bytes/minute - Define tx2.IsEquivalentTo(tx1): equality when scriptSigs are not considered - Do not relay these equivalent transactions Remove an unused variable declaration in txmempool.cpp. --- src/core.cpp | 16 ++++++++ src/core.h | 3 ++ src/init.cpp | 1 + src/main.cpp | 100 +++++++++++++++++++++++++++++++++++++++------- src/main.h | 3 ++ src/txmempool.cpp | 1 - 6 files changed, 109 insertions(+), 15 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 6c5ee1c0f8..ca28624529 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -119,6 +119,22 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) { return *this; } +bool CTransaction::IsEquivalentTo(const CTransaction& tx) const +{ + if (nVersion != tx.nVersion || + nLockTime != tx.nLockTime || + vin.size() != tx.vin.size() || + vout != tx.vout) + return false; + for (unsigned int i = 0; i < vin.size(); i++) + { + if (vin[i].nSequence != tx.vin[i].nSequence || + vin[i].prevout != tx.vin[i].prevout) + return false; + } + return true; +} + int64_t CTransaction::GetValueOut() const { int64_t nValueOut = 0; diff --git a/src/core.h b/src/core.h index 27fda95552..8606831575 100644 --- a/src/core.h +++ b/src/core.h @@ -256,6 +256,9 @@ public: return hash; } + // True if only scriptSigs are different + bool IsEquivalentTo(const CTransaction& tx) const; + // Return sum of txouts. int64_t GetValueOut() const; // GetValueIn() is a method on CCoinsViewCache, because diff --git a/src/init.cpp b/src/init.cpp index c7170b0f2d..bd732753e4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1175,6 +1175,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); #endif + RegisterInternalSignals(); StartNode(threadGroup); if (fServer) StartRPCThreads(); diff --git a/src/main.cpp b/src/main.cpp index d86fd3a24d..48237c1b54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "addrman.h" #include "alert.h" +#include "bloom.h" #include "chainparams.h" #include "checkpoints.h" #include "checkqueue.h" @@ -122,6 +123,10 @@ namespace { map::iterator> > mapBlocksToDownload; } +// Forward reference functions defined here: +static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000; +static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter); + ////////////////////////////////////////////////////////////////////////////// // // dispatching functions @@ -143,9 +148,24 @@ struct CMainSignals { boost::signals2::signal Inventory; // Tells listeners to broadcast their data. boost::signals2::signal Broadcast; + // Notifies listeners of detection of a double-spent transaction. Arguments are outpoint that is + // double-spent, first transaction seen, double-spend transaction, and whether the second double-spend + // transaction was first seen in a block. + // Note: only notifies if the previous transaction is in the memory pool; if previous transction was in a block, + // then the double-spend simply fails when we try to lookup the inputs in the current UTXO set. + boost::signals2::signal DetectedDoubleSpend; } g_signals; } +void RegisterInternalSignals() { + static CBloomFilter doubleSpendFilter; + seed_insecure_rand(); + doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE); + + g_signals.DetectedDoubleSpend.connect(boost::bind(RelayDoubleSpend, _1, _2, _3, doubleSpendFilter)); +} + + void RegisterWallet(CWalletInterface* pwalletIn) { g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2)); g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1)); @@ -824,6 +844,22 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, return nMinFee; } +// Exponentially limit the rate of nSize flow to nLimit. nLimit unit is thousands-per-minute. +bool RateLimitExceeded(double& dCount, int64_t& nLastTime, int64_t nLimit, unsigned int nSize) +{ + static CCriticalSection csLimiter; + int64_t nNow = GetTime(); + + LOCK(csLimiter); + + // Use an exponentially decaying ~10-minute window: + dCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime)); + nLastTime = nNow; + if (dCount >= nLimit*10*1000) + return true; + dCount += nSize; + return false; +} bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee) @@ -858,9 +894,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa for (unsigned int i = 0; i < tx.vin.size(); i++) { COutPoint outpoint = tx.vin[i].prevout; - if (pool.mapNextTx.count(outpoint)) + // Does tx conflict with a member of the pool, and is it not equivalent to that member? + if (pool.mapNextTx.count(outpoint) && !tx.IsEquivalentTo(*pool.mapNextTx[outpoint].ptx)) { - // Disable replacement feature for now + g_signals.DetectedDoubleSpend(outpoint, tx, false); return false; } } @@ -932,23 +969,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be annoying or make others' transactions take longer to confirm. if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize)) { - static CCriticalSection csFreeLimiter; static double dFreeCount; - static int64_t nLastTime; - int64_t nNow = GetTime(); + static int64_t nLastFreeTime; + static int64_t nFreeLimit = GetArg("-limitfreerelay", 15); - LOCK(csFreeLimiter); - - // Use an exponentially decaying ~10-minute window: - dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime)); - nLastTime = nNow; - // -limitfreerelay unit is thousand-bytes-per-minute - // At default rate it would take over a month to fill 1GB - if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) + if (RateLimitExceeded(dFreeCount, nLastFreeTime, nFreeLimit, nSize)) return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "insufficient priority"); + LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); - dFreeCount += nSize; } if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000) @@ -971,6 +1000,49 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } +static void +RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) +{ + // Relaying double-spend attempts to our peers lets them detect when + // somebody might be trying to cheat them. However, blindly relaying + // every double-spend across the entire network gives attackers + // a denial-of-service attack: just generate a stream of double-spends + // re-spending the same (limited) set of outpoints owned by the attacker. + // So, we use a bloom filter and only relay (at most) the first double + // spend for each outpoint. False-positives ("we have already relayed") + // are OK, because if the peer doesn't hear about the double-spend + // from us they are very likely to hear about it from another peer, since + // each peer uses a different, randomized bloom filter. + + if (fInBlock || filter.contains(outPoint)) return; + + // Apply an independent rate limit to double-spend relays + static double dRespendCount; + static int64_t nLastRespendTime; + static int64_t nRespendLimit = GetArg("-limitrespendrelay", 100); + unsigned int nSize = ::GetSerializeSize(doubleSpend, SER_NETWORK, PROTOCOL_VERSION); + + if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize)) + { + LogPrint("mempool", "Double-spend relay rejected by rate limiter\n"); + return; + } + + LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize); + + // Clear the filter on average every MAX_DOUBLE_SPEND_BLOOM + // insertions + if (insecure_rand()%MAX_DOUBLESPEND_BLOOM == 0) + filter.clear(); + + filter.insert(outPoint); + + RelayTransaction(doubleSpend); + + // Share conflict with wallet + g_signals.SyncTransaction(doubleSpend, NULL); +} + int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { diff --git a/src/main.h b/src/main.h index 0332db2163..c7f3dc4388 100644 --- a/src/main.h +++ b/src/main.h @@ -108,6 +108,9 @@ struct CNodeStateStats; struct CBlockTemplate; +/** Set up internal signal handlers **/ +void RegisterInternalSignals(); + /** Register a wallet to receive updates from core */ void RegisterWallet(CWalletInterface* pwalletIn); /** Unregister a wallet from core */ diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52f82ef040..97a426dd35 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -415,7 +415,6 @@ void CTxMemPool::remove(const CTransaction &tx, std::list& removed void CTxMemPool::removeConflicts(const CTransaction &tx, std::list& removed) { // Remove transactions which depend on inputs of tx, recursively - list result; LOCK(cs); BOOST_FOREACH(const CTxIn &txin, tx.vin) { std::map::iterator it = mapNextTx.find(txin.prevout); From ada5a067c75f19a724cc054286ecf2254e5dbe8f Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Thu, 26 Jun 2014 18:31:05 -0700 Subject: [PATCH 260/336] UI to alert of respend attempt affecting wallet. Respend transactions that conflict with transactions already in the wallet are added to it. They are not displayed unless they also involve the wallet, or get into a block. If they do not involve the wallet, they continue not to affect balance. Transactions that involve the wallet, and have conflicting non-equivalent transactions, are highlighted in red. When the conflict first occurs, a modal dialog is thrown. CWallet::SyncMetaData is changed to sync only to equivalent transactions. When a conflict is added to the wallet, counter nConflictsReceived is incremented. This acts like a change in active block height for the purpose of triggering UI updates. --- src/qt/guiconstants.h | 4 ++++ src/qt/transactionfilterproxy.cpp | 4 ++-- src/qt/transactionrecord.cpp | 10 +++++++--- src/qt/transactionrecord.h | 13 ++++++++++-- src/qt/transactiontablemodel.cpp | 18 ++++++++++++----- src/qt/walletmodel.cpp | 8 ++++++++ src/ui_interface.h | 3 ++- src/wallet.cpp | 33 +++++++++++++++++++++++++------ src/wallet.h | 15 ++++++++++++-- 9 files changed, 87 insertions(+), 21 deletions(-) diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 5ae4bc833d..44e361e1e5 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -23,6 +23,10 @@ static const int STATUSBAR_ICONSIZE = 16; #define COLOR_NEGATIVE QColor(255, 0, 0) /* Transaction list -- bare address (without label) */ #define COLOR_BAREADDRESS QColor(140, 140, 140) +/* Transaction list -- has conflicting transactions */ +#define COLOR_HASCONFLICTING Qt::white; +/* Transaction list -- has conflicting transactions - background */ +#define COLOR_HASCONFLICTING_BG QColor(192, 0, 0) /* Tooltips longer than this (in characters) are converted into rich text, so that they can be word-wrapped. diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp index f9546fddb5..7293029787 100644 --- a/src/qt/transactionfilterproxy.cpp +++ b/src/qt/transactionfilterproxy.cpp @@ -24,7 +24,7 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) : typeFilter(ALL_TYPES), minAmount(0), limitRows(-1), - showInactive(true) + showInactive(false) { } @@ -39,7 +39,7 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex & qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong()); int status = index.data(TransactionTableModel::StatusRole).toInt(); - if(!showInactive && status == TransactionStatus::Conflicted) + if(!showInactive && status == TransactionStatus::Conflicted && type == TransactionRecord::Other) return false; if(!(TYPE(type) & typeFilter)) return false; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index eec2b57e8c..21f1b7356f 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -170,6 +170,8 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) status.depth = wtx.GetDepthInMainChain(); status.cur_num_blocks = chainActive.Height(); + status.hasConflicting = false; + if (!IsFinalTx(wtx, chainActive.Height() + 1)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) @@ -213,6 +215,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) if (status.depth < 0) { status.status = TransactionStatus::Conflicted; + status.hasConflicting = !(wtx.GetConflicts(false).empty()); } else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) { @@ -221,6 +224,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; + status.hasConflicting = !(wtx.GetConflicts(false).empty()); } else if (status.depth < RecommendedNumConfirmations) { @@ -231,13 +235,13 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) status.status = TransactionStatus::Confirmed; } } - } -bool TransactionRecord::statusUpdateNeeded() +bool TransactionRecord::statusUpdateNeeded(int64_t nConflictsReceived) { AssertLockHeld(cs_main); - return status.cur_num_blocks != chainActive.Height(); + return (status.cur_num_blocks != chainActive.Height() || + status.cur_num_conflicts != nConflictsReceived); } QString TransactionRecord::getTxID() const diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index af6fd403b3..4c2847144a 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -20,7 +20,8 @@ class TransactionStatus public: TransactionStatus(): countsForBalance(false), sortKey(""), - matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1) + matures_in(0), status(Offline), hasConflicting(false), depth(0), open_for(0), cur_num_blocks(-1), + cur_num_conflicts(-1) { } enum Status { @@ -51,6 +52,10 @@ public: /** @name Reported status @{*/ Status status; + + // Has conflicting transactions spending same prevout + bool hasConflicting; + qint64 depth; qint64 open_for; /**< Timestamp if status==OpenUntilDate, otherwise number of additional blocks that need to be mined before @@ -59,6 +64,10 @@ public: /** Current number of blocks (to know whether cached status is still valid) */ int cur_num_blocks; + + /** Number of conflicts received into wallet as of last status update */ + int64_t cur_num_conflicts; + }; /** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has @@ -133,7 +142,7 @@ public: /** Return whether a status update is needed. */ - bool statusUpdateNeeded(); + bool statusUpdateNeeded(int64_t nConflictsReceived); }; #endif // TRANSACTIONRECORD_H diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index b9fcd0d6b0..eb5c3abdbc 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -168,8 +168,7 @@ public: parent->endRemoveRows(); break; case CT_UPDATED: - // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for - // visible transactions. + emit parent->dataChanged(parent->index(lowerIndex, parent->Status), parent->index(upperIndex-1, parent->Amount)); break; } } @@ -190,20 +189,21 @@ public: // stuck if the core is holding the locks for a longer time - for // example, during a wallet rescan. // - // If a status update is needed (blocks came in since last check), - // update the status of this transaction from the wallet. Otherwise, + // If a status update is needed (blocks or conflicts came in since last check), + // update the status of this transaction from the wallet. Otherwise, // simply re-use the cached status. TRY_LOCK(cs_main, lockMain); if(lockMain) { TRY_LOCK(wallet->cs_wallet, lockWallet); - if(lockWallet && rec->statusUpdateNeeded()) + if(lockWallet && rec->statusUpdateNeeded(wallet->nConflictsReceived)) { std::map::iterator mi = wallet->mapWallet.find(rec->hash); if(mi != wallet->mapWallet.end()) { rec->updateStatus(mi->second); + rec->status.cur_num_conflicts = wallet->nConflictsReceived; } } } @@ -363,6 +363,8 @@ QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const return tr("Payment to yourself"); case TransactionRecord::Generated: return tr("Mined"); + case TransactionRecord::Other: + return tr("Other"); default: return QString(); } @@ -535,7 +537,13 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const return formatTooltip(rec); case Qt::TextAlignmentRole: return column_alignments[index.column()]; + case Qt::BackgroundColorRole: + if (rec->status.hasConflicting) + return COLOR_HASCONFLICTING_BG; + break; case Qt::ForegroundRole: + if (rec->status.hasConflicting) + return COLOR_HASCONFLICTING; // Non-confirmed (but not immature) as transactions are grey if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature) { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2f633a26c8..3d6f2ab9ba 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -138,6 +138,14 @@ void WalletModel::checkBalanceChanged() void WalletModel::updateTransaction(const QString &hash, int status) { + if (status == CT_GOT_CONFLICT) + { + emit message(tr("Conflict Received"), + tr("WARNING: Transaction may never be confirmed. Its input was seen being spent by another transaction on the network. Wait for confirmation!"), + CClientUIInterface::MSG_WARNING); + return; + } + if(transactionTableModel) transactionTableModel->updateTransaction(hash, status); diff --git a/src/ui_interface.h b/src/ui_interface.h index e1a3e04e12..e9fcd91d41 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -21,7 +21,8 @@ enum ChangeType { CT_NEW, CT_UPDATED, - CT_DELETED + CT_DELETED, + CT_GOT_CONFLICT }; /** Signals for UI communication. */ diff --git a/src/wallet.cpp b/src/wallet.cpp index f6fd6e958d..79cc5ba3c9 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -256,7 +256,7 @@ bool CWallet::SetMaxVersion(int nVersion) return true; } -set CWallet::GetConflicts(const uint256& txid) const +set CWallet::GetConflicts(const uint256& txid, bool includeEquivalent) const { set result; AssertLockHeld(cs_wallet); @@ -274,7 +274,8 @@ set CWallet::GetConflicts(const uint256& txid) const continue; // No conflict if zero or one spends range = mapTxSpends.equal_range(txin.prevout); for (TxSpends::const_iterator it = range.first; it != range.second; ++it) - result.insert(it->second); + if (includeEquivalent || !wtx.IsEquivalentTo(mapWallet.at(it->second))) + result.insert(it->second); } return result; } @@ -303,6 +304,7 @@ void CWallet::SyncMetaData(pair range) const uint256& hash = it->second; CWalletTx* copyTo = &mapWallet[hash]; if (copyFrom == copyTo) continue; + if (!copyFrom->IsEquivalentTo(*copyTo)) continue; copyTo->mapValue = copyFrom->mapValue; copyTo->vOrderForm = copyFrom->vOrderForm; // fTimeReceivedIsTxTime not copied on purpose @@ -588,6 +590,20 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) // Notify UI of new or updated transaction NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); + // Notifications for existing transactions that now have conflicts with this one + if (fInsertedNew) + { + BOOST_FOREACH(const uint256& conflictHash, wtxIn.GetConflicts(false)) + { + CWalletTx& txConflict = mapWallet[conflictHash]; + NotifyTransactionChanged(this, conflictHash, CT_UPDATED); //Updates UI table + if (IsFromMe(txConflict) || IsMine(txConflict)) + { + NotifyTransactionChanged(this, conflictHash, CT_GOT_CONFLICT); //Throws dialog + } + } + } + // notify an external script when a wallet transaction comes in or is updated std::string strCmd = GetArg("-walletnotify", ""); @@ -610,7 +626,12 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl AssertLockHeld(cs_wallet); bool fExisted = mapWallet.count(tx.GetHash()); if (fExisted && !fUpdate) return false; - if (fExisted || IsMine(tx) || IsFromMe(tx)) + + bool fIsConflicting = IsConflicting(tx); + if (fIsConflicting) + nConflictsReceived++; + + if (fExisted || IsMine(tx) || IsFromMe(tx) || fIsConflicting) { CWalletTx wtx(this,tx); // Get merkle branch if transaction was found in a block @@ -896,7 +917,7 @@ void CWallet::ReacceptWalletTransactions() int nDepth = wtx.GetDepthInMainChain(); - if (!wtx.IsCoinBase() && nDepth < 0) + if (!wtx.IsCoinBase() && nDepth < 0 && (IsMine(wtx) || IsFromMe(wtx))) { // Try to add to memory pool LOCK(mempool.cs); @@ -916,13 +937,13 @@ void CWalletTx::RelayWalletTransaction() } } -set CWalletTx::GetConflicts() const +set CWalletTx::GetConflicts(bool includeEquivalent) const { set result; if (pwallet != NULL) { uint256 myHash = GetHash(); - result = pwallet->GetConflicts(myHash); + result = pwallet->GetConflicts(myHash, includeEquivalent); result.erase(myHash); } return result; diff --git a/src/wallet.h b/src/wallet.h index 8494ce9a34..1c2512d678 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -141,6 +141,9 @@ public: MasterKeyMap mapMasterKeys; unsigned int nMasterKeyMaxID; + // Increment to cause UI refresh, similar to new block + int64_t nConflictsReceived; + CWallet() { SetNull(); @@ -163,6 +166,7 @@ public: nNextResend = 0; nLastResend = 0; nTimeFirstKey = 0; + nConflictsReceived = 0; } std::map mapWallet; @@ -305,6 +309,13 @@ public: { return (GetDebit(tx) > 0); } + bool IsConflicting(const CTransaction& tx) const + { + BOOST_FOREACH(const CTxIn& txin, tx.vin) + if (mapTxSpends.count(txin.prevout)) + return true; + return false; + } int64_t GetDebit(const CTransaction& tx) const { int64_t nDebit = 0; @@ -377,7 +388,7 @@ public: int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } // Get wallet transactions that conflict with given transaction (spend same outputs) - std::set GetConflicts(const uint256& txid) const; + std::set GetConflicts(const uint256& txid, bool includeEquivalent) const; /** Address book entry changed. * @note called with lock cs_wallet held. @@ -699,7 +710,7 @@ public: void RelayWalletTransaction(); - std::set GetConflicts() const; + std::set GetConflicts(bool includeEquivalent=true) const; }; From 9004798e62e987ddf50030b17fa1881b63dd5e45 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Thu, 26 Jun 2014 18:31:40 -0700 Subject: [PATCH 261/336] Add -respendnotify option and new RPC data -respendnotify= Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID) Add respendsobserved array to gettransaction, listtransactions, and listsinceblock RPCs. This omits the malleated clones that are included in the walletconflicts array. Add RPC help for respendsobserved and walletconflicts (help was missing for the latter). --- contrib/debian/manpages/bitcoin-qt.1 | 3 +++ src/init.cpp | 1 + src/rpcwallet.cpp | 22 ++++++++++++++++++++++ src/wallet.cpp | 8 ++++++++ 4 files changed, 34 insertions(+) diff --git a/contrib/debian/manpages/bitcoin-qt.1 b/contrib/debian/manpages/bitcoin-qt.1 index cd478b1875..25a423f9c4 100644 --- a/contrib/debian/manpages/bitcoin-qt.1 +++ b/contrib/debian/manpages/bitcoin-qt.1 @@ -139,6 +139,9 @@ Execute command when the best block changes (%s in cmd is replaced by block hash \fB\-walletnotify=\fR Execute command when a wallet transaction changes (%s in cmd is replaced by TxID) .TP +\fB\-respendnotify=\fR +Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID) +.TP \fB\-alertnotify=\fR Execute command when a relevant alert is received (%s in cmd is replaced by message) .TP diff --git a/src/init.cpp b/src/init.cpp index bd732753e4..3d0c03328f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -260,6 +260,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; strUsage += " -wallet= " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; strUsage += " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; + strUsage += " -respendnotify= " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n"; strUsage += " -zapwallettxes= " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n"; strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; #endif diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 4f27cef087..38e96133b4 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -58,6 +58,10 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); entry.push_back(Pair("walletconflicts", conflicts)); + Array respends; + BOOST_FOREACH(const uint256& respend, wtx.GetConflicts(false)) + respends.push_back(respend.GetHex()); + entry.push_back(Pair("respendsobserved", respends)); entry.push_back(Pair("time", wtx.GetTxTime())); entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue) @@ -1211,6 +1215,12 @@ Value listtransactions(const Array& params, bool fHelp) " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n" " category of transactions.\n" " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n" + " \"walletconflicts\" : [\n" + " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n" + " ],\n" + " \"respendsobserved\" : [\n" + " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n" + " ],\n" " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n" " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n" " for 'send' and 'receive' category of transactions.\n" @@ -1376,6 +1386,12 @@ Value listsinceblock(const Array& params, bool fHelp) " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n" " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" " \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n" + " \"walletconflicts\" : [\n" + " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n" + " ],\n" + " \"respendsobserved\" : [\n" + " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n" + " ],\n" " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n" " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n" " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" @@ -1448,6 +1464,12 @@ Value gettransaction(const Array& params, bool fHelp) " \"blockindex\" : xx, (numeric) The block index\n" " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n" " \"txid\" : \"transactionid\", (string) The transaction id.\n" + " \"walletconflicts\" : [\n" + " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n" + " ],\n" + " \"respendsobserved\" : [\n" + " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n" + " ],\n" " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n" " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n" " \"details\" : [\n" diff --git a/src/wallet.cpp b/src/wallet.cpp index 79cc5ba3c9..91910c6ea9 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -600,6 +600,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) if (IsFromMe(txConflict) || IsMine(txConflict)) { NotifyTransactionChanged(this, conflictHash, CT_GOT_CONFLICT); //Throws dialog + // external respend notify + std::string strCmd = GetArg("-respendnotify", ""); + if (!strCmd.empty()) + { + boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); + boost::replace_all(strCmd, "%t", conflictHash.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } } } } From 9fa53dd3bdc6f62b16a7c2b970449c8c35f4c41b Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Fri, 27 Jun 2014 07:49:27 -0700 Subject: [PATCH 262/336] Add release notes entry --- doc/release-notes.md | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 9272d427cd..e68e12310e 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -19,3 +19,49 @@ estimate. Statistics used to estimate fees and priorities are saved in the data directory in the 'fee_estimates.dat' file just before program shutdown, and are read in at startup. + +Double-Spend Relay and Alerts +============================= +VERY IMPORTANT: *It has never been safe, and remains unsafe, to rely* +*on unconfirmed transactions.* + +Relay +----- +When an attempt is seen on the network to spend the same unspent funds +more than once, it is no longer ignored. Instead, it is broadcast, to +serve as an alert. This broadcast is subject to protections against +denial-of-service attacks. + +Wallets and other bitcoin services should alert their users to +double-spends that affect them. Merchants and other users may have +enough time to withhold goods or services when payment becomes +uncertain, until confirmation. + +Bitcoin Core Wallet Alerts +-------------------------- +The Bitcoin Core wallet now makes respend attempts visible in several +ways. + +If you are online, and a respend affecting one of your wallet +transactions is seen, a notification is immediately issued to the +command registered with `-respendnotify=`. Additionally, if +using the GUI: + - An alert box is immediately displayed. + - The affected wallet transaction is highlighted in red until it is + confirmed (and it may never be confirmed). + +A `respendsobserved` array is added to `gettransaction`, `listtransactions`, +and `listsinceblock` RPC results. + +Warning +------- +*If you rely on an unconfirmed transaction, these change do VERY* +*LITTLE to protect you from a malicious double-spend, because:* + + - You may learn about the respend too late to avoid doing whatever + you were being paid for + - Using other relay rules, a double-spender can craft his crime to + resist broadcast + - Miners can choose which conflicting spend to confirm, and some + miners may not confirmg the first acceptable spend they see + From 7a19efe04069d9a1e251cdc94b25184f76d9d901 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Fri, 27 Jun 2014 16:47:33 -0700 Subject: [PATCH 263/336] Formatting, spelling, comment fixes. --- doc/release-notes.md | 2 +- src/main.cpp | 6 ++---- src/qt/transactionrecord.h | 13 ++++++++++--- src/qt/transactiontablemodel.cpp | 4 ++-- src/qt/walletmodel.cpp | 14 +++++++------- src/wallet.cpp | 2 +- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index e68e12310e..3a4079e437 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -63,5 +63,5 @@ Warning - Using other relay rules, a double-spender can craft his crime to resist broadcast - Miners can choose which conflicting spend to confirm, and some - miners may not confirmg the first acceptable spend they see + miners may not confirm the first acceptable spend they see diff --git a/src/main.cpp b/src/main.cpp index 48237c1b54..df810f575f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -852,7 +852,6 @@ bool RateLimitExceeded(double& dCount, int64_t& nLastTime, int64_t nLimit, unsig LOCK(csLimiter); - // Use an exponentially decaying ~10-minute window: dCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime)); nLastTime = nNow; if (dCount >= nLimit*10*1000) @@ -973,7 +972,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa static int64_t nLastFreeTime; static int64_t nFreeLimit = GetArg("-limitfreerelay", 15); - if (RateLimitExceeded(dFreeCount, nLastFreeTime, nFreeLimit, nSize)) + if (RateLimitExceeded(dFreeCount, nLastFreeTime, nFreeLimit, nSize)) return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "insufficient priority"); @@ -1000,8 +999,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } -static void -RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) +static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) { // Relaying double-spend attempts to our peers lets them detect when // somebody might be trying to cheat them. However, blindly relaying diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 4c2847144a..37679cebfa 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -19,10 +19,17 @@ class TransactionStatus { public: TransactionStatus(): - countsForBalance(false), sortKey(""), - matures_in(0), status(Offline), hasConflicting(false), depth(0), open_for(0), cur_num_blocks(-1), + countsForBalance(false), + sortKey(""), + matures_in(0), + status(Offline), + hasConflicting(false), + depth(0), + open_for(0), + cur_num_blocks(-1), cur_num_conflicts(-1) - { } + { + } enum Status { Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index eb5c3abdbc..d7f4c043cf 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -538,9 +538,9 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const case Qt::TextAlignmentRole: return column_alignments[index.column()]; case Qt::BackgroundColorRole: - if (rec->status.hasConflicting) + if (rec->status.hasConflicting) return COLOR_HASCONFLICTING_BG; - break; + break; case Qt::ForegroundRole: if (rec->status.hasConflicting) return COLOR_HASCONFLICTING; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 3d6f2ab9ba..defc815def 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -138,13 +138,13 @@ void WalletModel::checkBalanceChanged() void WalletModel::updateTransaction(const QString &hash, int status) { - if (status == CT_GOT_CONFLICT) - { - emit message(tr("Conflict Received"), - tr("WARNING: Transaction may never be confirmed. Its input was seen being spent by another transaction on the network. Wait for confirmation!"), - CClientUIInterface::MSG_WARNING); - return; - } + if (status == CT_GOT_CONFLICT) + { + emit message(tr("Conflict Received"), + tr("WARNING: Transaction may never be confirmed. Its input was seen being spent by another transaction on the network. Wait for confirmation!"), + CClientUIInterface::MSG_WARNING); + return; + } if(transactionTableModel) transactionTableModel->updateTransaction(hash, status); diff --git a/src/wallet.cpp b/src/wallet.cpp index 91910c6ea9..daca7ac04b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -637,7 +637,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl bool fIsConflicting = IsConflicting(tx); if (fIsConflicting) - nConflictsReceived++; + nConflictsReceived++; if (fExisted || IsMine(tx) || IsFromMe(tx) || fIsConflicting) { From 0dd5d3a00906d8a0f16d6eac62b63c9bb2da1391 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Tue, 1 Apr 2014 13:02:04 +0800 Subject: [PATCH 264/336] Show only one zero instead of many when getblocks request received with a hashStop of uint256(0) --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index d86fd3a24d..590714b1fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3652,7 +3652,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pindex) pindex = chainActive.Next(pindex); int nLimit = 500; - LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), nLimit); + LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop==uint256(0) ? "end" : hashStop.ToString(), nLimit); for (; pindex; pindex = chainActive.Next(pindex)) { if (pindex->GetBlockHash() == hashStop) From 6ecf3edfee13f47a920ea6ea7b42b96d0bbbd5fd Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Fri, 27 Jun 2014 11:03:24 +0700 Subject: [PATCH 265/336] Display unknown commands received. --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index d86fd3a24d..3ffdd63923 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4041,6 +4041,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else { // Ignore unknown commands for extensibility + LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); } From 3f1ea918a87f7d4cbb6a4e7504e284365e66902e Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Sat, 28 Jun 2014 14:38:37 +0800 Subject: [PATCH 266/336] doc: Add historical release notes for 0.9.2 Also includes 0.9.2.1 --- doc/release-notes/release-notes-0.9.2.1.md | 207 +++++++++++++++++++++ doc/release-notes/release-notes-0.9.2.md | 207 +++++++++++++++++++++ 2 files changed, 414 insertions(+) create mode 100644 doc/release-notes/release-notes-0.9.2.1.md create mode 100644 doc/release-notes/release-notes-0.9.2.md diff --git a/doc/release-notes/release-notes-0.9.2.1.md b/doc/release-notes/release-notes-0.9.2.1.md new file mode 100644 index 0000000000..3168ad1a5a --- /dev/null +++ b/doc/release-notes/release-notes-0.9.2.1.md @@ -0,0 +1,207 @@ +Bitcoin Core version 0.9.2.1 is now available from: + + https://bitcoin.org/bin/0.9.2.1/ + +This is a new minor version release, bringing mostly bug fixes and some minor +improvements. OpenSSL has been updated because of a security issue (CVE-2014-0224). +Upgrading to this release is recommended. + +Please report bugs using the issue tracker at github: + + https://github.com/bitcoin/bitcoin/issues + +How to Upgrade +-------------- + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or +bitcoind/bitcoin-qt (on Linux). + +If you are upgrading from version 0.7.2 or earlier, the first time you run +0.9.2.1 your blockchain files will be re-indexed, which will take anywhere from +30 minutes to several hours, depending on the speed of your machine. + +Downgrading warnings +-------------------- + +The 'chainstate' for this release is not always compatible with previous +releases, so if you run 0.9.x and then decide to switch back to a +0.8.x release you might get a blockchain validation error when starting the +old release (due to 'pruned outputs' being omitted from the index of +unspent transaction outputs). + +Running the old release with the -reindex option will rebuild the chainstate +data structures and correct the problem. + +Also, the first time you run a 0.8.x release on a 0.9 wallet it will rescan +the blockchain for missing spent coins, which will take a long time (tens +of minutes on a typical machine). + +Important changes +================== + +Gitian OSX build +----------------- + +The deterministic build system that was already used for Windows and Linux +builds is now used for OSX as well. Although the resulting executables have +been tested quite a bit, there could be possible regressions. Be sure to report +these on the Github bug tracker mentioned above. + +Compatibility of Linux build +----------------------------- + +For Linux we now build against Qt 4.6, and filter the symbols for libstdc++ and glibc. +This brings back compatibility with + +- Debian 6+ / Tails +- Ubuntu 10.04 +- CentOS 6.5 + +0.9.2 - 0.9.2.1 Release notes +======================= + +The OpenSSL dependency in the gitian builds has been upgraded to 1.0.1h because of CVE-2014-0224. + +RPC: + +- Add `getwalletinfo`, `getblockchaininfo` and `getnetworkinfo` calls (will replace hodge-podge `getinfo` at some point) +- Add a `relayfee` field to `getnetworkinfo` +- Fix RPC related shutdown hangs and leaks +- Always show syncnode in `getpeerinfo` +- `sendrawtransaction`: report the reject code and reason, and make it possible to re-send transactions that are already in the mempool +- `getmininginfo` show right genproclimit + +Command-line options: + +- Fix `-printblocktree` output +- Show error message if ReadConfigFile fails + +Block-chain handling and storage: + +- Fix for GetBlockValue() after block 13,440,000 (BIP42) +- Upgrade leveldb to 1.17 + +Protocol and network code: + +- Per-peer block download tracking and stalled download detection +- Add new DNS seed from bitnodes.io +- Prevent socket leak in ThreadSocketHandler and correct some proxy related socket leaks +- Use pnode->nLastRecv as sync score (was the wrong way around) + +Wallet: + +- Make GetAvailableCredit run GetHash() only once per transaction (performance improvement) +- Lower paytxfee warning threshold from 0.25 BTC to 0.01 BTC +- Fix importwallet nTimeFirstKey (trigger necessary rescans) +- Log BerkeleyDB version at startup +- CWallet init fix + +Build system: + +- Add OSX build descriptors to gitian +- Fix explicit --disable-qt-dbus +- Don't require db_cxx.h when compiling with wallet disabled and GUI enabled +- Improve missing boost error reporting +- Upgrade miniupnpc version to 1.9 +- gitian-linux: --enable-glibc-back-compat for binary compatibility with old distributions +- gitian: don't export any symbols from executable +- gitian: build against Qt 4.6 +- devtools: add script to check symbols from Linux gitian executables +- Remove build-time no-IPv6 setting + +GUI: + +- Fix various coin control visual issues +- Show number of in/out connections in debug console +- Show weeks as well as years behind for long timespans behind +- Enable and disable the Show and Remove buttons for requested payments history based on whether any entry is selected. +- Show also value for options overridden on command line in options dialog +- Fill in label from address book also for URIs +- Fixes feel when resizing the last column on tables (issue #2862) +- Fix ESC in disablewallet mode +- Add expert section to wallet tab in optionsdialog +- Do proper boost::path conversion (fixes unicode in datadir) +- Only override -datadir if different from the default (fixes -datadir in config file) +- Show rescan progress at start-up +- Show importwallet progress +- Get required locks upfront in polling functions (avoids hanging on locks) +- Catch Windows shutdown events while client is running +- Optionally add third party links to transaction context menu +- Check for !pixmap() before trying to export QR code (avoids crashes when no QR code could be generated) +- Fix "Start bitcoin on system login" + +Miscellaneous: + +- Replace non-threadsafe C functions (gmtime, strerror and setlocale) +- Add missing cs_main and wallet locks +- Avoid exception at startup when system locale not recognized +- Changed bitrpc.py's raw_input to getpass for passwords to conceal characters during command line input +- devtools: add a script to fetch and postprocess translations + +Credits +-------- + +Thanks to everyone who contributed to this release: + +- Addy Yeow +- Altoidnerd +- Andrea D'Amore +- Andreas Schildbach +- Bardi Harborow +- Brandon Dahler +- Bryan Bishop +- Chris Beams +- Christian von Roques +- Cory Fields +- Cozz Lovan +- daniel +- Daniel Newton +- David A. Harding +- ditto-b +- duanemoody +- Eric S. Bullington +- Fabian Raetz +- Gavin Andresen +- Gregory Maxwell +- gubatron +- Haakon Nilsen +- harry +- Hector Jusforgues +- Isidoro Ghezzi +- Jeff Garzik +- Johnathan Corgan +- jtimon +- Kamil Domanski +- langerhans +- Luke Dashjr +- Manuel Araoz +- Mark Friedenbach +- Matt Corallo +- Matthew Bogosian +- Meeh +- Michael Ford +- Michagogo +- Mikael Wikman +- Mike Hearn +- olalonde +- paveljanik +- peryaudo +- Philip Kaufmann +- philsong +- Pieter Wuille +- R E Broadley +- richierichrawr +- Rune K. Svendsen +- rxl +- shshshsh +- Simon de la Rouviere +- Stuart Cardall +- super3 +- Telepatheic +- Thomas Zander +- Torstein Husebø +- Warren Togami +- Wladimir J. van der Laan +- Yoichi Hirai diff --git a/doc/release-notes/release-notes-0.9.2.md b/doc/release-notes/release-notes-0.9.2.md new file mode 100644 index 0000000000..a2749e549f --- /dev/null +++ b/doc/release-notes/release-notes-0.9.2.md @@ -0,0 +1,207 @@ +Bitcoin Core version 0.9.2 is now available from: + + https://bitcoin.org/bin/0.9.2/ + +This is a new minor version release, bringing mostly bug fixes and some minor +improvements. OpenSSL has been updated because of a security issue (CVE-2014-0224). +Upgrading to this release is recommended. + +Please report bugs using the issue tracker at github: + + https://github.com/bitcoin/bitcoin/issues + +How to Upgrade +-------------- + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or +bitcoind/bitcoin-qt (on Linux). + +If you are upgrading from version 0.7.2 or earlier, the first time you run +0.9.2 your blockchain files will be re-indexed, which will take anywhere from +30 minutes to several hours, depending on the speed of your machine. + +Downgrading warnings +-------------------- + +The 'chainstate' for this release is not always compatible with previous +releases, so if you run 0.9.x and then decide to switch back to a +0.8.x release you might get a blockchain validation error when starting the +old release (due to 'pruned outputs' being omitted from the index of +unspent transaction outputs). + +Running the old release with the -reindex option will rebuild the chainstate +data structures and correct the problem. + +Also, the first time you run a 0.8.x release on a 0.9 wallet it will rescan +the blockchain for missing spent coins, which will take a long time (tens +of minutes on a typical machine). + +Important changes +================== + +Gitian OSX build +----------------- + +The deterministic build system that was already used for Windows and Linux +builds is now used for OSX as well. Although the resulting executables have +been tested quite a bit, there could be possible regressions. Be sure to report +these on the Github bug tracker mentioned above. + +Compatibility of Linux build +----------------------------- + +For Linux we now build against Qt 4.6, and filter the symbols for libstdc++ and glibc. +This brings back compatibility with + +- Debian 6+ / Tails +- Ubuntu 10.04 +- CentOS 6.5 + +0.9.2 Release notes +======================= + +The OpenSSL dependency in the gitian builds has been upgraded to 1.0.1h because of CVE-2014-0224. + +RPC: + +- Add `getwalletinfo`, `getblockchaininfo` and `getnetworkinfo` calls (will replace hodge-podge `getinfo` at some point) +- Add a `relayfee` field to `getnetworkinfo` +- Fix RPC related shutdown hangs and leaks +- Always show syncnode in `getpeerinfo` +- `sendrawtransaction`: report the reject code and reason, and make it possible to re-send transactions that are already in the mempool +- `getmininginfo` show right genproclimit + +Command-line options: + +- Fix `-printblocktree` output +- Show error message if ReadConfigFile fails + +Block-chain handling and storage: + +- Fix for GetBlockValue() after block 13,440,000 (BIP42) +- Upgrade leveldb to 1.17 + +Protocol and network code: + +- Per-peer block download tracking and stalled download detection +- Add new DNS seed from bitnodes.io +- Prevent socket leak in ThreadSocketHandler and correct some proxy related socket leaks +- Use pnode->nLastRecv as sync score (was the wrong way around) + +Wallet: + +- Make GetAvailableCredit run GetHash() only once per transaction (performance improvement) +- Lower paytxfee warning threshold from 0.25 BTC to 0.01 BTC +- Fix importwallet nTimeFirstKey (trigger necessary rescans) +- Log BerkeleyDB version at startup +- CWallet init fix + +Build system: + +- Add OSX build descriptors to gitian +- Fix explicit --disable-qt-dbus +- Don't require db_cxx.h when compiling with wallet disabled and GUI enabled +- Improve missing boost error reporting +- Upgrade miniupnpc version to 1.9 +- gitian-linux: --enable-glibc-back-compat for binary compatibility with old distributions +- gitian: don't export any symbols from executable +- gitian: build against Qt 4.6 +- devtools: add script to check symbols from Linux gitian executables +- Remove build-time no-IPv6 setting + +GUI: + +- Fix various coin control visual issues +- Show number of in/out connections in debug console +- Show weeks as well as years behind for long timespans behind +- Enable and disable the Show and Remove buttons for requested payments history based on whether any entry is selected. +- Show also value for options overridden on command line in options dialog +- Fill in label from address book also for URIs +- Fixes feel when resizing the last column on tables (issue #2862) +- Fix ESC in disablewallet mode +- Add expert section to wallet tab in optionsdialog +- Do proper boost::path conversion (fixes unicode in datadir) +- Only override -datadir if different from the default (fixes -datadir in config file) +- Show rescan progress at start-up +- Show importwallet progress +- Get required locks upfront in polling functions (avoids hanging on locks) +- Catch Windows shutdown events while client is running +- Optionally add third party links to transaction context menu +- Check for !pixmap() before trying to export QR code (avoids crashes when no QR code could be generated) +- Fix "Start bitcoin on system login" + +Miscellaneous: + +- Replace non-threadsafe C functions (gmtime, strerror and setlocale) +- Add missing cs_main and wallet locks +- Avoid exception at startup when system locale not recognized +- Changed bitrpc.py's raw_input to getpass for passwords to conceal characters during command line input +- devtools: add a script to fetch and postprocess translations + +Credits +-------- + +Thanks to everyone who contributed to this release: + +- Addy Yeow +- Altoidnerd +- Andrea D'Amore +- Andreas Schildbach +- Bardi Harborow +- Brandon Dahler +- Bryan Bishop +- Chris Beams +- Christian von Roques +- Cory Fields +- Cozz Lovan +- daniel +- Daniel Newton +- David A. Harding +- ditto-b +- duanemoody +- Eric S. Bullington +- Fabian Raetz +- Gavin Andresen +- Gregory Maxwell +- gubatron +- Haakon Nilsen +- harry +- Hector Jusforgues +- Isidoro Ghezzi +- Jeff Garzik +- Johnathan Corgan +- jtimon +- Kamil Domanski +- langerhans +- Luke Dashjr +- Manuel Araoz +- Mark Friedenbach +- Matt Corallo +- Matthew Bogosian +- Meeh +- Michael Ford +- Michagogo +- Mikael Wikman +- Mike Hearn +- olalonde +- paveljanik +- peryaudo +- Philip Kaufmann +- philsong +- Pieter Wuille +- R E Broadley +- richierichrawr +- Rune K. Svendsen +- rxl +- shshshsh +- Simon de la Rouviere +- Stuart Cardall +- super3 +- Telepatheic +- Thomas Zander +- Torstein Husebø +- Warren Togami +- Wladimir J. van der Laan +- Yoichi Hirai From 92ddf2c0dd59de514337381999c392f35c1cdf1b Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Sat, 28 Jun 2014 16:43:07 +0800 Subject: [PATCH 267/336] Update OS X build instructions Update OpenSSL version Homebrew is now the preferred dependancy manager --- doc/build-osx.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/doc/build-osx.md b/doc/build-osx.md index 0de5c792e9..1e38326d86 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -22,7 +22,7 @@ Xcode 4.3 or later, you'll need to install its command line tools. This can be done in `Xcode > Preferences > Downloads > Components` and generally must be re-done or updated every time Xcode is updated. -There's an assumption that you already have `git` installed, as well. If +There's also an assumption that you already have `git` installed. If not, it's the path of least resistance to install [Github for Mac](https://mac.github.com/) (OS X 10.7+) or [Git for OS X](https://code.google.com/p/git-osx-installer/). It is also @@ -30,11 +30,8 @@ available via Homebrew or MacPorts. You will also need to install [Homebrew](http://brew.sh) or [MacPorts](https://www.macports.org/) in order to install library -dependencies. It's largely a religious decision which to choose, but, as of -December 2012, MacPorts is a little easier because you can just install the -dependencies immediately - no other work required. If you're unsure, read -the instructions through first in order to assess what you want to do. -Homebrew is a little more popular among those newer to OS X. +dependencies. It's largely a religious decision which to choose, however, Homebrew +is now used for building release versions. The installation of the actual dependencies is covered in the Instructions sections below. @@ -44,8 +41,6 @@ Instructions: MacPorts ### Install dependencies -Installing the dependencies using MacPorts is very straightforward. - sudo port install boost db48@+no_java openssl miniupnpc autoconf pkgconfig automake Optional: install Qt4 @@ -80,7 +75,7 @@ Note: After you have installed the dependencies, you should check that the Homeb openssl version -into Terminal. You should see OpenSSL 1.0.1f 6 Jan 2014. +into Terminal. You should see OpenSSL 1.0.1h 5 Jun 2014. If not, you can ensure that the Homebrew OpenSSL is correctly linked by running @@ -103,7 +98,7 @@ PATH. ./configure make -3. It is a good idea to build and run the unit tests, too: +3. It is also a good idea to build and run the unit tests: make check @@ -131,7 +126,7 @@ For MacPorts, that means editing your macports.conf and setting ... and then uninstalling and re-installing, or simply rebuilding, all ports. As of December 2012, the `boost` port does not obey `macosx_deployment_target`. -Download `http://gavinandresen-bitcoin.s3.amazonaws.com/boost_macports_fix.zip` +Download `https://gavinandresen-bitcoin.s3.amazonaws.com/boost_macports_fix.zip` for a fix. Once dependencies are compiled, see release-process.md for how the Bitcoin-Qt.app @@ -149,13 +144,14 @@ commands: echo -e "rpcuser=bitcoinrpc\nrpcpassword=$(xxd -l 16 -p /dev/urandom)" > "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" chmod 600 "/Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf" -When next you run it, it will start downloading the blockchain, but it won't +The next time you run it, it will start downloading the blockchain, but it won't output anything while it's doing this. This process may take several hours; you can monitor its process by looking at the debug.log file, like this: tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log Other commands: +------- ./bitcoind -daemon # to start the bitcoin daemon. ./bitcoin-cli --help # for a list of command-line options. From 645d497aa0010525441ce409e8e6d327a157ab39 Mon Sep 17 00:00:00 2001 From: jtimon Date: Fri, 27 Jun 2014 13:28:08 +0200 Subject: [PATCH 268/336] Replace HexBits with strprintf --- src/rpcblockchain.cpp | 2 +- src/rpcmining.cpp | 2 +- src/rpcserver.cpp | 10 ---------- src/rpcserver.h | 1 - 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 580c6bd5ba..a67f266a13 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -66,7 +66,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex) result.push_back(Pair("tx", txs)); result.push_back(Pair("time", block.GetBlockTime())); result.push_back(Pair("nonce", (uint64_t)block.nNonce)); - result.push_back(Pair("bits", HexBits(block.nBits))); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 98caf704ee..db60ef3592 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -443,7 +443,7 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); result.push_back(Pair("curtime", (int64_t)pblock->nTime)); - result.push_back(Pair("bits", HexBits(pblock->nBits))); + result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); return result; diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 54043458d5..6a87c8bf99 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -97,16 +97,6 @@ Value ValueFromAmount(int64_t 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)); -} - uint256 ParseHashV(const Value& v, string strName) { string strHex; diff --git a/src/rpcserver.h b/src/rpcserver.h index fcd293663f..01e77163c4 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -116,7 +116,6 @@ extern int64_t nWalletUnlockTime; extern int64_t AmountFromValue(const json_spirit::Value& value); extern json_spirit::Value ValueFromAmount(int64_t amount); extern double GetDifficulty(const CBlockIndex* blockindex = NULL); -extern std::string HexBits(unsigned int nBits); extern std::string HelpRequiringPassphrase(); extern std::string HelpExampleCli(std::string methodname, std::string args); extern std::string HelpExampleRpc(std::string methodname, std::string args); From d618965eb8163544d97a213b1c0e3f629c59669b Mon Sep 17 00:00:00 2001 From: Drak Date: Sat, 28 Jun 2014 12:41:19 +0100 Subject: [PATCH 269/336] Add note about PPA to build instructions --- doc/build-unix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build-unix.md b/doc/build-unix.md index 9d4b662d07..0f381d56c5 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -91,7 +91,7 @@ To enable the change run sudo apt-get update -for other Ubuntu & Debian: +for other Debian & Ubuntu (with ppa): sudo apt-get install libdb4.8-dev libdb4.8++-dev From 675bcd5892bc6f8997e999fb2c7a7e70e449063e Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Sat, 28 Jun 2014 20:57:46 +0800 Subject: [PATCH 270/336] Correct comment for 15-of-15 p2sh script size The original comment forgets to account for the script push which will need an OP_PUSHDATA2 + 2-bytes for the 513 script bytes. props davecgh fixes #4224 --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 590714b1fc..86f9a04a3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -488,7 +488,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason) // Treat non-final transactions as non-standard to prevent a specific type // of double-spend attack, as well as DoS attacks. (if the transaction // can't be mined, the attacker isn't expending resources broadcasting it) - // Basically we don't want to propagate transactions that can't included in + // Basically we don't want to propagate transactions that can't be included in // the next block. // // However, IsFinalTx() is confusing... Without arguments, it uses @@ -521,7 +521,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason) { // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed // keys. (remember the 520 byte limit on redeemScript size) That works - // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624 + // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 // bytes of scriptSig, which we round off to 1650 bytes for some minor // future-proofing. That's also enough to spend a 20-of-20 // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not From de79aaa7a9ad07664461ee8735299aa68c630969 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 28 Jun 2014 17:35:22 +0200 Subject: [PATCH 271/336] Move non-trivial uint256.h methods to uint256.cpp --- src/Makefile.am | 1 + src/uint256.cpp | 292 ++++++++++++++++++++++++++++++++++++++++++++++++ src/uint256.h | 262 +++---------------------------------------- src/util.cpp | 5 + src/util.h | 1 + 5 files changed, 316 insertions(+), 245 deletions(-) create mode 100644 src/uint256.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 3643e60201..9c7b294d35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,6 +192,7 @@ libbitcoin_util_a_SOURCES = \ chainparamsbase.cpp \ rpcprotocol.cpp \ sync.cpp \ + uint256.cpp \ util.cpp \ version.cpp \ compat/glibc_sanity.cpp \ diff --git a/src/uint256.cpp b/src/uint256.cpp new file mode 100644 index 0000000000..3392f1e9bc --- /dev/null +++ b/src/uint256.cpp @@ -0,0 +1,292 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "uint256.h" +#include "util.h" + +#include +#include + +template +base_uint::base_uint(const std::string& str) +{ + SetHex(str); +} + +template +base_uint::base_uint(const std::vector& vch) +{ + if (vch.size() != sizeof(pn)) + throw uint_error("Converting vector of wrong size to base_uint"); + memcpy(pn, &vch[0], sizeof(pn)); +} + +template +base_uint& base_uint::operator<<=(unsigned int shift) +{ + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i+k+1 < WIDTH && shift != 0) + pn[i+k+1] |= (a.pn[i] >> (32-shift)); + if (i+k < WIDTH) + pn[i+k] |= (a.pn[i] << shift); + } + return *this; +} + +template +base_uint& base_uint::operator>>=(unsigned int shift) +{ + base_uint a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i-k-1 >= 0 && shift != 0) + pn[i-k-1] |= (a.pn[i] << (32-shift)); + if (i-k >= 0) + pn[i-k] |= (a.pn[i] >> shift); + } + return *this; +} + +template +base_uint& base_uint::operator*=(uint32_t b32) +{ + uint64_t carry = 0; + for (int i = 0; i < WIDTH; i++) { + uint64_t n = carry + (uint64_t)b32 * pn[i]; + pn[i] = n & 0xffffffff; + carry = n >> 32; + } + return *this; +} + +template +base_uint& base_uint::operator*=(const base_uint& b) +{ + base_uint a = *this; + *this = 0; + for (int j = 0; j < WIDTH; j++) { + uint64_t carry = 0; + for (int i = 0; i + j < WIDTH; i++) { + uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; + pn[i + j] = n & 0xffffffff; + carry = n >> 32; + } + } + return *this; +} + +template +base_uint& base_uint::operator/=(const base_uint& b) +{ + base_uint div = b; // make a copy, so we can shift. + base_uint num = *this; // make a copy, so we can subtract. + *this = 0; // the quotient. + int num_bits = num.bits(); + int div_bits = div.bits(); + if (div_bits == 0) + throw uint_error("Division by zero"); + if (div_bits > num_bits) // the result is certainly 0. + return *this; + int shift = num_bits - div_bits; + div <<= shift; // shift so that div and nun align. + while (shift >= 0) { + if (num >= div) { + num -= div; + pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. + } + div >>= 1; // shift back. + shift--; + } + // num now contains the remainder of the division. + return *this; +} + +template +int base_uint::CompareTo(const base_uint& b) const { + for (int i = WIDTH-1; i >= 0; i--) { + if (pn[i] < b.pn[i]) + return -1; + if (pn[i] > b.pn[i]) + return 1; + } + return 0; +} + +template +bool base_uint::EqualTo(uint64_t b) const { + for (int i = WIDTH-1; i >= 2; i--) { + if (pn[i]) + return false; + } + if (pn[1] != (b >> 32)) + return false; + if (pn[0] != (b & 0xfffffffful)) + return false; + return true; +} + +template +double base_uint::getdouble() const +{ + double ret = 0.0; + double fact = 1.0; + for (int i = 0; i < WIDTH; i++) { + ret += fact * pn[i]; + fact *= 4294967296.0; + } + return ret; +} + +template +std::string base_uint::GetHex() const +{ + char psz[sizeof(pn)*2 + 1]; + for (unsigned int i = 0; i < sizeof(pn); i++) + sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + return std::string(psz, psz + sizeof(pn)*2); +} + +template +void base_uint::SetHex(const char* psz) +{ + memset(pn,0,sizeof(pn)); + + // skip leading spaces + while (isspace(*psz)) + psz++; + + // skip 0x + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + + // hex string to uint + const char* pbegin = psz; + while (::HexDigit(*psz) != -1) + psz++; + psz--; + unsigned char* p1 = (unsigned char*)pn; + unsigned char* pend = p1 + WIDTH * 4; + while (psz >= pbegin && p1 < pend) { + *p1 = ::HexDigit(*psz--); + if (psz >= pbegin) { + *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + p1++; + } + } +} + +template +void base_uint::SetHex(const std::string& str) +{ + SetHex(str.c_str()); +} + +template +std::string base_uint::ToString() const +{ + return (GetHex()); +} + +template +unsigned int base_uint::bits() const +{ + for (int pos = WIDTH-1; pos >= 0; pos--) { + if (pn[pos]) { + for (int bits = 31; bits > 0; bits--) { + if (pn[pos] & 1< +template base_uint<160>::base_uint(const std::string&); +template base_uint<160>::base_uint(const std::vector&); +template base_uint<160>& base_uint<160>::operator<<=(unsigned int); +template base_uint<160>& base_uint<160>::operator>>=(unsigned int); +template base_uint<160>& base_uint<160>::operator*=(uint32_t b32); +template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b); +template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b); +template int base_uint<160>::CompareTo(const base_uint<160>&) const; +template bool base_uint<160>::EqualTo(uint64_t) const; +template double base_uint<160>::getdouble() const; +template std::string base_uint<160>::GetHex() const; +template std::string base_uint<160>::ToString() const; +template void base_uint<160>::SetHex(const char*); +template void base_uint<160>::SetHex(const std::string&); +template unsigned int base_uint<160>::bits() const; + +// Explicit instantiations for base_uint<256> +template base_uint<256>::base_uint(const std::string&); +template base_uint<256>::base_uint(const std::vector&); +template base_uint<256>& base_uint<256>::operator<<=(unsigned int); +template base_uint<256>& base_uint<256>::operator>>=(unsigned int); +template base_uint<256>& base_uint<256>::operator*=(uint32_t b32); +template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b); +template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b); +template int base_uint<256>::CompareTo(const base_uint<256>&) const; +template bool base_uint<256>::EqualTo(uint64_t) const; +template double base_uint<256>::getdouble() const; +template std::string base_uint<256>::GetHex() const; +template std::string base_uint<256>::ToString() const; +template void base_uint<256>::SetHex(const char*); +template void base_uint<256>::SetHex(const std::string&); +template unsigned int base_uint<256>::bits() const; + +// This implementation directly uses shifts instead of going +// through an intermediate MPI representation. +uint256& uint256::SetCompact(uint32_t nCompact, bool *pfNegative, bool *pfOverflow) +{ + int nSize = nCompact >> 24; + uint32_t nWord = nCompact & 0x007fffff; + if (nSize <= 3) { + nWord >>= 8*(3-nSize); + *this = nWord; + } else { + *this = nWord; + *this <<= 8*(nSize-3); + } + if (pfNegative) + *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; + if (pfOverflow) + *pfOverflow = nWord != 0 && ((nSize > 34) || + (nWord > 0xff && nSize > 33) || + (nWord > 0xffff && nSize > 32)); + return *this; +} + +uint32_t uint256::GetCompact(bool fNegative) const +{ + int nSize = (bits() + 7) / 8; + uint32_t nCompact = 0; + if (nSize <= 3) { + nCompact = GetLow64() << 8*(3-nSize); + } else { + uint256 bn = *this >> 8*(nSize-3); + nCompact = bn.GetLow64(); + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if (nCompact & 0x00800000) { + nCompact >>= 8; + nSize++; + } + assert((nCompact & ~0x007fffff) == 0); + assert(nSize < 256); + nCompact |= nSize << 24; + nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); + return nCompact; +} diff --git a/src/uint256.h b/src/uint256.h index 1acedd14bf..82db7758c9 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -9,18 +9,9 @@ #include #include #include -#include #include -#include #include -extern const signed char p_util_hexdigit[256]; // defined in util.cpp - -inline signed char HexDigit(char c) -{ - return p_util_hexdigit[(unsigned char)c]; -} - class uint_error : public std::runtime_error { public: explicit uint_error(const std::string& str) : std::runtime_error(str) {} @@ -62,17 +53,8 @@ public: pn[i] = 0; } - explicit base_uint(const std::string& str) - { - SetHex(str); - } - - explicit base_uint(const std::vector& vch) - { - if (vch.size() != sizeof(pn)) - throw uint_error("Converting vector of wrong size to base_uint"); - memcpy(pn, &vch[0], sizeof(pn)); - } + explicit base_uint(const std::string& str); + explicit base_uint(const std::vector& vch); bool operator!() const { @@ -99,16 +81,7 @@ public: return ret; } - double getdouble() const - { - double ret = 0.0; - double fact = 1.0; - for (int i = 0; i < WIDTH; i++) { - ret += fact * pn[i]; - fact *= 4294967296.0; - } - return ret; - } + double getdouble() const; base_uint& operator=(uint64_t b) { @@ -154,39 +127,8 @@ public: return *this; } - base_uint& operator<<=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i+k+1 < WIDTH && shift != 0) - pn[i+k+1] |= (a.pn[i] >> (32-shift)); - if (i+k < WIDTH) - pn[i+k] |= (a.pn[i] << shift); - } - return *this; - } - - base_uint& operator>>=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i-k-1 >= 0 && shift != 0) - pn[i-k-1] |= (a.pn[i] << (32-shift)); - if (i-k >= 0) - pn[i-k] |= (a.pn[i] >> shift); - } - return *this; - } + base_uint& operator<<=(unsigned int shift); + base_uint& operator>>=(unsigned int shift); base_uint& operator+=(const base_uint& b) { @@ -222,57 +164,9 @@ public: return *this; } - base_uint& operator*=(uint32_t b32) - { - uint64_t carry = 0; - for (int i = 0; i < WIDTH; i++) - { - uint64_t n = carry + (uint64_t)b32 * pn[i]; - pn[i] = n & 0xffffffff; - carry = n >> 32; - } - return *this; - } - - base_uint& operator*=(const base_uint& b) - { - base_uint a = *this; - *this = 0; - for (int j = 0; j < WIDTH; j++) { - uint64_t carry = 0; - for (int i = 0; i + j < WIDTH; i++) { - uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; - pn[i + j] = n & 0xffffffff; - carry = n >> 32; - } - } - return *this; - } - - base_uint& operator/=(const base_uint& b) - { - base_uint div = b; // make a copy, so we can shift. - base_uint num = *this; // make a copy, so we can subtract. - *this = 0; // the quotient. - int num_bits = num.bits(); - int div_bits = div.bits(); - if (div_bits == 0) - throw uint_error("Division by zero"); - if (div_bits > num_bits) // the result is certainly 0. - return *this; - int shift = num_bits - div_bits; - div <<= shift; // shift so that div and nun align. - while (shift >= 0) { - if (num >= div) { - num -= div; - pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result. - } - div >>= 1; // shift back. - shift--; - } - // num now contains the remainder of the division. - return *this; - } + base_uint& operator*=(uint32_t b32); + base_uint& operator*=(const base_uint& b); + base_uint& operator/=(const base_uint& b); base_uint& operator++() { @@ -308,27 +202,8 @@ public: return ret; } - int CompareTo(const base_uint& b) const { - for (int i = base_uint::WIDTH-1; i >= 0; i--) { - if (pn[i] < b.pn[i]) - return -1; - if (pn[i] > b.pn[i]) - return 1; - } - return 0; - } - - bool EqualTo(uint64_t b) const { - for (int i = base_uint::WIDTH-1; i >= 2; i--) { - if (pn[i]) - return false; - } - if (pn[1] != (b >> 32)) - return false; - if (pn[0] != (b & 0xfffffffful)) - return false; - return true; - } + int CompareTo(const base_uint& b) const; + bool EqualTo(uint64_t b) const; friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; } friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; } @@ -349,53 +224,10 @@ public: friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); } friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); } - std::string GetHex() const - { - char psz[sizeof(pn)*2 + 1]; - for (unsigned int i = 0; i < sizeof(pn); i++) - sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); - return std::string(psz, psz + sizeof(pn)*2); - } - - void SetHex(const char* psz) - { - memset(pn,0,sizeof(pn)); - - // skip leading spaces - while (isspace(*psz)) - psz++; - - // skip 0x - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - - // hex string to uint - const char* pbegin = psz; - while (::HexDigit(*psz) != -1) - psz++; - psz--; - unsigned char* p1 = (unsigned char*)pn; - unsigned char* pend = p1 + WIDTH * 4; - while (psz >= pbegin && p1 < pend) - { - *p1 = ::HexDigit(*psz--); - if (psz >= pbegin) - { - *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); - p1++; - } - } - } - - void SetHex(const std::string& str) - { - SetHex(str.c_str()); - } - - std::string ToString() const - { - return (GetHex()); - } + std::string GetHex() const; + void SetHex(const char* psz); + void SetHex(const std::string& str); + std::string ToString() const; unsigned char* begin() { @@ -424,19 +256,7 @@ public: // Returns the position of the highest bit set plus one, or zero if the // value is zero. - unsigned int bits() const - { - for (int pos = WIDTH-1; pos >= 0; pos--) { - if (pn[pos]) { - for (int bits = 31; bits > 0; bits--) { - if (pn[pos] & 1<> 24; - uint32_t nWord = nCompact & 0x007fffff; - if (nSize <= 3) - { - nWord >>= 8*(3-nSize); - *this = nWord; - } - else - { - *this = nWord; - *this <<= 8*(nSize-3); - } - if (pfNegative) - *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; - if (pfOverflow) - *pfOverflow = nWord != 0 && ((nSize > 34) || - (nWord > 0xff && nSize > 33) || - (nWord > 0xffff && nSize > 32)); - return *this; - } - - uint32_t GetCompact(bool fNegative = false) const - { - int nSize = (bits() + 7) / 8; - uint32_t nCompact = 0; - if (nSize <= 3) - nCompact = GetLow64() << 8*(3-nSize); - else - { - uint256 bn = *this >> 8*(nSize-3); - nCompact = bn.GetLow64(); - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if (nCompact & 0x00800000) - { - nCompact >>= 8; - nSize++; - } - assert((nCompact & ~0x007fffff) == 0); - assert(nSize < 256); - nCompact |= nSize << 24; - nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); - return nCompact; - } + uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); + uint32_t GetCompact(bool fNegative = false) const; }; #endif diff --git a/src/util.cpp b/src/util.cpp index 9e4b2b787e..e67c0dfd8a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -419,6 +419,11 @@ const signed char p_util_hexdigit[256] = -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; +signed char HexDigit(char c) +{ + return p_util_hexdigit[(unsigned char)c]; +} + bool IsHex(const string& str) { BOOST_FOREACH(char c, str) diff --git a/src/util.h b/src/util.h index 6057c72e66..707b8f2d76 100644 --- a/src/util.h +++ b/src/util.h @@ -156,6 +156,7 @@ bool ParseMoney(const char* pszIn, int64_t& nRet); std::string SanitizeString(const std::string& str); std::vector ParseHex(const char* psz); std::vector ParseHex(const std::string& str); +signed char HexDigit(char c); bool IsHex(const std::string& str); std::vector DecodeBase64(const char* p, bool* pfInvalid = NULL); std::string DecodeBase64(const std::string& str); From 16f33f163d4e2c10320a96a22bbab71c9a0df195 Mon Sep 17 00:00:00 2001 From: kazcw Date: Sat, 28 Jun 2014 18:14:36 -0700 Subject: [PATCH 272/336] fix RPC error replies After pull #4288, RPC messages indicating errors have a Content-Length unrelated to their actual contents, rendering bitcoin-cli and curl unable to decode the reply. This patch sets the Content-Length field based on the actual content returned. Additionally, pull #4288 clobbered the error descriptions provided in ErrorReply, which bitcoin-cli relies upon; this patch moves #4288 http-error descriptions to an HTTPError method, allowing HTTPReply to pass content on unchanged. --- src/rpcprotocol.cpp | 42 +++++++++++++++++++++++------------------- src/rpcprotocol.h | 2 ++ src/rpcserver.cpp | 8 ++++---- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 2cb4a35c4b..dd8692e802 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -54,8 +54,19 @@ static string rfc1123Time() return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime()); } -string HTTPReply(int nStatus, const string& strMsg, bool keepalive, - bool headersOnly, const char *contentType) +static const char *httpStatusDescription(int nStatus) +{ + switch (nStatus) { + case HTTP_OK: return "OK"; + case HTTP_BAD_REQUEST: return "Bad Request"; + case HTTP_FORBIDDEN: return "Forbidden"; + case HTTP_NOT_FOUND: return "Not Found"; + case HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error"; + default: return ""; + } +} + +string HTTPError(int nStatus, bool keepalive, bool headersOnly) { if (nStatus == HTTP_UNAUTHORIZED) return strprintf("HTTP/1.0 401 Authorization Required\r\n" @@ -75,20 +86,13 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive, "

401 Unauthorized.

\r\n" "\r\n", rfc1123Time(), FormatFullVersion()); - const char *cStatus; - if (nStatus == HTTP_OK) cStatus = "OK"; - else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request"; - else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden"; - else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; - else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; - else cStatus = ""; - - bool useInternalContent = false; - if (nStatus != HTTP_OK) { - contentType = "text/plain"; - useInternalContent = true; - } + return HTTPReply(nStatus, httpStatusDescription(nStatus), keepalive, + headersOnly, "text/plain"); +} +string HTTPReply(int nStatus, const string& strMsg, bool keepalive, + bool headersOnly, const char *contentType) +{ return strprintf( "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" @@ -99,14 +103,14 @@ string HTTPReply(int nStatus, const string& strMsg, bool keepalive, "\r\n" "%s", nStatus, - cStatus, + httpStatusDescription(nStatus), rfc1123Time(), keepalive ? "keep-alive" : "close", - strMsg.size(), + (headersOnly ? 0 : strMsg.size()), contentType, FormatFullVersion(), - (headersOnly ? "" : - (useInternalContent ? cStatus : strMsg.c_str()))); + (headersOnly ? "" : strMsg.c_str()) + ); } bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index f1317e9c28..5627077bfb 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -141,6 +141,8 @@ private: }; std::string HTTPPost(const std::string& strMsg, const std::map& mapRequestHeaders); +std::string HTTPError(int nStatus, bool keepalive, + bool headerOnly = false); std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive, bool headerOnly = false, const char *contentType = "application/json"); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 6a87c8bf99..f47b3385da 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -481,7 +481,7 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptorstream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush; + conn->stream() << HTTPError(HTTP_FORBIDDEN, false) << std::flush; conn->close(); } else { @@ -807,7 +807,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn, // Check authorization if (mapHeaders.count("authorization") == 0) { - conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush; return false; } @@ -820,7 +820,7 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn, if (mapArgs["-rpcpassword"].size() < 20) MilliSleep(250); - conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; + conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush; return false; } @@ -888,7 +888,7 @@ void ServiceConnection(AcceptedConnection *conn) if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun)) break; } else { - conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; + conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush; break; } } From ffebc1be43751050c0b35d7140ba127783708d13 Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Sun, 29 Jun 2014 13:20:19 +0800 Subject: [PATCH 273/336] Update verify.sh script to point to bitcoin.org Now that downloads are no longer hosted on Sourceforge, update the script to retrieve the binaries and signature file from bitcoin.org. --- contrib/verifysfbinaries/README.md | 2 +- contrib/verifysfbinaries/verify.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifysfbinaries/README.md index f646d1efd1..8c038865bd 100644 --- a/contrib/verifysfbinaries/README.md +++ b/contrib/verifysfbinaries/README.md @@ -1,5 +1,5 @@ ### Verify SF Binaries ### -This script attempts to download the signature file `SHA256SUMS.asc` from SourceForge. +This script attempts to download the signature file `SHA256SUMS.asc` from https://bitcoin.org. It first checks if the signature passes, and then downloads the files specified in the file, and checks if the hashes of these files match those that are specified in the signature file. diff --git a/contrib/verifysfbinaries/verify.sh b/contrib/verifysfbinaries/verify.sh index e92295661c..3eb4693883 100755 --- a/contrib/verifysfbinaries/verify.sh +++ b/contrib/verifysfbinaries/verify.sh @@ -1,6 +1,6 @@ #!/bin/bash -### This script attempts to download the signature file SHA256SUMS.asc from SourceForge +### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org ### It first checks if the signature passes, and then downloads the files specified in ### the file, and checks if the hashes of these files match those that are specified ### in the signature file. @@ -18,11 +18,11 @@ WORKINGDIR="/tmp/bitcoin" TMPFILE="hashes.tmp" #this URL is used if a version number is not specified as an argument to the script -SIGNATUREFILE="http://downloads.sourceforge.net/project/bitcoin/Bitcoin/bitcoin-0.9.0rc1/SHA256SUMS.asc" +SIGNATUREFILE="https://bitcoin.org/bin/0.9.2.1/SHA256SUMS.asc" SIGNATUREFILENAME="SHA256SUMS.asc" RCSUBDIR="test/" -BASEDIR="http://downloads.sourceforge.net/project/bitcoin/Bitcoin/" +BASEDIR="https://bitcoin.org/bin/" VERSIONPREFIX="bitcoin-" RCVERSIONSTRING="rc" @@ -62,7 +62,7 @@ WGETOUT=$(wget -N "$BASEDIR$SIGNATUREFILENAME" 2>&1) #and then see if wget completed successfully if [ $? -ne 0 ]; then echo "Error: couldn't fetch signature file. Have you specified the version number in the following format?" - echo "[bitcoin-]-[rc[0-9]] (example: bitcoin-0.7.1-rc1)" + echo "[bitcoin-]-[rc[0-9]] (example: bitcoin-0.9.2-rc1)" echo "wget output:" echo "$WGETOUT"|sed 's/^/\t/g' exit 2 From aa815647005bc8467f467c35a9e617794446cd64 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 23 Jun 2014 00:00:26 +0200 Subject: [PATCH 274/336] Track peers' available blocks --- src/main.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.h | 1 + src/rpcnet.cpp | 1 + 3 files changed, 48 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 336a5a9a86..dc68431282 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -207,6 +207,10 @@ struct CNodeState { std::string name; // List of asynchronously-determined block rejections to notify this peer about. std::vector rejects; + // The best known block we know this peer has announced. + CBlockIndex *pindexBestKnownBlock; + // The hash of the last unknown block this peer has announced. + uint256 hashLastUnknownBlock; list vBlocksInFlight; int nBlocksInFlight; list vBlocksToDownload; @@ -217,6 +221,8 @@ struct CNodeState { CNodeState() { nMisbehavior = 0; fShouldBan = false; + pindexBestKnownBlock = NULL; + hashLastUnknownBlock = uint256(0); nBlocksToDownload = 0; nBlocksInFlight = 0; nLastBlockReceive = 0; @@ -313,6 +319,39 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256 &hash) { mapBlocksInFlight[hash] = std::make_pair(nodeid, it); } +/** Check whether the last unknown block a peer advertized is not yet known. */ +void ProcessBlockAvailability(NodeId nodeid) { + CNodeState *state = State(nodeid); + assert(state != NULL); + + if (state->hashLastUnknownBlock != 0) { + map::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock); + if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) { + if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) + state->pindexBestKnownBlock = itOld->second; + state->hashLastUnknownBlock = uint256(0); + } + } +} + +/** Update tracking information about which blocks a peer is assumed to have. */ +void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { + CNodeState *state = State(nodeid); + assert(state != NULL); + + ProcessBlockAvailability(nodeid); + + map::iterator it = mapBlockIndex.find(hash); + if (it != mapBlockIndex.end() && it->second->nChainWork > 0) { + // An actually better block was announced. + if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) + state->pindexBestKnownBlock = it->second; + } else { + // An unknown block was announced; just assume that the latest one is the best one. + state->hashLastUnknownBlock = hash; + } +} + } // anon namespace bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { @@ -321,6 +360,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { if (state == NULL) return false; stats.nMisbehavior = state->nMisbehavior; + stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1; return true; } @@ -3613,6 +3653,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(inv.hash)); } + if (inv.type == MSG_BLOCK) + UpdateBlockAvailability(pfrom->GetId(), inv.hash); + // Track requests for our stuff g_signals.Inventory(inv.hash); } @@ -4359,6 +4402,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->fDisconnect = true; } + // Update knowledge of peer's block availability. + ProcessBlockAvailability(pto->GetId()); + // // Message: getdata (blocks) // diff --git a/src/main.h b/src/main.h index 0332db2163..9487078b74 100644 --- a/src/main.h +++ b/src/main.h @@ -185,6 +185,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa struct CNodeStateStats { int nMisbehavior; + int nSyncHeight; }; struct CDiskBlockPos diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index a54872ccc4..2d7abb2d58 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -134,6 +134,7 @@ Value getpeerinfo(const Array& params, bool fHelp) obj.push_back(Pair("startingheight", stats.nStartingHeight)); if (fStateStats) { obj.push_back(Pair("banscore", statestats.nMisbehavior)); + obj.push_back(Pair("syncheight", statestats.nSyncHeight)); } obj.push_back(Pair("syncnode", stats.fSyncNode)); From c9a0918330f31dcb1d5e86b56af63c3f521d3cf2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 25 Jun 2014 00:56:47 +0200 Subject: [PATCH 275/336] Add a skiplist to the CBlockIndex structure. This allows fast (O(log n)) access to far predecessor blocks. Use it to speed up CChain::FindFork and CChain::GetLocator. --- src/main.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.h | 14 +++++++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index dc68431282..41125cb577 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -414,8 +414,11 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { break; // Exponentially larger steps back, plus the genesis block. int nHeight = std::max(pindex->nHeight - nStep, 0); + // Jump back quickly to the same height as the chain. + if (pindex->nHeight > nHeight) + pindex = pindex->GetAncestor(nHeight); // In case pindex is not in this chain, iterate pindex->pprev to find blocks. - while (pindex->nHeight > nHeight && !Contains(pindex)) + while (!Contains(pindex)) pindex = pindex->pprev; // If pindex is in this chain, use direct height-based access. if (pindex->nHeight > nHeight) @@ -442,6 +445,8 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const { } CBlockIndex *CChain::FindFork(CBlockIndex *pindex) const { + if (pindex->nHeight > Height()) + pindex = pindex->GetAncestor(Height()); while (pindex && !Contains(pindex)) pindex = pindex->pprev; return pindex; @@ -2151,6 +2156,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block) { pindexNew->pprev = (*miPrev).second; pindexNew->nHeight = pindexNew->pprev->nHeight + 1; + pindexNew->BuildSkip(); } pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork(); pindexNew->RaiseValidity(BLOCK_VALID_TREE); @@ -2508,6 +2514,55 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns return (nFound >= nRequired); } +/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */ +int static inline InvertLowestOne(int n) { return n & (n - 1); } + +/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */ +int static inline GetSkipHeight(int height) { + if (height < 2) + return 0; + + // Determine which height to jump back to. Any number strictly lower than height is acceptable, + // but the following expression seems to perform well in simulations (max 110 steps to go back + // up to 2**18 blocks). + return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height); +} + +CBlockIndex* CBlockIndex::GetAncestor(int height) +{ + if (height > nHeight || height < 0) + return NULL; + + CBlockIndex* pindexWalk = this; + int heightWalk = nHeight; + while (heightWalk > height) { + int heightSkip = GetSkipHeight(heightWalk); + int heightSkipPrev = GetSkipHeight(heightWalk - 1); + if (heightSkip == height || + (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && + heightSkipPrev >= height))) { + // Only follow pskip if pprev->pskip isn't better than pskip->pprev. + pindexWalk = pindexWalk->pskip; + heightWalk = heightSkip; + } else { + pindexWalk = pindexWalk->pprev; + heightWalk--; + } + } + return pindexWalk; +} + +const CBlockIndex* CBlockIndex::GetAncestor(int height) const +{ + return const_cast(this)->GetAncestor(height); +} + +void CBlockIndex::BuildSkip() +{ + if (pprev) + pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); +} + void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd) { AssertLockHeld(cs_main); @@ -2858,6 +2913,8 @@ bool static LoadBlockIndexDB() setBlockIndexValid.insert(pindex); if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork)) pindexBestInvalid = pindex; + if (pindex->pprev) + pindex->BuildSkip(); } // Load block file info diff --git a/src/main.h b/src/main.h index 9487078b74..1af86b065f 100644 --- a/src/main.h +++ b/src/main.h @@ -677,6 +677,9 @@ public: // pointer to the index of the predecessor of this block CBlockIndex* pprev; + // pointer to the index of some further predecessor of this block + CBlockIndex* pskip; + // height of the entry in the chain. The genesis block has height 0 int nHeight; @@ -716,6 +719,7 @@ public: { phashBlock = NULL; pprev = NULL; + pskip = NULL; nHeight = 0; nFile = 0; nDataPos = 0; @@ -737,6 +741,7 @@ public: { phashBlock = NULL; pprev = NULL; + pskip = NULL; nHeight = 0; nFile = 0; nDataPos = 0; @@ -869,10 +874,15 @@ public: } return false; } + + // Build the skiplist pointer for this entry. + void BuildSkip(); + + // Efficiently find an ancestor of this block. + CBlockIndex* GetAncestor(int height); + const CBlockIndex* GetAncestor(int height) const; }; - - /** Used to marshal pointers into hashes for db storage. */ class CDiskBlockIndex : public CBlockIndex { From 236982c2b6de619f0744c9c17ea7208b64a4afb3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 29 Jun 2014 15:26:58 +0200 Subject: [PATCH 276/336] Add skiplist unit tests --- src/Makefile.test.include | 1 + src/test/skiplist_tests.cpp | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/test/skiplist_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 4dab1773f4..8685452c7b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -47,6 +47,7 @@ BITCOIN_TESTS =\ test/script_tests.cpp \ test/serialize_tests.cpp \ test/sigopcount_tests.cpp \ + test/skiplist_tests.cpp \ test/test_bitcoin.cpp \ test/transaction_tests.cpp \ test/uint256_tests.cpp \ diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp new file mode 100644 index 0000000000..ea301685c9 --- /dev/null +++ b/src/test/skiplist_tests.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2014 The Bitcoin Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include "main.h" +#include "util.h" + + +#define SKIPLIST_LENGTH 300000 + +BOOST_AUTO_TEST_SUITE(skiplist_tests) + +BOOST_AUTO_TEST_CASE(skiplist_test) +{ + std::vector vIndex(SKIPLIST_LENGTH); + + for (int i=0; i 0) { + BOOST_CHECK(vIndex[i].pskip == &vIndex[vIndex[i].pskip->nHeight]); + BOOST_CHECK(vIndex[i].pskip->nHeight < i); + } else { + BOOST_CHECK(vIndex[i].pskip == NULL); + } + } + + for (int i=0; i < 1000; i++) { + int from = insecure_rand() % (SKIPLIST_LENGTH - 1); + int to = insecure_rand() % (from + 1); + + BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]); + BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]); + BOOST_CHECK(vIndex[from].GetAncestor(0) == &vIndex[0]); + } +} + +BOOST_AUTO_TEST_SUITE_END() + From 77888d68d5b78d442a18073c663478bae35da246 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 30 Jun 2014 15:43:01 +0200 Subject: [PATCH 277/336] Fix the build for Qt5 Merging #3883 broke the Qt5 build, define the color in the standard way. --- src/qt/guiconstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 44e361e1e5..696761e234 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -24,7 +24,7 @@ static const int STATUSBAR_ICONSIZE = 16; /* Transaction list -- bare address (without label) */ #define COLOR_BAREADDRESS QColor(140, 140, 140) /* Transaction list -- has conflicting transactions */ -#define COLOR_HASCONFLICTING Qt::white; +#define COLOR_HASCONFLICTING QColor(255, 255, 255) /* Transaction list -- has conflicting transactions - background */ #define COLOR_HASCONFLICTING_BG QColor(192, 0, 0) From 3faf1f8294065eaabe2d6d24f2fe04ee4dfd6ae2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 30 Jun 2014 16:37:59 +0200 Subject: [PATCH 278/336] test: Fix warning about integer signedness in P2SH tests --- src/test/script_P2SH_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 6ae2b9cf64..a1dc17ba36 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) // vout[4] is max sigops: CScript fifteenSigops; fifteenSigops << OP_1; - for (int i = 0; i < MAX_P2SH_SIGOPS; i++) + for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++) fifteenSigops << key[i%3].GetPubKey(); fifteenSigops << OP_15 << OP_CHECKMULTISIG; keystore.AddCScript(fifteenSigops); From 9a6497ed0798055d2117547e82a1569a4017d2f2 Mon Sep 17 00:00:00 2001 From: Trevin Hofmann Date: Tue, 1 Jul 2014 00:05:24 -0500 Subject: [PATCH 279/336] http to https, 2013 to 2014 --- COPYING | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/COPYING b/COPYING index c410baa6a0..6219bd75a6 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2009-2013 Bitcoin Developers +Copyright (c) 2009-2014 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 diff --git a/README.md b/README.md index 102aa56201..7c2fe12f3a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Bitcoin Core integration/staging tree ===================================== -http://www.bitcoin.org +https://www.bitcoin.org Copyright (c) 2009-2014 Bitcoin Core Developers @@ -15,7 +15,7 @@ out collectively by the network. Bitcoin Core is the name of open source software which enables the use of this currency. For more information, as well as an immediately useable, binary version of -the Bitcoin Core software, see http://www.bitcoin.org/en/download. +the Bitcoin Core software, see https://www.bitcoin.org/en/download. License ------- From 8d9cc7d743583f6cb72d224af458fa5f470b00e8 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 27 Jun 2014 14:51:46 +0200 Subject: [PATCH 280/336] fix copyright string in two of our *.rc files - also make comment about rc-files in clientversion.h generic Merges #4429. --- src/bitcoin-cli-res.rc | 1 - src/bitcoind-res.rc | 1 - src/clientversion.h | 5 ++++- src/qt/res/bitcoin-qt-res.rc | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc index a4a0c47ea5..b1aa1b0e16 100644 --- a/src/bitcoin-cli-res.rc +++ b/src/bitcoin-cli-res.rc @@ -5,7 +5,6 @@ #define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR -#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc index dc5c56b797..2e6d754495 100644 --- a/src/bitcoind-res.rc +++ b/src/bitcoind-res.rc @@ -5,7 +5,6 @@ #define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR -#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core developers" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION diff --git a/src/clientversion.h b/src/clientversion.h index a30bbff06b..6c718a9f79 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,7 +8,7 @@ // client versioning and copyright year // -// These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it +// These need to be macros, as version.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 99 @@ -28,4 +28,7 @@ #define STRINGIZE(X) DO_STRINGIZE(X) #define DO_STRINGIZE(X) #X +// Copyright string used in Windows .rc files +#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin Core Developers" + #endif // CLIENTVERSION_H diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc index ee23ae9b78..809235be5f 100644 --- a/src/qt/res/bitcoin-qt-res.rc +++ b/src/qt/res/bitcoin-qt-res.rc @@ -8,7 +8,6 @@ IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR -#define COPYRIGHT_STR "2009-" STRINGIZE(COPYRIGHT_YEAR) " The Bitcoin developers" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION From dd638dd712861a2fc419fe9b2b064ae303b074e6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 25 Jun 2014 13:45:29 +0200 Subject: [PATCH 281/336] typedef std::map to CCoinsMap This makes it possible to switch to a more efficient map type without changing all occurences manually. Merges half of #4413. --- src/coins.cpp | 16 ++++++++-------- src/coins.h | 11 ++++++----- src/txdb.cpp | 4 ++-- src/txdb.h | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 86b2a6ef17..13a4ea95cd 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -55,7 +55,7 @@ bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return fal bool CCoinsView::HaveCoins(const uint256 &txid) { return false; } uint256 CCoinsView::GetBestBlock() { return uint256(0); } bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; } -bool CCoinsView::BatchWrite(const std::map &mapCoins, const uint256 &hashBlock) { return false; } +bool CCoinsView::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; } bool CCoinsView::GetStats(CCoinsStats &stats) { return false; } @@ -66,7 +66,7 @@ bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(t uint256 CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); } bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); } void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } -bool CCoinsViewBacked::BatchWrite(const std::map &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } +bool CCoinsViewBacked::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); } CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { } @@ -83,20 +83,20 @@ bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) { return false; } -std::map::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) { - std::map::iterator it = cacheCoins.lower_bound(txid); +CCoinsMap::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) { + CCoinsMap::iterator it = cacheCoins.lower_bound(txid); if (it != cacheCoins.end() && it->first == txid) return it; CCoins tmp; if (!base->GetCoins(txid,tmp)) return cacheCoins.end(); - std::map::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins())); + CCoinsMap::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins())); tmp.swap(ret->second); return ret; } CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) { - std::map::iterator it = FetchCoins(txid); + CCoinsMap::iterator it = FetchCoins(txid); assert(it != cacheCoins.end()); return it->second; } @@ -121,8 +121,8 @@ bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { return true; } -bool CCoinsViewCache::BatchWrite(const std::map &mapCoins, const uint256 &hashBlockIn) { - for (std::map::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) +bool CCoinsViewCache::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlockIn) { + for (CCoinsMap::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) cacheCoins[it->first] = it->second; hashBlock = hashBlockIn; return true; diff --git a/src/coins.h b/src/coins.h index 0ad28524a1..c57a5ec722 100644 --- a/src/coins.h +++ b/src/coins.h @@ -239,6 +239,7 @@ public: } }; +typedef std::map CCoinsMap; struct CCoinsStats { @@ -275,7 +276,7 @@ public: virtual bool SetBestBlock(const uint256 &hashBlock); // Do a bulk modification (multiple SetCoins + one SetBestBlock) - virtual bool BatchWrite(const std::map &mapCoins, const uint256 &hashBlock); + virtual bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock); // Calculate statistics about the unspent transaction output set virtual bool GetStats(CCoinsStats &stats); @@ -299,7 +300,7 @@ public: uint256 GetBestBlock(); bool SetBestBlock(const uint256 &hashBlock); void SetBackend(CCoinsView &viewIn); - bool BatchWrite(const std::map &mapCoins, const uint256 &hashBlock); + bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock); bool GetStats(CCoinsStats &stats); }; @@ -309,7 +310,7 @@ class CCoinsViewCache : public CCoinsViewBacked { protected: uint256 hashBlock; - std::map cacheCoins; + CCoinsMap cacheCoins; public: CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false); @@ -320,7 +321,7 @@ public: bool HaveCoins(const uint256 &txid); uint256 GetBestBlock(); bool SetBestBlock(const uint256 &hashBlock); - bool BatchWrite(const std::map &mapCoins, const uint256 &hashBlock); + bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock); // Return a modifiable reference to a CCoins. Check HaveCoins first. // Many methods explicitly require a CCoinsViewCache because of this method, to reduce @@ -352,7 +353,7 @@ public: const CTxOut &GetOutputFor(const CTxIn& input); private: - std::map::iterator FetchCoins(const uint256 &txid); + CCoinsMap::iterator FetchCoins(const uint256 &txid); }; #endif diff --git a/src/txdb.cpp b/src/txdb.cpp index 92137f71ff..52cd96283e 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -54,11 +54,11 @@ bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) { return db.WriteBatch(batch); } -bool CCoinsViewDB::BatchWrite(const std::map &mapCoins, const uint256 &hashBlock) { +bool CCoinsViewDB::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) { LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size()); CLevelDBBatch batch; - for (std::map::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) + for (CCoinsMap::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) BatchWriteCoins(batch, it->first, it->second); if (hashBlock != uint256(0)) BatchWriteHashBestChain(batch, hashBlock); diff --git a/src/txdb.h b/src/txdb.h index 7257b0dd21..7d670c2542 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -37,7 +37,7 @@ public: bool HaveCoins(const uint256 &txid); uint256 GetBestBlock(); bool SetBestBlock(const uint256 &hashBlock); - bool BatchWrite(const std::map &mapCoins, const uint256 &hashBlock); + bool BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock); bool GetStats(CCoinsStats &stats); }; From d95ba75825d3b417d03cd2cce6bb944d5a679040 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 1 Jul 2014 14:57:45 +0200 Subject: [PATCH 282/336] qt: Log messages with type>QtDebugMsg as non-debug More important messages should end up in the log no matter if -debug=qt is set. --- src/qt/bitcoin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 89305e9f35..569facb499 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -126,15 +126,15 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans #if QT_VERSION < 0x050000 void DebugMessageHandler(QtMsgType type, const char *msg) { - Q_UNUSED(type); - LogPrint("qt", "GUI: %s\n", msg); + const char *category = (type == QtDebugMsg) ? "qt" : NULL; + LogPrint(category, "GUI: %s\n", msg); } #else void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg) { - Q_UNUSED(type); Q_UNUSED(context); - LogPrint("qt", "GUI: %s\n", qPrintable(msg)); + const char *category = (type == QtDebugMsg) ? "qt" : NULL; + LogPrint(category, "GUI: %s\n", QString::toStdString(msg)); } #endif From 33fdd99288fd257d6b5a3797a0a68aff649a3a71 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 1 Jul 2014 15:21:17 +0200 Subject: [PATCH 283/336] qt: Change serious messages from qDebug to qWarning By changing the logging stream for warnings from qDebug to qWarning, these will always be logged to debug.log. --- src/qt/addresstablemodel.cpp | 6 +++--- src/qt/paymentrequestplus.cpp | 22 +++++++++++----------- src/qt/paymentserver.cpp | 24 ++++++++++++------------ src/qt/transactiontablemodel.cpp | 6 +++--- src/qt/winshutdownmonitor.cpp | 6 +++--- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index dfbd445ce3..8d5284d5e9 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -114,7 +114,7 @@ public: case CT_NEW: if(inModel) { - qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model"; + qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_NEW, but entry is already in model"; break; } parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex); @@ -124,7 +124,7 @@ public: case CT_UPDATED: if(!inModel) { - qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model"; + qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_UPDATED, but entry is not in model"; break; } lower->type = newEntryType; @@ -134,7 +134,7 @@ public: case CT_DELETED: if(!inModel) { - qDebug() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model"; + qWarning() << "AddressTablePriv::updateEntry : Warning: Got CT_DELETED, but entry is not in model"; break; } parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1); diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 464f995eb6..acce42e203 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -29,18 +29,18 @@ bool PaymentRequestPlus::parse(const QByteArray& data) { bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size()); if (!parseOK) { - qDebug() << "PaymentRequestPlus::parse : Error parsing payment request"; + qWarning() << "PaymentRequestPlus::parse : Error parsing payment request"; return false; } if (paymentRequest.payment_details_version() > 1) { - qDebug() << "PaymentRequestPlus::parse : Received up-version payment details, version=" << paymentRequest.payment_details_version(); + qWarning() << "PaymentRequestPlus::parse : Received up-version payment details, version=" << paymentRequest.payment_details_version(); return false; } parseOK = details.ParseFromString(paymentRequest.serialized_payment_details()); if (!parseOK) { - qDebug() << "PaymentRequestPlus::parse : Error parsing payment details"; + qWarning() << "PaymentRequestPlus::parse : Error parsing payment details"; paymentRequest.Clear(); return false; } @@ -80,17 +80,17 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c digestAlgorithm = EVP_sha1(); } else if (paymentRequest.pki_type() == "none") { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; return false; } else { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type()); + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type()); return false; } payments::X509Certificates certChain; if (!certChain.ParseFromString(paymentRequest.pki_data())) { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data"; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data"; return false; } @@ -100,12 +100,12 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size()); QSslCertificate qCert(certData, QSsl::Der); if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert; return false; } #if QT_VERSION >= 0x050000 if (qCert.isBlacklisted()) { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert; return false; } #endif @@ -115,7 +115,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c certs.push_back(cert); } if (certs.empty()) { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain"; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain"; return false; } @@ -131,7 +131,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c // load the signing cert into it and verify. X509_STORE_CTX *store_ctx = X509_STORE_CTX_new(); if (!store_ctx) { - qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX"; + qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX"; return false; } @@ -183,7 +183,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c catch (SSLVerifyError& err) { fResult = false; - qDebug() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what(); + qWarning() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what(); } if (website) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index fbb11617fe..2049d65073 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -90,7 +90,7 @@ static QList savedPaymentRequests; static void ReportInvalidCertificate(const QSslCertificate& cert) { - qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName); + qWarning() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName); } // @@ -161,7 +161,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) continue; } } - qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates"; + qWarning() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates"; // Project for another day: // Fetch certificate revocation lists, and add them to certStore. @@ -223,7 +223,7 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { // Printing to debug.log is about the best we can do here, the // GUI hasn't started yet so we can't pop up a message box. - qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; + qWarning() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; } } return true; @@ -403,7 +403,7 @@ void PaymentServer::handleURIOrFile(const QString& s) } else { - qDebug() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl; + qWarning() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl; emit message(tr("URI handling"), tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()), CClientUIInterface::ICON_WARNING); @@ -476,13 +476,13 @@ bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPl QFile f(filename); if (!f.open(QIODevice::ReadOnly)) { - qDebug() << "PaymentServer::readPaymentRequest : Failed to open " << filename; + qWarning() << "PaymentServer::readPaymentRequest : Failed to open " << filename; return false; } if (f.size() > MAX_PAYMENT_REQUEST_SIZE) { - qDebug() << "PaymentServer::readPaymentRequest : " << filename << " too large"; + qWarning() << "PaymentServer::readPaymentRequest : " << filename << " too large"; return false; } @@ -624,7 +624,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien else { // This should never happen, because sending coins should have // just unlocked the wallet and refilled the keypool. - qDebug() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set"; + qWarning() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set"; } } @@ -636,7 +636,7 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipien } else { // This should never happen, either. - qDebug() << "PaymentServer::fetchPaymentACK : Error serializing payment message"; + qWarning() << "PaymentServer::fetchPaymentACK : Error serializing payment message"; } } @@ -649,7 +649,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) .arg(reply->request().url().toString()) .arg(reply->errorString()); - qDebug() << "PaymentServer::netRequestFinished : " << msg; + qWarning() << "PaymentServer::netRequestFinished : " << msg; emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); return; } @@ -663,7 +663,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) SendCoinsRecipient recipient; if (!request.parse(data)) { - qDebug() << "PaymentServer::netRequestFinished : Error parsing payment request"; + qWarning() << "PaymentServer::netRequestFinished : Error parsing payment request"; emit message(tr("Payment request error"), tr("Payment request can not be parsed!"), CClientUIInterface::MSG_ERROR); @@ -681,7 +681,7 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply) QString msg = tr("Bad response from server %1") .arg(reply->request().url().toString()); - qDebug() << "PaymentServer::netRequestFinished : " << msg; + qWarning() << "PaymentServer::netRequestFinished : " << msg; emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); } else @@ -697,7 +697,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList QString errString; foreach (const QSslError& err, errs) { - qDebug() << "PaymentServer::reportSslErrors : " << err; + qWarning() << "PaymentServer::reportSslErrors : " << err; errString += err.errorString() + "\n"; } emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d7f4c043cf..a935752246 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -130,12 +130,12 @@ public: case CT_NEW: if(inModel) { - qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is already in model"; + qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is already in model"; break; } if(!inWallet) { - qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet"; + qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet"; break; } if(showTransaction) @@ -159,7 +159,7 @@ public: case CT_DELETED: if(!inModel) { - qDebug() << "TransactionTablePriv::updateWallet : Warning: Got CT_DELETED, but transaction is not in model"; + qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_DELETED, but transaction is not in model"; break; } // Removed -- remove entire transaction from table diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index b7526f0ae4..f8f9bf45b3 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -45,13 +45,13 @@ void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, c typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate"); if (shutdownBRCreate == NULL) { - qDebug() << "registerShutdownBlockReason : GetProcAddress for ShutdownBlockReasonCreate failed"; + qWarning() << "registerShutdownBlockReason : GetProcAddress for ShutdownBlockReasonCreate failed"; return; } if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str())) - qDebug() << "registerShutdownBlockReason : Successfully registered: " + strReason; + qWarning() << "registerShutdownBlockReason : Successfully registered: " + strReason; else - qDebug() << "registerShutdownBlockReason : Failed to register: " + strReason; + qWarning() << "registerShutdownBlockReason : Failed to register: " + strReason; } #endif From b150b09edcd3b6b7ca5f26ca6ebee92bbad97089 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 6 Jun 2014 10:23:34 -0400 Subject: [PATCH 284/336] secp256k1: add libtool as a dependency --- autogen.sh | 3 +++ configure.ac | 1 + contrib/debian/control | 1 + contrib/gitian-descriptors/gitian-osx-bitcoin.yml | 1 + doc/build-osx.md | 4 ++-- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/autogen.sh b/autogen.sh index 5b883a6a4c..50b85bcba0 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,4 +2,7 @@ set -e srcdir="$(dirname $0)" cd "$srcdir" +if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then + export LIBTOOLIZE="${GLIBTOOLIZE}" +fi autoreconf --install --force diff --git a/configure.ac b/configure.ac index 811ef1dd80..925ac41ad4 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,7 @@ define(_COPYRIGHT_YEAR, 2014) AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@bitcoin.org],[bitcoin]) AC_CONFIG_AUX_DIR([src/build-aux]) AC_CONFIG_MACRO_DIR([src/m4]) +LT_INIT([disable-shared]) AC_CANONICAL_HOST AH_TOP([#ifndef BITCOIN_CONFIG_H]) AH_TOP([#define BITCOIN_CONFIG_H]) diff --git a/contrib/debian/control b/contrib/debian/control index 9e006a7070..a04e88d4e1 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -6,6 +6,7 @@ Uploaders: Micah Anderson Build-Depends: debhelper, devscripts, automake, + libtool, bash-completion, libboost-system-dev (>> 1.35) | libboost-system1.35-dev, libdb4.8++-dev, diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml index 44b5de9be3..bc3d561c35 100644 --- a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml +++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml @@ -11,6 +11,7 @@ packages: - "bsdmainutils" - "pkg-config" - "p7zip-full" +- "libtool" reference_datetime: "2013-06-01 00:00:00" remotes: diff --git a/doc/build-osx.md b/doc/build-osx.md index 1e38326d86..bc42723b12 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -41,7 +41,7 @@ Instructions: MacPorts ### Install dependencies - sudo port install boost db48@+no_java openssl miniupnpc autoconf pkgconfig automake + sudo port install boost db48@+no_java openssl miniupnpc autoconf pkgconfig automake libtool Optional: install Qt4 @@ -69,7 +69,7 @@ Instructions: Homebrew #### Install dependencies using Homebrew - brew install autoconf automake berkeley-db4 boost miniupnpc openssl pkg-config protobuf qt + brew install autoconf automake libtool berkeley-db4 boost miniupnpc openssl pkg-config protobuf qt Note: After you have installed the dependencies, you should check that the Homebrew installed version of OpenSSL is the one available for compilation. You can check this by typing From 556682663547f9a9ede69fc4f924b50c531d92b3 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 6 Jun 2014 10:57:28 -0400 Subject: [PATCH 285/336] secp256k1: Add build-side changes for libsecp256k1 Note: This is added to our existing automake targets rather than as a libtool-style lib. The switch to libtool-style targets can come later if it proves to not add any complications. --- Makefile.am | 1 + configure.ac | 1 + src/Makefile.am | 20 +++++++++++++++++++- src/Makefile.qt.include | 3 +++ src/Makefile.qttest.include | 3 +++ src/Makefile.test.include | 5 +++++ src/secp256k1/.empty | 0 7 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/secp256k1/.empty diff --git a/Makefile.am b/Makefile.am index 719af42ac7..3a6a6b6d88 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,6 +35,7 @@ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ dist-hook: -$(MAKE) -C $(top_distdir)/src/leveldb clean + -$(MAKE) -C $(top_distdir)/src/secp256k1 distclean -$(GIT) archive --format=tar HEAD -- src/version.cpp | $(AMTAR) -C $(top_distdir) -xf - distcheck-hook: diff --git a/configure.ac b/configure.ac index 925ac41ad4..2a4636e360 100644 --- a/configure.ac +++ b/configure.ac @@ -680,6 +680,7 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes]) AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) +AM_CONDITIONAL([USE_LIBSECP256K1],[test x$use_libsecp256k1 = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) diff --git a/src/Makefile.am b/src/Makefile.am index 9c7b294d35..e2a62c9699 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,10 @@ AM_CPPFLAGS = $(INCLUDES) AM_LDFLAGS = $(PTHREAD_CFLAGS) +if USE_LIBSECP256K1 +secp256k1/libsecp256k1.la: $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) + @$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) +endif if EMBEDDED_LEVELDB LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include @@ -20,6 +24,10 @@ endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +if USE_LIBSECP256K1 +BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include +endif + LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a @@ -220,6 +228,11 @@ bitcoind_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBMEMENV) + +if USE_LIBSECP256K1 + bitcoind_LDADD += secp256k1/libsecp256k1.la +endif + if ENABLE_WALLET bitcoind_LDADD += libbitcoin_wallet.a endif @@ -242,6 +255,10 @@ bitcoin_cli_LDADD = \ $(BOOST_LIBS) bitcoin_cli_SOURCES = \ bitcoin-cli.cpp + +if USE_LIBSECP256K1 + bitcoin_cli_LDADD += secp256k1/libsecp256k1.la +endif bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # @@ -253,10 +270,11 @@ CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb +EXTRA_DIST = leveldb secp256k1 clean-local: -$(MAKE) -C leveldb clean + -$(MAKE) -C secp256k1 clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 9df0779ba3..4563bb3565 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -357,6 +357,9 @@ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +if USE_LIBSECP256K1 + qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la +endif qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) #locale/foo.ts -> locale/foo.qm diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index a509f23755..7e10ce5a96 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -33,6 +33,9 @@ endif qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +if USE_LIBSECP256K1 + qt_test_test_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la +endif qt_test_test_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 8685452c7b..12b90adca3 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -69,6 +69,11 @@ test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_CO if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif + +if USE_LIBSECP256K1 + test_test_bitcoin_LDADD += secp256k1/libsecp256k1.la +endif + test_test_bitcoin_LDADD += $(BDB_LIBS) nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/secp256k1/.empty b/src/secp256k1/.empty new file mode 100644 index 0000000000..e69de29bb2 From fda3fed18aedc4bfc8ccffe89d8d2cabb12677ab Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 Jun 2014 01:26:27 +0200 Subject: [PATCH 286/336] libsecp256k1 integration --- src/key.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 12 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 784085da34..3c4fa77e72 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -5,15 +5,34 @@ #include "key.h" #include "crypto/sha2.h" +#include +#ifdef USE_SECP256K1 +#include +#else #include #include #include -#include +#endif // anonymous namespace with local implementation code (OpenSSL interaction) namespace { +#ifdef USE_SECP256K1 +#include +class CSecp256k1Init { +public: + CSecp256k1Init() { + secp256k1_start(); + } + ~CSecp256k1Init() { + secp256k1_stop(); + } +}; +static CSecp256k1Init instance_of_csecp256k1; + +#else + // Generate a private key from just the secret parameter int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) { @@ -334,6 +353,8 @@ public: } }; +#endif + int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { while (c1len > c2len) { if (*c1) @@ -398,10 +419,15 @@ void CKey::MakeNewKey(bool fCompressedIn) { } bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { +#ifdef USE_SECP256K1 + if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) + return false; +#else CECKey key; if (!key.SetPrivKey(privkey)) return false; key.GetSecretBytes(vch); +#endif fCompressed = fCompressedIn; fValid = true; return true; @@ -409,99 +435,167 @@ bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { CPrivKey CKey::GetPrivKey() const { assert(fValid); + CPrivKey privkey; +#ifdef USE_SECP256K1 + privkey.resize(279); + int privkeylen = 279; + int ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); + assert(ret); + privkey.resize(privkeylen); +#else CECKey key; key.SetSecretBytes(vch); - CPrivKey privkey; key.GetPrivKey(privkey, fCompressed); +#endif return privkey; } CPubKey CKey::GetPubKey() const { assert(fValid); + CPubKey pubkey; +#ifdef USE_SECP256K1 + int clen = 65; + int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)pubkey.begin(), &clen, begin(), fCompressed); + assert(ret); + assert(pubkey.IsValid()); + assert((int)pubkey.size() == clen); +#else CECKey key; key.SetSecretBytes(vch); - CPubKey pubkey; key.GetPubKey(pubkey, fCompressed); +#endif return pubkey; } bool CKey::Sign(const uint256 &hash, std::vector& vchSig) const { if (!fValid) return false; +#ifdef USE_SECP256K1 + vchSig.resize(72); + int nSigLen = 72; + CKey nonce; + do { + nonce.MakeNewKey(true); + if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin())) + break; + } while(true); + vchSig.resize(nSigLen); + return true; +#else CECKey key; key.SetSecretBytes(vch); return key.Sign(hash, vchSig); +#endif } bool CKey::SignCompact(const uint256 &hash, std::vector& vchSig) const { if (!fValid) return false; - CECKey key; - key.SetSecretBytes(vch); vchSig.resize(65); int rec = -1; +#ifdef USE_SECP256K1 + CKey nonce; + do { + nonce.MakeNewKey(true); + if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec)) + break; + } while(true); +#else + CECKey key; + key.SetSecretBytes(vch); if (!key.SignCompact(hash, &vchSig[1], rec)) return false; +#endif assert(rec != -1); vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); return true; } bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { +#ifdef USE_SECP256K1 + if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) + return false; +#else CECKey key; if (!key.SetPrivKey(privkey, fSkipCheck)) return false; - key.GetSecretBytes(vch); +#endif fCompressed = vchPubKey.IsCompressed(); fValid = true; - + if (fSkipCheck) return true; - + if (GetPubKey() != vchPubKey) return false; - + return true; } bool CPubKey::Verify(const uint256 &hash, const std::vector& vchSig) const { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1) + return false; +#else CECKey key; if (!key.SetPubKey(*this)) return false; if (!key.Verify(hash, vchSig)) return false; +#endif return true; } bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector& vchSig) { if (vchSig.size() != 65) return false; - CECKey key; - if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4)) + int recid = (vchSig[0] - 27) & 3; + bool fComp = (vchSig[0] - 27) & 4; +#ifdef USE_SECP256K1 + int pubkeylen = 65; + if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid)) return false; - key.GetPubKey(*this, (vchSig[0] - 27) & 4); + assert((int)size() == pubkeylen); +#else + CECKey key; + if (!key.Recover(hash, &vchSig[1], recid)) + return false; + key.GetPubKey(*this, fComp); +#endif return true; } bool CPubKey::IsFullyValid() const { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + if (!secp256k1_ecdsa_pubkey_verify(begin(), size())) + return false; +#else CECKey key; if (!key.SetPubKey(*this)) return false; +#endif return true; } bool CPubKey::Decompress() { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + int clen = size(); + int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen); + assert(ret); + assert(clen == (int)size()); +#else CECKey key; if (!key.SetPubKey(*this)) return false; key.GetPubKey(*this, false); +#endif return true; } @@ -531,7 +625,12 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild BIP32Hash(cc, nChild, 0, begin(), out); } memcpy(ccChild, out+32, 32); +#ifdef USE_SECP256K1 + memcpy((unsigned char*)keyChild.begin(), begin(), 32); + bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out); +#else bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out); +#endif UnlockObject(out); keyChild.fCompressed = true; keyChild.fValid = ret; @@ -545,10 +644,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild, out+32, 32); +#ifdef USE_SECP256K1 + pubkeyChild = *this; + bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out); +#else CECKey key; bool ret = key.SetPubKey(*this); ret &= key.TweakPublic(out); key.GetPubKey(pubkeyChild, true); +#endif return ret; } @@ -629,6 +733,9 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { } bool ECC_InitSanityCheck() { +#ifdef USE_SECP256K1 + return true; +#else EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if(pkey == NULL) return false; @@ -636,6 +743,7 @@ bool ECC_InitSanityCheck() { // TODO Is there more EC functionality that could be missing? return true; +#endif } From 462ad223d65bf9a37b4617c4c318279f257258d9 Mon Sep 17 00:00:00 2001 From: Micha Date: Tue, 1 Jul 2014 19:29:44 +0300 Subject: [PATCH 287/336] Clean up release-process.md after OS X gitian changes This is PR #4271, but with the changes to the descriptors, both the names of the files and the names of the intermediate build artifact archives, removed. This also closes #3775 if it goes in, because it covers the changes in that PR. --- doc/release-process.md | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index d12b41772e..324b8c43ab 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -33,16 +33,21 @@ Release Process git checkout v${VERSION} popd pushd ./gitian-builder - mkdir -p inputs; cd inputs/ - Register and download the Apple SDK (see OSX Readme for details) - visit https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg + ###Fetch and build inputs: (first time, or when dependency versions change) + + mkdir -p inputs; cd inputs/ + + Register and download the Apple SDK: (see OSX Readme for details) + + https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_4.6.3/xcode4630916281a.dmg + + Using a Mac, create a tarball for the 10.7 SDK and copy it to the inputs directory: - Using a Mac, create a tarball for the 10.7 SDK tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.7.sdk.tar.gz MacOSX10.7.sdk - Fetch and build inputs: (first time, or when dependency versions change) - + Download remaining inputs, and build everything: + wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.9.tar.gz' -O miniupnpc-1.9.tar.gz wget 'https://www.openssl.org/source/openssl-1.0.1h.tar.gz' wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' @@ -87,10 +92,10 @@ Release Process The expected SHA256 hashes of the intermediate inputs are: - 46710f673467e367738d8806e45b4cb5931aaeea61f4b6b55a68eea56d5006c5 bitcoin-deps-linux32-gitian-r6.zip - f03be39fb26670243d3a659e64d18e19d03dec5c11e9912011107768390b5268 bitcoin-deps-linux64-gitian-r6.zip f29b7d9577417333fb56e023c2977f5726a7c297f320b175a4108cf7cd4c2d29 boost-linux32-1.55.0-gitian-r1.zip 88232451c4104f7eb16e469ac6474fd1231bd485687253f7b2bdf46c0781d535 boost-linux64-1.55.0-gitian-r1.zip + 46710f673467e367738d8806e45b4cb5931aaeea61f4b6b55a68eea56d5006c5 bitcoin-deps-linux32-gitian-r6.zip + f03be39fb26670243d3a659e64d18e19d03dec5c11e9912011107768390b5268 bitcoin-deps-linux64-gitian-r6.zip 57e57dbdadc818cd270e7e00500a5e1085b3bcbdef69a885f0fb7573a8d987e1 qt-linux32-4.6.4-gitian-r1.tar.gz 60eb4b9c5779580b7d66529efa5b2836ba1a70edde2a0f3f696d647906a826be qt-linux64-4.6.4-gitian-r1.tar.gz 60dc2d3b61e9c7d5dbe2f90d5955772ad748a47918ff2d8b74e8db9b1b91c909 boost-win32-1.55.0-gitian-r6.zip @@ -106,10 +111,10 @@ Release Process ec95abef1df2b096a970359787c01d8c45e2a4475b7ae34e12c022634fbdba8a osx-depends-qt-5.2.1-r4.tar.gz - Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32: + Build Bitcoin Core for Linux, Windows, and OS X: ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml - ./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml + ./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml pushd build/out zip -r bitcoin-${VERSION}-linux-gitian.zip * mv bitcoin-${VERSION}-linux-gitian.zip ../../../ @@ -132,7 +137,7 @@ Release Process 1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip) 2. windows 32-bit and 64-bit binaries + installer + source (bitcoin-${VERSION}-win-gitian.zip) 3. OSX installer (Bitcoin-Qt.dmg) - 4. Gitian signatures (in gitian.sigs/${VERSION}[-win|-osx]/(your gitian key)/ + 4. Gitian signatures (in gitian.sigs/${VERSION}-/(your gitian key)/ repackage gitian builds for release as stand-alone zip/tar/installer exe @@ -172,8 +177,9 @@ repackage gitian builds for release as stand-alone zip/tar/installer exe Commit your signature to gitian.sigs: pushd gitian.sigs - git add ${VERSION}/${SIGNER} + git add ${VERSION}-linux/${SIGNER} git add ${VERSION}-win/${SIGNER} + git add ${VERSION}-osx/${SIGNER} git commit -a git push # Assuming you can push to the gitian.sigs tree popd From 88dd3598d22197a22565e524cecdc08107cf76ac Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Tue, 1 Jul 2014 14:26:57 -0700 Subject: [PATCH 288/336] Check signatures before respend relay Check that all inputs are completely valid before actually relaying a double-spend. --- src/main.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 04d9523e26..1294e5b2ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -127,7 +127,7 @@ namespace { // Forward reference functions defined here: static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000; -static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter); +static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter); ////////////////////////////////////////////////////////////////////////////// // @@ -156,7 +156,7 @@ struct CMainSignals { // transaction was first seen in a block. // Note: only notifies if the previous transaction is in the memory pool; if previous transction was in a block, // then the double-spend simply fails when we try to lookup the inputs in the current UTXO set. - boost::signals2::signal DetectedDoubleSpend; + boost::signals2::signal DetectedDoubleSpend; } g_signals; } // anon namespace @@ -166,7 +166,7 @@ void RegisterInternalSignals() { seed_insecure_rand(); doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE); - g_signals.DetectedDoubleSpend.connect(boost::bind(RelayDoubleSpend, _1, _2, _3, doubleSpendFilter)); + g_signals.DetectedDoubleSpend.connect(boost::bind(RelayableRespend, _1, _2, _3, doubleSpendFilter)); } @@ -936,6 +936,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; // Check for conflicts with in-memory transactions + bool relayableRespend = false; { LOCK(pool.cs); // protect pool.mapNextTx for (unsigned int i = 0; i < tx.vin.size(); i++) @@ -944,8 +945,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Does tx conflict with a member of the pool, and is it not equivalent to that member? if (pool.mapNextTx.count(outpoint) && !tx.IsEquivalentTo(*pool.mapNextTx[outpoint].ptx)) { - g_signals.DetectedDoubleSpend(outpoint, tx, false); - return false; + relayableRespend = g_signals.DetectedDoubleSpend(outpoint, tx, false); + if (!relayableRespend) + return false; } } } @@ -1038,16 +1040,24 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString()); } - // Store transaction in memory - pool.addUnchecked(hash, entry); + + if (relayableRespend) + { + RelayTransaction(tx); + } + else + { + // Store transaction in memory + pool.addUnchecked(hash, entry); + } } g_signals.SyncTransaction(tx, NULL); - return true; + return !relayableRespend; } -static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) +static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) { // Relaying double-spend attempts to our peers lets them detect when // somebody might be trying to cheat them. However, blindly relaying @@ -1060,7 +1070,7 @@ static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doub // from us they are very likely to hear about it from another peer, since // each peer uses a different, randomized bloom filter. - if (fInBlock || filter.contains(outPoint)) return; + if (fInBlock || filter.contains(outPoint)) return false; // Apply an independent rate limit to double-spend relays static double dRespendCount; @@ -1071,7 +1081,7 @@ static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doub if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize)) { LogPrint("mempool", "Double-spend relay rejected by rate limiter\n"); - return; + return false; } LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize); @@ -1083,10 +1093,7 @@ static void RelayDoubleSpend(const COutPoint& outPoint, const CTransaction& doub filter.insert(outPoint); - RelayTransaction(doubleSpend); - - // Share conflict with wallet - g_signals.SyncTransaction(doubleSpend, NULL); + return true; } From 2882d594fed93dc5bde67ffa33624ab29f90ac8b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 2 Jul 2014 08:14:50 +0200 Subject: [PATCH 289/336] Fix the Qt5 build after d95ba75 Sorry, my own fault this time. --- src/qt/bitcoin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 569facb499..7c4af25edf 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -134,7 +134,7 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons { Q_UNUSED(context); const char *category = (type == QtDebugMsg) ? "qt" : NULL; - LogPrint(category, "GUI: %s\n", QString::toStdString(msg)); + LogPrint(category, "GUI: %s\n", msg.toStdString()); } #endif From dd49e92fb0cae0dcdf0b2ea303da99c7814db473 Mon Sep 17 00:00:00 2001 From: Julian Haight Date: Wed, 2 Jul 2014 09:42:15 +0200 Subject: [PATCH 290/336] qt: fix 'opens in testnet mode when presented with a BIP-72 link with no fallback' Passes tests: ``` $ ./bitcoin-qt 'bitcoin:?r=http://www.example.com/' .. fixed the original problem - this launches mainnet. $ ./bitcoin-qt 'bitcoin:mngeNQbTKnmaMbx8EXCYdwUbnt9JJD52cC' .. launches testnet $ ./bitcoin-qt -testnet 'bitcoin:1NXXeQRyMFFFRfyUix2o7mk1vhvk2Nxp78' .. sanity check - launches mainnet. ``` Fixes #4355. Closes #4411. --- src/qt/paymentserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 2049d65073..6ca90f0513 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -195,7 +195,7 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) savedPaymentRequests.append(arg); SendCoinsRecipient r; - if (GUIUtil::parseBitcoinURI(arg, &r)) + if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty()) { CBitcoinAddress address(r.address.toStdString()); From 9d5ad718cfdceb0975250ce8268eea400d6f582a Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Wed, 2 Jul 2014 16:32:02 +0800 Subject: [PATCH 291/336] Fix formatting in release-process.md --- doc/release-process.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/release-process.md b/doc/release-process.md index 324b8c43ab..c588381411 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -23,7 +23,7 @@ Release Process * * * -##perform gitian builds +###perform gitian builds From a directory containing the bitcoin source, gitian-builder and gitian.sigs @@ -34,7 +34,7 @@ Release Process popd pushd ./gitian-builder - ###Fetch and build inputs: (first time, or when dependency versions change) +###fetch and build inputs: (first time, or when dependency versions change) mkdir -p inputs; cd inputs/ From 3f7a61fc0966bc63dfcafd231c449d922abb884c Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Wed, 2 Jul 2014 17:16:49 +0800 Subject: [PATCH 292/336] Update Gitian Build guide to include OSX --- doc/gitian-building.md | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index 378a45eda5..b356a5d88d 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -4,8 +4,8 @@ Gitian building *Setup instructions for a gitian build of Bitcoin using a Debian VM or physical system.* Gitian is the deterministic build process that is used to build the Bitcoin -Core executables [1]. It provides a way to be reasonably sure that the -executables are really built from source on github. It also makes sure that +Core executables. It provides a way to be reasonably sure that the +executables are really built from source on GitHub. It also makes sure that the same, tested dependencies are used and statically built into the executable. Multiple developers build the source code by following a specific descriptor @@ -17,9 +17,6 @@ More independent gitian builders are needed, which is why I wrote this guide. It is preferred to follow these steps yourself instead of using someone else's VM image to avoid 'contaminating' the build. -[1] For all platforms except for MacOSX, at this point. Work for deterministic -builds for Mac is under way here: https://github.com/theuni/osx-cross-depends . - Table of Contents ------------------ @@ -38,7 +35,7 @@ Preparing the Gitian builder host --------------------------------- The first step is to prepare the host environment that will be used to perform the Gitian builds. -In this guide it is explained how to set up the environment, and how to get the builds started. +This guide explains how to set up the environment, and how to start the builds. Debian Linux was chosen as the host distribution because it has a lightweight install (in contrast to Ubuntu) and is readily available. Any kind of virtualization can be used, for example: @@ -134,7 +131,7 @@ and proceed, just press `Enter`. To select a different button, press `Tab`. ![](gitian-building/debian_install_5_configure_the_network.png) -- Choose a root password and enter it twice (and remember it for later) +- Choose a root password and enter it twice (remember it for later) ![](gitian-building/debian_install_6a_set_up_root_password.png) @@ -143,7 +140,7 @@ and proceed, just press `Enter`. To select a different button, press `Tab`. ![](gitian-building/debian_install_7_set_up_user_fullname.png) ![](gitian-building/debian_install_8_set_up_username.png) -- Choose a user password and enter it twice (and remember it for later) +- Choose a user password and enter it twice (remember it for later) ![](gitian-building/debian_install_9_user_password.png) @@ -236,7 +233,7 @@ adduser debian sudo When you get a colorful screen with a question about the 'LXC directory', just go with the default (`/var/lib/lxc`). -Then set up LXC and the rest with the following is a complex jumble of settings and workarounds: +Then set up LXC and the rest with the following, which is a complex jumble of settings and workarounds: ```bash # the version of lxc-start in Debian 7.4 needs to run as root, so make sure @@ -280,7 +277,7 @@ cd .. **Note**: When sudo asks for a password, enter the password for the user *debian* not for *root*. -Clone the git repositories for bitcoin and gitian and then checkout the bitcoin version that you are willing to build. +Clone the git repositories for bitcoin and gitian and then checkout the bitcoin version that you want to build. ```bash git clone https://github.com/devrandom/gitian-builder.git @@ -319,10 +316,10 @@ you will find a list of `wget` commands that can be executed to get the dependen I needed to add `--no-check-certificate` to the OpenSSL wget line to make it work. Likely this is because the ca-certificates in Debian 7.4 is fairly old. This does not create a -security issue as the gitian descriptors check integrity of the input archives and refuse to work +security issue as the gitian descriptors check the integrity of the input archives and refuse to work if any one is corrupted. -After downloading the archives, execute the `gbuild` commends to build the dependencies. +After downloading the archives, execute the `gbuild` commands to build the dependencies. This can take a long time, but only has to be done when the dependencies change, for example to upgrade the used version. @@ -339,7 +336,7 @@ tail -f var/build.log Building Bitcoin ---------------- -To build Bitcoin (for Linux and/or Windows) just follow the steps under 'perform +To build Bitcoin (for Linux, OSX and Windows) just follow the steps under 'perform gitian builds' in [doc/release-process.md](release-process.md) in the bitcoin repository. Output from `gbuild` will look something like @@ -372,7 +369,7 @@ can be inspected in `var/install.log` and `var/build.log`. Building an alternative repository ----------------------------------- -If you want to do a test build of a pull on github it can be useful to point +If you want to do a test build of a pull on GitHub it can be useful to point the gitian builder at an alternative repository, using the same descriptors and inputs. @@ -382,13 +379,14 @@ URL=https://github.com/laanwj/bitcoin.git COMMIT=2014_03_windows_unicode_path ./bin/gbuild --commit bitcoin=${COMMIT} --url bitcoin=${URL} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml ./bin/gbuild --commit bitcoin=${COMMIT} --url bitcoin=${URL} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml +./bin/gbuild --commit bitcoin=${COMMIT} --url bitcoin=${URL} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml ``` Signing externally ------------------- -If you want to do the PGP signing on another device that's possible too; just define `SIGNER` as mentioned -and follow the steps in the build process as normally. +If you want to do the PGP signing on another device that's also possible; just define `SIGNER` as mentioned +and follow the steps in the build process as normal. gpg: skipped "laanwj": secret key not available @@ -396,8 +394,9 @@ When you execute `gsign` you will get an error from GPG, which can be ignored. C in `gitian.sigs` to your signing machine and do ```bash - gpg --detach-sign ${VERSION}/${SIGNER}/bitcoin-build.assert + gpg --detach-sign ${VERSION}-linux/${SIGNER}/bitcoin-build.assert gpg --detach-sign ${VERSION}-win/${SIGNER}/bitcoin-build.assert + gpg --detach-sign ${VERSION}-osx/${SIGNER}/bitcoin-build.assert ``` This will create the `.sig` files that can be committed together with the `.assert` files to assert your @@ -407,5 +406,5 @@ Uploading signatures --------------------- After building and signing you can push your signatures (both the `.assert` and `.assert.sig` files) to the -[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or if not possible create a pull +[bitcoin/gitian.sigs](https://github.com/bitcoin/gitian.sigs/) repository, or if that's not possible create a pull request. You can also mail the files to me (laanwj@gmail.com) and I'll commit them. From c8988460a2865b99ee96da6799d37ac6ccb79d4d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Jul 2013 01:06:01 +0200 Subject: [PATCH 293/336] Add support for watch-only addresses Changes: * Add Add/Have WatchOnly methods to CKeyStore, and implementations in CBasicKeyStore. * Add similar methods to CWallet, and support entries for it in CWalletDB. * Make IsMine in script/wallet return a new enum 'isminetype', rather than a boolean. This allows distinguishing between spendable and unspendable coins. * Add a field fSpendable to COutput (GetAvailableCoins' return type). * Mark watchonly coins in listunspent as 'watchonly': true. * Add 'watchonly' to validateaddress, suppressing script/pubkey/... in this case. Based on a patch by Eric Lombrozo. Conflicts: src/qt/walletmodel.cpp src/rpcserver.cpp src/wallet.cpp --- src/keystore.cpp | 12 +++++++++ src/keystore.h | 19 ++++++++++++++ src/qt/walletmodel.cpp | 6 ++--- src/rpcclient.cpp | 1 + src/rpcdump.cpp | 45 +++++++++++++++++++++++++++++++++ src/rpcmisc.cpp | 52 +++++++++++++++++++++++---------------- src/rpcrawtransaction.cpp | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + src/script.cpp | 52 +++++++++++++++++++++++++++++---------- src/script.h | 12 +++++++-- src/test/wallet_tests.cpp | 2 +- src/wallet.cpp | 35 ++++++++++++++++++++------ src/wallet.h | 14 ++++++++--- src/walletdb.cpp | 19 ++++++++++++++ src/walletdb.h | 3 +++ 16 files changed, 223 insertions(+), 52 deletions(-) diff --git a/src/keystore.cpp b/src/keystore.cpp index 594e0c61da..c2ea1ce5a9 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -59,3 +59,15 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) return false; } +bool CBasicKeyStore::AddWatchOnly(const CTxDestination &dest) +{ + LOCK(cs_KeyStore); + setWatchOnly.insert(dest); + return true; +} + +bool CBasicKeyStore::HaveWatchOnly(const CTxDestination &dest) const +{ + LOCK(cs_KeyStore); + return setWatchOnly.count(dest) > 0; +} diff --git a/src/keystore.h b/src/keystore.h index 79d8661aca..90fc3a4c7b 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -8,11 +8,21 @@ #include "key.h" #include "sync.h" +#include "script.h" // for CNoDestination #include +#include class CScript; +/** A txout script template with a specific destination. It is either: + * * CNoDestination: no destination set + * * CKeyID: TX_PUBKEYHASH destination + * * CScriptID: TX_SCRIPTHASH destination + * A CTxDestination is the internal data type encoded in a CBitcoinAddress + */ +typedef boost::variant CTxDestination; + /** A virtual base class for key stores */ class CKeyStore { @@ -36,10 +46,15 @@ public: virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; + + // Support for Watch-only addresses + virtual bool AddWatchOnly(const CTxDestination &dest) =0; + virtual bool HaveWatchOnly(const CTxDestination &dest) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; +typedef std::set WatchOnlySet; /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore @@ -47,6 +62,7 @@ class CBasicKeyStore : public CKeyStore protected: KeyMap mapKeys; ScriptMap mapScripts; + WatchOnlySet setWatchOnly; public: bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); @@ -88,6 +104,9 @@ public: virtual bool AddCScript(const CScript& redeemScript); virtual bool HaveCScript(const CScriptID &hash) const; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; + + virtual bool AddWatchOnly(const CTxDestination &dest); + virtual bool HaveWatchOnly(const CTxDestination &dest) const; }; typedef std::vector > CKeyingMaterial; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index defc815def..d32e74b78a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -543,7 +543,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vOutputs.push_back(out); } } @@ -570,7 +570,7 @@ void WalletModel::listCoins(std::map >& mapCoins) if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vCoins.push_back(out); } @@ -581,7 +581,7 @@ void WalletModel::listCoins(std::map >& mapCoins) while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) { if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; - cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); } CTxDestination address; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 501940a730..76c99e7c9f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -72,6 +72,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "lockunspent", 0 }, { "lockunspent", 1 }, { "importprivkey", 2 }, + { "importaddress", 2 }, { "verifychain", 0 }, { "verifychain", 1 }, { "keypoolrefill", 0 }, diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 593e0d2b6b..5b325c46ee 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -133,6 +133,51 @@ Value importprivkey(const Array& params, bool fHelp) return Value::null; } +Value importaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 3) + throw runtime_error( + "importaddress
[label] [rescan=true]\n" + "Adds an address that can be watched as if it were in your wallet but cannot be used to spend."); + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + CTxDestination dest; + dest = address.Get(); + + string strLabel = ""; + if (params.size() > 1) + strLabel = params[1].get_str(); + + // Whether to perform rescan after import + bool fRescan = true; + if (params.size() > 2) + fRescan = params[2].get_bool(); + + { + LOCK2(cs_main, pwalletMain->cs_wallet); + + // Don't throw error in case an address is already there + if (pwalletMain->HaveWatchOnly(dest)) + return Value::null; + + pwalletMain->MarkDirty(); + pwalletMain->SetAddressBook(dest, strLabel, "receive"); + + if (!pwalletMain->AddWatchOnly(dest)) + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + + if (fRescan) + { + pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); + pwalletMain->ReacceptWalletTransactions(); + } + } + + return Value::null; +} + Value importwallet(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 5b470516a1..e2de2dbcdb 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -92,36 +92,45 @@ Value getinfo(const Array& params, bool fHelp) #ifdef ENABLE_WALLET class DescribeAddressVisitor : public boost::static_visitor { +private: + isminetype mine; + public: + DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {} + Object operator()(const CNoDestination &dest) const { return Object(); } Object operator()(const CKeyID &keyID) const { Object obj; CPubKey vchPubKey; - pwalletMain->GetPubKey(keyID, vchPubKey); obj.push_back(Pair("isscript", false)); - obj.push_back(Pair("pubkey", HexStr(vchPubKey))); - obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + if (mine == MINE_SPENDABLE) { + pwalletMain->GetPubKey(keyID, vchPubKey); + obj.push_back(Pair("pubkey", HexStr(vchPubKey))); + obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + } return obj; } Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - CScript subscript; - pwalletMain->GetCScript(scriptID, subscript); - std::vector addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.push_back(Pair("script", GetTxnOutputType(whichType))); - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); - Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - obj.push_back(Pair("addresses", a)); - if (whichType == TX_MULTISIG) - obj.push_back(Pair("sigsrequired", nRequired)); + if (mine == MINE_SPENDABLE) { + CScript subscript; + pwalletMain->GetCScript(scriptID, subscript); + std::vector addresses; + txnouttype whichType; + int nRequired; + ExtractDestinations(subscript, whichType, addresses, nRequired); + obj.push_back(Pair("script", GetTxnOutputType(whichType))); + obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + obj.push_back(Pair("addresses", a)); + if (whichType == TX_MULTISIG) + obj.push_back(Pair("sigsrequired", nRequired)); + } return obj; } }; @@ -161,10 +170,11 @@ Value validateaddress(const Array& params, bool fHelp) string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET - bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false; - ret.push_back(Pair("ismine", fMine)); - if (fMine) { - Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; + ret.push_back(Pair("ismine", mine != MINE_NO)); + if (mine != MINE_NO) { + ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); + Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 9771f8e685..da4bde3975 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -304,6 +304,7 @@ Value listunspent(const Array& params, bool fHelp) } entry.push_back(Pair("amount",ValueFromAmount(nValue))); entry.push_back(Pair("confirmations",out.nDepth)); + entry.push_back(Pair("spendable", out.fSpendable)); results.push_back(entry); } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f47b3385da..363403c69e 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -282,6 +282,7 @@ static const CRPCCommand vRPCCommands[] = { "getwalletinfo", &getwalletinfo, true, false, true }, { "importprivkey", &importprivkey, false, false, true }, { "importwallet", &importwallet, false, false, true }, + { "importaddress", &importaddress, false, false, true }, { "keypoolrefill", &keypoolrefill, true, false, true }, { "listaccounts", &listaccounts, false, false, true }, { "listaddressgroupings", &listaddressgroupings, false, false, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 01e77163c4..e32eb975a1 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -131,6 +131,7 @@ extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fH extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value importaddress(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); diff --git a/src/script.cpp b/src/script.cpp index e1b6985408..0ef0126255 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1456,36 +1456,57 @@ public: bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } }; -bool IsMine(const CKeyStore &keystore, const CTxDestination &dest) +isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest) { - return boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest); + if (boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(dest)) + return MINE_WATCH_ONLY; + return MINE_NO; } -bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) +isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) { vector vSolutions; txnouttype whichType; - if (!Solver(scriptPubKey, whichType, vSolutions)) - return false; + if (!Solver(scriptPubKey, whichType, vSolutions)) { + if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + return MINE_WATCH_ONLY; + return MINE_NO; + } CKeyID keyID; switch (whichType) { case TX_NONSTANDARD: case TX_NULL_DATA: - return false; + break; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); - return keystore.HaveKey(keyID); + if (keystore.HaveKey(keyID)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(keyID)) + return MINE_WATCH_ONLY; + break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); - return keystore.HaveKey(keyID); + if (keystore.HaveKey(keyID)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(keyID)) + return MINE_WATCH_ONLY; + break; case TX_SCRIPTHASH: { + CScriptID scriptID = CScriptID(uint160(vSolutions[0])); CScript subscript; - if (!keystore.GetCScript(CScriptID(uint160(vSolutions[0])), subscript)) - return false; - return IsMine(keystore, subscript); + if (keystore.GetCScript(scriptID, subscript)) { + isminetype ret = IsMine(keystore, subscript); + if (ret) + return ret; + } + if (keystore.HaveWatchOnly(scriptID)) + return MINE_WATCH_ONLY; + break; } case TX_MULTISIG: { @@ -1495,10 +1516,15 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // them) enable spend-out-from-under-you attacks, especially // in shared-wallet situations. vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); - return HaveKeys(keys, keystore) == keys.size(); + if (HaveKeys(keys, keystore) == keys.size()) + return MINE_SPENDABLE; + break; } } - return false; + + if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + return MINE_WATCH_ONLY; + return MINE_NO; } bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) diff --git a/src/script.h b/src/script.h index 7ab471f6e6..1db758094e 100644 --- a/src/script.h +++ b/src/script.h @@ -194,6 +194,14 @@ enum SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length }; +/** IsMine() return codes */ +enum isminetype +{ + MINE_NO = 0, + MINE_WATCH_ONLY = 1, + MINE_SPENDABLE = 2, +}; + // Mandatory script verification flags that all new blocks must comply with for // them to be valid. (but old blocks may not comply with) Currently just P2SH, // but in the future other flags may be added, such as a soft-fork to enforce @@ -801,8 +809,8 @@ bool EvalScript(std::vector >& stack, const CScript& bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions); bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); -bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination &dest); void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 86a83f5163..3887efbd0d 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -46,7 +46,7 @@ static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, in wtx->fDebitCached = true; wtx->nDebitCached = 1; } - COutput output(wtx, nInput, nAge); + COutput output(wtx, nInput, nAge, true); vCoins.push_back(output); } diff --git a/src/wallet.cpp b/src/wallet.cpp index daca7ac04b..3d679f4c56 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -145,6 +145,22 @@ bool CWallet::LoadCScript(const CScript& redeemScript) return CCryptoKeyStore::AddCScript(redeemScript); } +bool CWallet::AddWatchOnly(const CTxDestination &dest) +{ + if (!CCryptoKeyStore::AddWatchOnly(dest)) + return false; + nTimeFirstKey = 1; // No birthday information for watch-only keys. + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteWatchOnly(dest); +} + +bool CWallet::LoadWatchOnly(const CTxDestination &dest) +{ + LogPrintf("Loaded %s!\n", CBitcoinAddress(dest).ToString().c_str()); + return CCryptoKeyStore::AddWatchOnly(dest); +} + bool CWallet::Unlock(const SecureString& strWalletPassphrase) { CCrypter crypter; @@ -680,7 +696,7 @@ void CWallet::EraseFromWallet(const uint256 &hash) } -bool CWallet::IsMine(const CTxIn &txin) const +isminetype CWallet::IsMine(const CTxIn &txin) const { { LOCK(cs_wallet); @@ -689,11 +705,10 @@ bool CWallet::IsMine(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev.vout[txin.prevout.n])) - return true; + return IsMine(prev.vout[txin.prevout.n]); } } - return false; + return MINE_NO; } int64_t CWallet::GetDebit(const CTxIn &txin) const @@ -1051,7 +1066,7 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } -// populate vCoins with vector of spendable COutputs +// populate vCoins with vector of available COutputs. void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { vCoins.clear(); @@ -1077,10 +1092,11 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) { - if (!(IsSpent(wtxid, i)) && IsMine(pcoin->vout[i]) && + isminetype mine = IsMine(pcoin->vout[i]); + if (!(IsSpent(wtxid, i)) && mine != MINE_NO && !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth)); + vCoins.push_back(COutput(pcoin, i, nDepth, mine & MINE_SPENDABLE)); } } } @@ -1147,8 +1163,11 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); - BOOST_FOREACH(COutput output, vCoins) + BOOST_FOREACH(const COutput &output, vCoins) { + if (!output.fSpendable) + continue; + const CWalletTx *pcoin = output.tx; if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) diff --git a/src/wallet.h b/src/wallet.h index 1c2512d678..ff6af3a6a8 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -226,6 +226,11 @@ public: /// Look up a destination data tuple in the store, return true if found false otherwise bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; + // Adds a watch-only address to the store, and saves it to disk. + bool AddWatchOnly(const CTxDestination &dest); + // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) + bool LoadWatchOnly(const CTxDestination &dest); + bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); @@ -279,9 +284,9 @@ public: std::set GetAccountAddresses(std::string strAccount) const; - bool IsMine(const CTxIn& txin) const; + isminetype IsMine(const CTxIn& txin) const; int64_t GetDebit(const CTxIn& txin) const; - bool IsMine(const CTxOut& txout) const + isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } @@ -722,10 +727,11 @@ public: const CWalletTx *tx; int i; int nDepth; + bool fSpendable; - COutput(const CWalletTx *txIn, int iIn, int nDepthIn) + COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn) { - tx = txIn; i = iIn; nDepth = nDepthIn; + tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; } std::string ToString() const diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 3ce2ef019c..9338d57097 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,6 +112,12 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } +bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +{ + nWalletDBUpdated++; + return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); +} + bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { nWalletDBUpdated++; @@ -404,6 +410,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } + else if (strType == "watch") + { + std::string strAddress; + ssKey >> strAddress; + char fYes; + ssValue >> fYes; + if (fYes == '1') + pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + + // Watch-only addresses have no birthday information for now, + // so set the wallet birthday to the beginning of time. + pwallet->nTimeFirstKey = 1; + } else if (strType == "key" || strType == "wkey") { CPubKey vchPubKey; diff --git a/src/walletdb.h b/src/walletdb.h index 8eb716acbb..3a6cb152a1 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -7,6 +7,7 @@ #include "db.h" #include "key.h" +#include "keystore.h" #include #include @@ -93,6 +94,8 @@ public: bool WriteCScript(const uint160& hash, const CScript& redeemScript); + bool WriteWatchOnly(const CTxDestination &dest); + bool WriteBestBlock(const CBlockLocator& locator); bool ReadBestBlock(CBlockLocator& locator); From 2935b211033610d7ef0deef9bf1b344a5bac029f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Dec 2013 15:27:53 +0100 Subject: [PATCH 294/336] qt: Hide unspendable outputs in coin control --- src/qt/walletmodel.cpp | 6 ++++-- src/wallet.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index d32e74b78a..098d39e8a7 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -60,7 +60,8 @@ qint64 WalletModel::getBalance(const CCoinControl *coinControl) const std::vector vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) - nBalance += out.tx->vout[out.i].nValue; + if(out.fSpendable) + nBalance += out.tx->vout[out.i].nValue; return nBalance; } @@ -585,7 +586,8 @@ void WalletModel::listCoins(std::map >& mapCoins) } CTxDestination address; - if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; + if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) + continue; mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); } } diff --git a/src/wallet.cpp b/src/wallet.cpp index 3d679f4c56..40ace9c40b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1259,6 +1259,8 @@ bool CWallet::SelectCoins(int64_t nTargetValue, setvout[out.i].nValue; setCoinsRet.insert(make_pair(out.tx, out.i)); } From ffd40da361639faeef405c7e4a504a340d77aa5b Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 29 Mar 2014 05:15:28 +0100 Subject: [PATCH 295/336] Watchonly balances are shown separately in gui. --- src/qt/forms/overviewpage.ui | 525 +++++++++++++++++++++++------------ src/qt/overviewpage.cpp | 34 ++- src/qt/overviewpage.h | 6 +- src/qt/sendcoinsdialog.cpp | 13 +- src/qt/sendcoinsdialog.h | 3 +- src/qt/transactiondesc.cpp | 64 +++-- src/qt/transactionrecord.cpp | 17 +- src/qt/walletmodel.cpp | 27 +- src/qt/walletmodel.h | 9 +- src/rpcdump.cpp | 4 +- src/rpcmisc.cpp | 2 +- src/script.h | 2 + src/wallet.cpp | 53 +++- src/wallet.h | 71 ++++- 14 files changed, 597 insertions(+), 233 deletions(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index e662912781..8784da5f3e 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -6,7 +6,7 @@ 0 0 - 573 + 596 342 @@ -46,204 +46,369 @@ - - - - 75 - true - - - - Wallet - - + + + + + + 75 + true + + + + Wallet + + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. + + + QLabel { color: red; } + + + (out of sync) + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - - - The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. - - - QLabel { color: red; } - - - (out of sync) - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + 75 + true + + + + Watchonly: + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - 12 - - - - - Available: + + + + + QFormLayout::AllNonFixedFieldsGrow - + + 12 + + + 12 + + + + + Available: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current spendable balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Pending: + + + + + + + + 75 + true + + + + IBeamCursor + + + Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Immature: + + + + + + + + 75 + true + + + + IBeamCursor + + + Mined balance that has not yet matured + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + + + + Total: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current total balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + - - - - - 75 - true - + + + + QFormLayout::AllNonFixedFieldsGrow - - IBeamCursor + + 12 - - Your current spendable balance + + 12 - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - + + + + + 75 + true + + + + IBeamCursor + + + Your current balance in watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 75 + true + + + + IBeamCursor + + + Unconfirmed transactions to watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 75 + true + + + + IBeamCursor + + + Mined balance in watchonly addresses that has not yet matured + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + Qt::Horizontal + + + + + + + + 75 + true + + + + IBeamCursor + + + Current total balance in watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + - - - - Pending: - - - - - - - - 75 - true - - - - IBeamCursor - - - Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Immature: - - - - - - - - 75 - true - - - - Mined balance that has not yet matured - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Total: - - - - - - - - 75 - true - - - - IBeamCursor - - - Your current total balance - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - - Qt::Horizontal + + QSizePolicy::Expanding + - 40 + 20 20 diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 1a9d1de571..1278f368cf 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -103,6 +103,9 @@ OverviewPage::OverviewPage(QWidget *parent) : currentBalance(-1), currentUnconfirmedBalance(-1), currentImmatureBalance(-1), + currentWatchOnlyBalance(-1), + currentWatchUnconfBalance(-1), + currentWatchImmatureBalance(-1), txdelegate(new TxViewDelegate()), filter(0) { @@ -135,22 +138,39 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) +void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance) { int unit = walletModel->getOptionsModel()->getDisplayUnit(); currentBalance = balance; currentUnconfirmedBalance = unconfirmedBalance; currentImmatureBalance = immatureBalance; + currentWatchOnlyBalance = watchOnlyBalance; + currentWatchUnconfBalance = watchUnconfBalance; + currentWatchImmatureBalance = watchImmatureBalance; ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance)); ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance)); + ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance)); + ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance)); + ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance)); + ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance)); // only show immature (newly mined) balance if it's non-zero, so as not to complicate things // for the non-mining users bool showImmature = immatureBalance != 0; - ui->labelImmature->setVisible(showImmature); - ui->labelImmatureText->setVisible(showImmature); + bool showWatchOnlyImmature = watchImmatureBalance != 0; + bool showWatchOnly = (watchOnlyBalance != 0 || watchUnconfBalance != 0 || showWatchOnlyImmature); + + // for symmetry reasons also show immature label when the watchonly one is shown + ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature); + ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature); + ui->labelWatchonly->setVisible(showWatchOnly); // show Watchonly label + ui->lineWatchBalance->setVisible(showWatchOnly); // show watchonly balance separator line + ui->labelWatchAvailable->setVisible(showWatchOnly); // show watchonly available balance + ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watchonly immature balance + ui->labelWatchPending->setVisible(showWatchOnly); // show watchonly pending balance + ui->labelWatchTotal->setVisible(showWatchOnly); // show watchonly total balance } void OverviewPage::setClientModel(ClientModel *model) @@ -182,8 +202,9 @@ void OverviewPage::setWalletModel(WalletModel *model) ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); // Keep up to date with wallet - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); + setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), + model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); } @@ -197,7 +218,8 @@ void OverviewPage::updateDisplayUnit() if(walletModel && walletModel->getOptionsModel()) { if(currentBalance != -1) - setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance); + setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance, + currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance); // Update txdelegate->unit with the current unit txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit(); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 2507a3fb31..fe00106770 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -34,7 +34,8 @@ public: void showOutOfSyncWarning(bool fShow); public slots: - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); signals: void transactionClicked(const QModelIndex &index); @@ -46,6 +47,9 @@ private: qint64 currentBalance; qint64 currentUnconfirmedBalance; qint64 currentImmatureBalance; + qint64 currentWatchOnlyBalance; + qint64 currentWatchUnconfBalance; + qint64 currentWatchImmatureBalance; TxViewDelegate *txdelegate; TransactionFilterProxy *filter; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index b7d74d7039..6f10ed5b0b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -90,8 +90,9 @@ void SendCoinsDialog::setModel(WalletModel *model) } } - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); + setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), + model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); // Coin Control @@ -383,10 +384,14 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) return true; } -void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) +void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchBalance, qint64 watchUnconfirmedBalance, qint64 watchImmatureBalance) { Q_UNUSED(unconfirmedBalance); Q_UNUSED(immatureBalance); + Q_UNUSED(watchBalance); + Q_UNUSED(watchUnconfirmedBalance); + Q_UNUSED(watchImmatureBalance); if(model && model->getOptionsModel()) { @@ -396,7 +401,7 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint void SendCoinsDialog::updateDisplayUnit() { - setBalance(model->getBalance(), 0, 0); + setBalance(model->getBalance(), 0, 0, 0, 0, 0); } void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index fcae26c720..6cdf4a00c8 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -47,7 +47,8 @@ public slots: void accept(); SendCoinsEntry *addEntry(); void updateTabsAndLabels(); - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); private: Ui::SendCoinsDialog *ui; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index e48dbcac9d..76dc47318d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -89,19 +89,27 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (nNet > 0) { // Credit - if (CBitcoinAddress(rec->address).IsValid()) + BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - CTxDestination address = CBitcoinAddress(rec->address).Get(); - if (wallet->mapAddressBook.count(address)) + if (wallet->IsMine(txout)) { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(rec->address); - if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; - else - strHTML += " (" + tr("own address") + ")"; - strHTML += "
"; + if (CBitcoinAddress(rec->address).IsValid()) + { + CTxDestination address = CBitcoinAddress(rec->address).Get(); + if (wallet->mapAddressBook.count(address)) + { + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(rec->address); + std::string addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? "own address" : "watch-only"; + if (!wallet->mapAddressBook[address].name.empty()) + strHTML += " (" + tr(addressOwned.c_str()) + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + else + strHTML += " (" + tr(addressOwned.c_str()) + ")"; + strHTML += "
"; + } + } + break; } } } @@ -148,22 +156,33 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco } else { - bool fAllFromMe = true; + isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) - fAllFromMe = fAllFromMe && wallet->IsMine(txin); + { + isminetype mine = wallet->IsMine(txin); + if(fAllFromMe > mine) fAllFromMe = mine; + } - bool fAllToMe = true; + isminetype fAllToMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - fAllToMe = fAllToMe && wallet->IsMine(txout); + { + isminetype mine = wallet->IsMine(txout); + if(fAllToMe > mine) fAllToMe = mine; + } if (fAllFromMe) { + if(fAllFromMe == MINE_WATCH_ONLY) + strHTML += "" + tr("From") + ": " + tr("watch-only") + "
"; + // // Debit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - if (wallet->IsMine(txout)) + // Ignore change + isminetype toSelf = wallet->IsMine(txout); + if ((toSelf == MINE_SPENDABLE) && (fAllFromMe == MINE_SPENDABLE)) continue; if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) @@ -176,11 +195,17 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + if(toSelf == MINE_SPENDABLE) + strHTML += " (own address)"; + else if(toSelf == MINE_WATCH_ONLY) + strHTML += " (watch-only)"; strHTML += "
"; } } strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "
"; + if(toSelf) + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, txout.nValue) + "
"; } if (fAllToMe) @@ -188,8 +213,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // Payment to self int64_t nChange = wtx.GetChange(); int64_t nValue = nCredit - nChange; - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -nValue) + "
"; - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, nValue) + "
"; + strHTML += "" + tr("Total debit") + ": " + BitcoinUnits::formatWithUnit(unit, -nValue) + "
"; + strHTML += "" + tr("Total credit") + ": " + BitcoinUnits::formatWithUnit(unit, nValue) + "
"; } int64_t nTxFee = nDebit - wtx.GetValueOut(); @@ -286,7 +311,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); } strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue); - strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & MINE_SPENDABLE ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & MINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 21f1b7356f..3d77d39893 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -45,7 +45,8 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - if(wallet->IsMine(txout)) + isminetype mine = wallet->IsMine(txout); + if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; @@ -75,13 +76,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } else { - bool fAllFromMe = true; + isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) - fAllFromMe = fAllFromMe && wallet->IsMine(txin); + { + isminetype mine = wallet->IsMine(txin); + if(fAllFromMe > mine) fAllFromMe = mine; + } - bool fAllToMe = true; + isminetype fAllToMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - fAllToMe = fAllToMe && wallet->IsMine(txout); + { + isminetype mine = wallet->IsMine(txout); + if(fAllToMe > mine) fAllToMe = mine; + } if (fAllFromMe && fAllToMe) { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 098d39e8a7..7317c32766 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -79,6 +79,21 @@ qint64 WalletModel::getImmatureBalance() const return wallet->GetImmatureBalance(); } +qint64 WalletModel::getWatchBalance() const +{ + return wallet->GetWatchOnlyBalance(); +} + +qint64 WalletModel::getWatchUnconfirmedBalance() const +{ + return wallet->GetUnconfirmedWatchOnlyBalance(); +} + +qint64 WalletModel::getWatchImmatureBalance() const +{ + return wallet->GetImmatureWatchOnlyBalance(); +} + int WalletModel::getNumTransactions() const { int numTransactions = 0; @@ -127,13 +142,21 @@ void WalletModel::checkBalanceChanged() qint64 newBalance = getBalance(); qint64 newUnconfirmedBalance = getUnconfirmedBalance(); qint64 newImmatureBalance = getImmatureBalance(); + qint64 newWatchOnlyBalance = getWatchBalance(); + qint64 newWatchUnconfBalance = getWatchUnconfirmedBalance(); + qint64 newWatchImmatureBalance = getWatchImmatureBalance(); - if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance || + cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance) { cachedBalance = newBalance; cachedUnconfirmedBalance = newUnconfirmedBalance; cachedImmatureBalance = newImmatureBalance; - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); + cachedWatchOnlyBalance = newWatchOnlyBalance; + cachedWatchUnconfBalance = newWatchUnconfBalance; + cachedWatchImmatureBalance = newWatchImmatureBalance; + emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, + newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance); } } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ccf590aaed..7ad54ff8e6 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -128,6 +128,9 @@ public: qint64 getBalance(const CCoinControl *coinControl = NULL) const; qint64 getUnconfirmedBalance() const; qint64 getImmatureBalance() const; + qint64 getWatchBalance() const; + qint64 getWatchUnconfirmedBalance() const; + qint64 getWatchImmatureBalance() const; int getNumTransactions() const; EncryptionStatus getEncryptionStatus() const; @@ -206,6 +209,9 @@ private: qint64 cachedBalance; qint64 cachedUnconfirmedBalance; qint64 cachedImmatureBalance; + qint64 cachedWatchOnlyBalance; + qint64 cachedWatchUnconfBalance; + qint64 cachedWatchImmatureBalance; qint64 cachedNumTransactions; EncryptionStatus cachedEncryptionStatus; int cachedNumBlocks; @@ -218,7 +224,8 @@ private: signals: // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); // Number of transactions in wallet changed void numTransactionsChanged(int count); diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 5b325c46ee..98af4695d6 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -158,12 +158,14 @@ Value importaddress(const Array& params, bool fHelp) { LOCK2(cs_main, pwalletMain->cs_wallet); + // add to address book or update label + pwalletMain->SetAddressBook(dest, strLabel, "receive"); + // Don't throw error in case an address is already there if (pwalletMain->HaveWatchOnly(dest)) return Value::null; pwalletMain->MarkDirty(); - pwalletMain->SetAddressBook(dest, strLabel, "receive"); if (!pwalletMain->AddWatchOnly(dest)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index e2de2dbcdb..3245f7d713 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -171,7 +171,7 @@ Value validateaddress(const Array& params, bool fHelp) ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", mine != MINE_NO)); + ret.push_back(Pair("ismine", mine == MINE_SPENDABLE)); if (mine != MINE_NO) { ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); diff --git a/src/script.h b/src/script.h index 1db758094e..56c7d01d4e 100644 --- a/src/script.h +++ b/src/script.h @@ -201,6 +201,8 @@ enum isminetype MINE_WATCH_ONLY = 1, MINE_SPENDABLE = 2, }; +/** used for bitflags of isminetype */ +typedef uint8_t isminefilter; // Mandatory script verification flags that all new blocks must comply with for // them to be valid. (but old blocks may not comply with) Currently just P2SH, diff --git a/src/wallet.cpp b/src/wallet.cpp index 40ace9c40b..d4e9fe9d18 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -738,7 +738,7 @@ bool CWallet::IsChange(const CTxOut& txout) const // a better way of identifying which outputs are 'the send' and which are // 'the change' will need to be implemented (maybe extend CWalletTx to remember // which output, if any, was change). - if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address)) + if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address) == MINE_SPENDABLE) { LOCK(cs_wallet); if (!mapAddressBook.count(address)) @@ -793,7 +793,7 @@ int CWalletTx::GetRequestCount() const } void CWalletTx::GetAmounts(list >& listReceived, - list >& listSent, int64_t& nFee, string& strSentAccount) const + list >& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const { nFee = 0; listReceived.clear(); @@ -820,9 +820,9 @@ void CWalletTx::GetAmounts(list >& listReceived, // Don't report 'change' txouts if (pwallet->IsChange(txout)) continue; - fIsMine = pwallet->IsMine(txout); + fIsMine = (pwallet->IsMine(txout) & filter); } - else if (!(fIsMine = pwallet->IsMine(txout))) + else if (!(fIsMine = (pwallet->IsMine(txout) & filter))) continue; // In either case, we need to get the destination address @@ -1066,6 +1066,51 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } +int64_t CWallet::GetWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsTrusted()) + nTotal += pcoin->GetAvailableWatchOnlyCredit(); + } + } + + return nTotal; +} + +int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + nTotal += pcoin->GetAvailableWatchOnlyCredit(); + } + } + return nTotal; +} + +int64_t CWallet::GetImmatureWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + nTotal += pcoin->GetImmatureWatchOnlyCredit(); + } + } + return nTotal; +} + // populate vCoins with vector of available COutputs. void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { diff --git a/src/wallet.h b/src/wallet.h index ff6af3a6a8..355aa36973 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -262,6 +262,9 @@ public: int64_t GetBalance() const; int64_t GetUnconfirmedBalance() const; int64_t GetImmatureBalance() const; + int64_t GetWatchOnlyBalance() const; + int64_t GetUnconfirmedWatchOnlyBalance() const; + int64_t GetImmatureWatchOnlyBalance() const; bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); bool CreateTransaction(CScript scriptPubKey, int64_t nValue, @@ -290,11 +293,11 @@ public: { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); - return (IsMine(txout) ? txout.nValue : 0); + return ((IsMine(txout) & filter) ? txout.nValue : 0); } bool IsChange(const CTxOut& txout) const; int64_t GetChange(const CTxOut& txout) const @@ -332,12 +335,12 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx) const + int64_t GetCredit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { int64_t nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { - nCredit += GetCredit(txout); + nCredit += GetCredit(txout, filter); if (!MoneyRange(nCredit)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); } @@ -483,11 +486,15 @@ public: mutable bool fCreditCached; mutable bool fImmatureCreditCached; mutable bool fAvailableCreditCached; + mutable bool fImmatureWatchCreditCached; + mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; mutable int64_t nDebitCached; mutable int64_t nCreditCached; mutable int64_t nImmatureCreditCached; mutable int64_t nAvailableCreditCached; + mutable int64_t nImmatureWatchCreditCached; + mutable int64_t nAvailableWatchCreditCached; mutable int64_t nChangeCached; CWalletTx() @@ -524,11 +531,15 @@ public: fCreditCached = false; fImmatureCreditCached = false; fAvailableCreditCached = false; + fImmatureWatchCreditCached = false; + fAvailableWatchCreditCached = false; fChangeCached = false; nDebitCached = 0; nCreditCached = 0; nImmatureCreditCached = 0; nAvailableCreditCached = 0; + nAvailableWatchCreditCached = 0; + nImmatureWatchCreditCached = 0; nChangeCached = 0; nOrderPos = -1; } @@ -581,6 +592,8 @@ public: { fCreditCached = false; fAvailableCreditCached = false; + fAvailableWatchCreditCached = false; + fImmatureWatchCreditCached = false; fDebitCached = false; fChangeCached = false; } @@ -622,7 +635,7 @@ public: { if (fUseCache && fImmatureCreditCached) return nImmatureCreditCached; - nImmatureCreditCached = pwallet->GetCredit(*this); + nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE); fImmatureCreditCached = true; return nImmatureCreditCached; } @@ -649,7 +662,7 @@ public: if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout); + nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -660,6 +673,48 @@ public: return nCredit; } + int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const + { + if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) + { + if (fUseCache && fImmatureWatchCreditCached) + return nImmatureWatchCreditCached; + nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY); + fImmatureWatchCreditCached = true; + return nImmatureWatchCreditCached; + } + + return 0; + } + + int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const + { + if (pwallet == 0) + return 0; + + // Must wait until coinbase is safely deep enough in the chain before valuing it + if (IsCoinBase() && GetBlocksToMaturity() > 0) + return 0; + + if (fUseCache && fAvailableWatchCreditCached) + return nAvailableWatchCreditCached; + + int64_t nCredit = 0; + for (unsigned int i = 0; i < vout.size(); i++) + { + if (!pwallet->IsSpent(GetHash(), i)) + { + const CTxOut &txout = vout[i]; + nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); + } + } + + nAvailableWatchCreditCached = nCredit; + fAvailableWatchCreditCached = true; + return nCredit; + } int64_t GetChange() const { @@ -671,7 +726,7 @@ public: } void GetAmounts(std::list >& listReceived, - std::list >& listSent, int64_t& nFee, std::string& strSentAccount) const; + std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee) const; @@ -702,7 +757,7 @@ public: if (parent == NULL) return false; const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (!pwallet->IsMine(parentOut)) + if (pwallet->IsMine(parentOut) != MINE_SPENDABLE) return false; } return true; From d2692f61164730322547871f2124de06ade0436b Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 5 Apr 2014 21:36:48 +0200 Subject: [PATCH 296/336] Watchonly transactions are marked in transaction history --- src/qt/transactionrecord.cpp | 7 +++++++ src/qt/transactionrecord.h | 3 +++ src/qt/transactiontablemodel.cpp | 11 +++++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 3d77d39893..1011363f3e 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -70,16 +70,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * sub.type = TransactionRecord::Generated; } + sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; parts.append(sub); } } } else { + bool involvesWatchAddress = false; isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); + if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } @@ -87,6 +90,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); + if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } @@ -97,6 +101,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); + parts.last().involvesWatchAddress = involvesWatchAddress; } else if (fAllFromMe) { @@ -141,6 +146,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } sub.debit = -nValue; + sub.involvesWatchAddress = involvesWatchAddress; parts.append(sub); } } @@ -150,6 +156,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); + parts.last().involvesWatchAddress = involvesWatchAddress; } } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 37679cebfa..d3cfa77d97 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -137,6 +137,9 @@ public: /** Status: can change with block chain update */ TransactionStatus status; + /** Whether the transaction was sent/received with a watch-only address */ + bool involvesWatchAddress; + /** Return the unique identifier for this transaction (part) */ QString getTxID() const; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index a935752246..c357d26a9d 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -390,19 +390,22 @@ QVariant TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const { + // mark transactions involving watch-only addresses: + QString watchAddress = wtx->involvesWatchAddress ? " (w) " : ""; + switch(wtx->type) { case TransactionRecord::RecvFromOther: - return QString::fromStdString(wtx->address); + return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::RecvWithAddress: case TransactionRecord::SendToAddress: case TransactionRecord::Generated: - return lookupAddress(wtx->address, tooltip); + return lookupAddress(wtx->address, tooltip) + watchAddress; case TransactionRecord::SendToOther: - return QString::fromStdString(wtx->address); + return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::SendToSelf: default: - return tr("(n/a)"); + return tr("(n/a)") + watchAddress; } } From d4640d7d8c3ba373195d33ab75db9c8cb43f8806 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 15:23:50 +0200 Subject: [PATCH 297/336] Added argument to getbalance to include watchonly addresses and fixed errors in balance calculation. --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 23 +++++++++++++-------- src/wallet.cpp | 10 ++++----- src/wallet.h | 52 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 76c99e7c9f..ea5ca8e0f6 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -40,6 +40,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 1 }, { "getbalance", 1 }, + { "getbalance", 2 }, { "getblockhash", 0 }, { "move", 2 }, { "move", 3 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 38e96133b4..79b438d417 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -557,7 +557,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { int64_t nBalance = 0; @@ -569,7 +569,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi continue; int64_t nReceived, nSent, nFee; - wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee); + wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) nBalance += nReceived; @@ -582,18 +582,18 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { CWalletDB walletdb(pwalletMain->strWalletFile); - return GetAccountBalance(walletdb, strAccount, nMinDepth); + return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); } Value getbalance(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "getbalance ( \"account\" minconf )\n" + "getbalance ( \"account\" minconf includeWatchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" "If account is specified, returns the balance in the account.\n" "Note that the account \"\" is not the same as leaving the parameter out.\n" @@ -601,6 +601,7 @@ Value getbalance(const Array& params, bool fHelp) "\nArguments:\n" "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" + "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" "amount (numeric) The total amount in btc received for this account.\n" "\nExamples:\n" @@ -620,8 +621,14 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; + isminefilter filter = MINE_SPENDABLE; if (params.size() > 1) + { nMinDepth = params[1].get_int(); + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -638,7 +645,7 @@ Value getbalance(const Array& params, bool fHelp) string strSentAccount; list > listReceived; list > listSent; - wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (wtx.GetDepthInMainChain() >= nMinDepth) { BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) @@ -653,7 +660,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } diff --git a/src/wallet.cpp b/src/wallet.cpp index d4e9fe9d18..3c9aa3306f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -711,7 +711,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return MINE_NO; } -int64_t CWallet::GetDebit(const CTxIn &txin) const +int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { LOCK(cs_wallet); @@ -720,7 +720,7 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev.vout[txin.prevout.n])) + if (IsMine(prev.vout[txin.prevout.n]) & filter) return prev.vout[txin.prevout.n].nValue; } } @@ -801,7 +801,7 @@ void CWalletTx::GetAmounts(list >& listReceived, strSentAccount = strFromAccount; // Compute fee: - int64_t nDebit = GetDebit(); + int64_t nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { int64_t nValueOut = GetValueOut(); @@ -846,7 +846,7 @@ void CWalletTx::GetAmounts(list >& listReceived, } void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const + int64_t& nSent, int64_t& nFee, const isminefilter& filter) const { nReceived = nSent = nFee = 0; @@ -854,7 +854,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, string strSentAccount; list > listReceived; list > listSent; - GetAmounts(listReceived, listSent, allFee, strSentAccount); + GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (strAccount == strSentAccount) { diff --git a/src/wallet.h b/src/wallet.h index 355aa36973..b11e6c662e 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -288,12 +288,12 @@ public: std::set GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin) const; + int64_t GetDebit(const CTxIn& txin, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter=(MINE_WATCH_ONLY|MINE_SPENDABLE)) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); @@ -324,12 +324,12 @@ public: return true; return false; } - int64_t GetDebit(const CTransaction& tx) const + int64_t GetDebit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { int64_t nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { - nDebit += GetDebit(txin); + nDebit += GetDebit(txin, filter); if (!MoneyRange(nDebit)) throw std::runtime_error("CWallet::GetDebit() : value out of range"); } @@ -486,6 +486,8 @@ public: mutable bool fCreditCached; mutable bool fImmatureCreditCached; mutable bool fAvailableCreditCached; + mutable bool fWatchDebitCached; + mutable bool fWatchCreditCached; mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; @@ -493,6 +495,8 @@ public: mutable int64_t nCreditCached; mutable int64_t nImmatureCreditCached; mutable int64_t nAvailableCreditCached; + mutable int64_t nWatchDebitCached; + mutable int64_t nWatchCreditCached; mutable int64_t nImmatureWatchCreditCached; mutable int64_t nAvailableWatchCreditCached; mutable int64_t nChangeCached; @@ -531,6 +535,8 @@ public: fCreditCached = false; fImmatureCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fImmatureWatchCreditCached = false; fAvailableWatchCreditCached = false; fChangeCached = false; @@ -538,6 +544,8 @@ public: nCreditCached = 0; nImmatureCreditCached = 0; nAvailableCreditCached = 0; + nWatchDebitCached = 0; + nWatchCreditCached = 0; nAvailableWatchCreditCached = 0; nImmatureWatchCreditCached = 0; nChangeCached = 0; @@ -592,6 +600,8 @@ public: { fCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fAvailableWatchCreditCached = false; fImmatureWatchCreditCached = false; fDebitCached = false; @@ -604,15 +614,35 @@ public: MarkDirty(); } - int64_t GetDebit() const + int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { if (vin.empty()) return 0; - if (fDebitCached) - return nDebitCached; - nDebitCached = pwallet->GetDebit(*this); - fDebitCached = true; - return nDebitCached; + + int64_t debit = 0; + if(filter & MINE_SPENDABLE) + { + if (fDebitCached) + debit += nDebitCached; + else + { + nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE); + fDebitCached = true; + debit += nDebitCached; + } + } + if(filter & MINE_WATCH_ONLY) + { + if(fWatchDebitCached) + debit += nWatchDebitCached; + else + { + nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY); + fWatchDebitCached = true; + debit += nWatchDebitCached; + } + } + return debit; } int64_t GetCredit(bool fUseCache=true) const @@ -729,7 +759,7 @@ public: std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const; + int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; bool IsFromMe() const { From 83f3543f20348aa718620314e7deb37bd0f71b90 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 16:13:15 +0200 Subject: [PATCH 298/336] Added argument to listaccounts to include watchonly addresses --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index ea5ca8e0f6..d96b47833f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -49,6 +49,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listtransactions", 1 }, { "listtransactions", 2 }, { "listaccounts", 0 }, + { "listaccounts", 1 }, { "walletpassphrase", 1 }, { "getblocktemplate", 0 }, { "listsinceblock", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 79b438d417..d52a4bc5bb 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1302,12 +1302,13 @@ Value listtransactions(const Array& params, bool fHelp) Value listaccounts(const Array& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 2) throw runtime_error( - "listaccounts ( minconf )\n" + "listaccounts ( minconf includeWatchonly)\n" "\nReturns Object that has account names as keys, account balances as values.\n" "\nArguments:\n" - "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n" + "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n" + "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n" "\nResult:\n" "{ (json object where keys are account names, and values are numeric balances\n" " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n" @@ -1325,12 +1326,18 @@ Value listaccounts(const Array& params, bool fHelp) ); int nMinDepth = 1; + isminefilter includeWatchonly = MINE_SPENDABLE; if (params.size() > 0) + { nMinDepth = params[0].get_int(); + if(params.size() > 1) + if(params[1].get_bool()) + includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; + } map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { - if (IsMine(*pwalletMain, entry.first)) // This address belongs to me + if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me mapAccountBalances[entry.second.name] = 0; } @@ -1344,7 +1351,7 @@ Value listaccounts(const Array& params, bool fHelp) int nDepth = wtx.GetDepthInMainChain(); if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0) continue; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) mapAccountBalances[strSentAccount] -= s.second; From 952877e01c1045298fd51d1152d96c304d4cf2a4 Mon Sep 17 00:00:00 2001 From: JaSK Date: Wed, 9 Apr 2014 17:20:07 +0200 Subject: [PATCH 299/336] Showing 'involvesWatchonly' property for transactions returned by 'listtransactions' and 'listsinceblock'. It is only appended when the transaction involves a watchonly address. --- src/rpcwallet.cpp | 5 +++++ src/wallet.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index d52a4bc5bb..8de10c52f8 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1117,6 +1117,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); bool fAllAccounts = (strAccount == string("*")); + bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) @@ -1124,6 +1125,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) { Object entry; + if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & MINE_WATCH_ONLY)) + entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", strSentAccount)); MaybePushAddress(entry, s.first); entry.push_back(Pair("category", "send")); @@ -1146,6 +1149,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if (fAllAccounts || (account == strAccount)) { Object entry; + if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & MINE_WATCH_ONLY)) + entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.first); if (wtx.IsCoinBase()) diff --git a/src/wallet.h b/src/wallet.h index b11e6c662e..3453d23d97 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -761,9 +761,9 @@ public: void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; - bool IsFromMe() const + bool IsFromMe(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { - return (GetDebit() > 0); + return (GetDebit(filter) > 0); } bool IsTrusted() const From d7d5d23b77e204eccd4bf8a5608c1a499d5fc42f Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 17:51:04 +0200 Subject: [PATCH 300/336] Added argument to listtransactions and listsinceblock to include watchonly addresses --- src/rpcclient.cpp | 3 ++- src/rpcwallet.cpp | 62 ++++++++++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index d96b47833f..f329d517b3 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -48,11 +48,13 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendfrom", 3 }, { "listtransactions", 1 }, { "listtransactions", 2 }, + { "listtransactions", 3 }, { "listaccounts", 0 }, { "listaccounts", 1 }, { "walletpassphrase", 1 }, { "getblocktemplate", 0 }, { "listsinceblock", 1 }, + { "listsinceblock", 2 }, { "sendmany", 1 }, { "sendmany", 2 }, { "addmultisigaddress", 0 }, @@ -129,7 +131,6 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector > listReceived; list > listSent; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter); bool fAllAccounts = (strAccount == string("*")); bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); @@ -1194,16 +1194,16 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Value listtransactions(const Array& params, bool fHelp) { - if (fHelp || params.size() > 3) + if (fHelp || params.size() > 4) throw runtime_error( - "listtransactions ( \"account\" count from )\n" + "listtransactions ( \"account\" count from includeWatchonly)\n" "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n" "\nArguments:\n" "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n" " If \"\" is set, it will list transactions for the default account.\n" "2. count (numeric, optional, default=10) The number of transactions to return\n" "3. from (numeric, optional, default=0) The number of transactions to skip\n" - + "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n" "\nResult:\n" "[\n" " {\n" @@ -1255,15 +1255,26 @@ Value listtransactions(const Array& params, bool fHelp) ); string strAccount = "*"; - if (params.size() > 0) - strAccount = params[0].get_str(); int nCount = 10; - if (params.size() > 1) - nCount = params[1].get_int(); int nFrom = 0; - if (params.size() > 2) - nFrom = params[2].get_int(); - + isminefilter filter = MINE_SPENDABLE; + if (params.size() > 0) + { + strAccount = params[0].get_str(); + if (params.size() > 1) + { + nCount = params[1].get_int(); + if (params.size() > 2) + { + nFrom = params[2].get_int(); + if(params.size() > 3) + { + if(params[3].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } + } + } + } if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); if (nFrom < 0) @@ -1279,7 +1290,7 @@ Value listtransactions(const Array& params, bool fHelp) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) - ListTransactions(*pwtx, strAccount, 0, true, ret); + ListTransactions(*pwtx, strAccount, 0, true, ret, filter); CAccountingEntry *const pacentry = (*it).second.second; if (pacentry != 0) AcentryToJSON(*pacentry, strAccount, ret); @@ -1386,11 +1397,12 @@ Value listsinceblock(const Array& params, bool fHelp) { if (fHelp) throw runtime_error( - "listsinceblock ( \"blockhash\" target-confirmations )\n" + "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n" "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n" "\nArguments:\n" "1. \"blockhash\" (string, optional) The block hash to list transactions since\n" "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n" + "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')" "\nResult:\n" "{\n" " \"transactions\": [\n" @@ -1426,7 +1438,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; - + isminefilter filter = MINE_SPENDABLE; if (params.size() > 0) { uint256 blockId = 0; @@ -1435,14 +1447,20 @@ Value listsinceblock(const Array& params, bool fHelp) std::map::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; - } - if (params.size() > 1) - { - target_confirms = params[1].get_int(); + if (params.size() > 1) + { + target_confirms = params[1].get_int(); - if (target_confirms < 1) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + if (target_confirms < 1) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + + if(params.size() > 2) + { + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } + } } int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; @@ -1454,7 +1472,7 @@ Value listsinceblock(const Array& params, bool fHelp) CWalletTx tx = (*it).second; if (depth == -1 || tx.GetDepthInMainChain() < depth) - ListTransactions(tx, "*", 0, true, transactions); + ListTransactions(tx, "*", 0, true, transactions, filter); } CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms]; From a5c6c5d6df887764ac07664aae842234c19bbf8d Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 29 Apr 2014 19:39:01 +0200 Subject: [PATCH 301/336] fixed tiny glitch and improved readability like laanwj suggested --- src/qt/transactiondesc.cpp | 6 +-- src/rpcmisc.cpp | 4 +- src/rpcwallet.cpp | 76 ++++++++++++++++---------------------- src/wallet.cpp | 6 +-- 4 files changed, 40 insertions(+), 52 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 76dc47318d..d94f066ed9 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -101,11 +101,11 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; strHTML += "" + tr("To") + ": "; strHTML += GUIUtil::HtmlEscape(rec->address); - std::string addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? "own address" : "watch-only"; + QString addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? tr("own address") : tr("watch-only"); if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + tr(addressOwned.c_str()) + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; else - strHTML += " (" + tr(addressOwned.c_str()) + ")"; + strHTML += " (" + addressOwned + ")"; strHTML += "
"; } } diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 3245f7d713..f0b4619b26 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -171,9 +171,9 @@ Value validateaddress(const Array& params, bool fHelp) ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", mine == MINE_SPENDABLE)); + ret.push_back(Pair("ismine", (mine & MINE_SPENDABLE) ? true : false)); if (mine != MINE_NO) { - ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); + ret.push_back(Pair("iswatchonly", (mine & MINE_WATCH_ONLY) ? true: false)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index a9db442d4c..e9a111f523 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -621,14 +621,12 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; - isminefilter filter = MINE_SPENDABLE; if (params.size() > 1) - { nMinDepth = params[1].get_int(); - if(params.size() > 2) - if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -1255,26 +1253,19 @@ Value listtransactions(const Array& params, bool fHelp) ); string strAccount = "*"; - int nCount = 10; - int nFrom = 0; - isminefilter filter = MINE_SPENDABLE; if (params.size() > 0) - { strAccount = params[0].get_str(); - if (params.size() > 1) - { - nCount = params[1].get_int(); - if (params.size() > 2) - { - nFrom = params[2].get_int(); - if(params.size() > 3) - { - if(params[3].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } - } - } - } + int nCount = 10; + if (params.size() > 1) + nCount = params[1].get_int(); + int nFrom = 0; + if (params.size() > 2) + nFrom = params[2].get_int(); + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 3) + if(params[3].get_bool()) + filter = filter | MINE_WATCH_ONLY; + if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); if (nFrom < 0) @@ -1342,14 +1333,12 @@ Value listaccounts(const Array& params, bool fHelp) ); int nMinDepth = 1; - isminefilter includeWatchonly = MINE_SPENDABLE; if (params.size() > 0) - { nMinDepth = params[0].get_int(); - if(params.size() > 1) - if(params[1].get_bool()) - includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; - } + isminefilter includeWatchonly = MINE_SPENDABLE; + if(params.size() > 1) + if(params[1].get_bool()) + includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { @@ -1439,6 +1428,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; isminefilter filter = MINE_SPENDABLE; + if (params.size() > 0) { uint256 blockId = 0; @@ -1447,22 +1437,20 @@ Value listsinceblock(const Array& params, bool fHelp) std::map::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; - - if (params.size() > 1) - { - target_confirms = params[1].get_int(); - - if (target_confirms < 1) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); - - if(params.size() > 2) - { - if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } - } } + if (params.size() > 1) + { + target_confirms = params[1].get_int(); + + if (target_confirms < 1) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + } + + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; Array transactions; diff --git a/src/wallet.cpp b/src/wallet.cpp index 3c9aa3306f..4b480321ac 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -811,7 +811,8 @@ void CWalletTx::GetAmounts(list >& listReceived, // Sent/received. BOOST_FOREACH(const CTxOut& txout, vout) { - bool fIsMine; + isminetype fIsMine = pwallet->IsMine(txout); + // Only need to handle txouts if AT LEAST one of these is true: // 1) they debit from us (sent) // 2) the output is to us (received) @@ -820,9 +821,8 @@ void CWalletTx::GetAmounts(list >& listReceived, // Don't report 'change' txouts if (pwallet->IsChange(txout)) continue; - fIsMine = (pwallet->IsMine(txout) & filter); } - else if (!(fIsMine = (pwallet->IsMine(txout) & filter))) + else if (!(fIsMine & filter)) continue; // In either case, we need to get the destination address From f87ba3df64bb5825f7e2f6a33c93cf5738682019 Mon Sep 17 00:00:00 2001 From: JaSK Date: Fri, 23 May 2014 00:58:15 +0200 Subject: [PATCH 302/336] added includeWatchonly argument to 'gettransaction' because it affects balance calculation --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f329d517b3..b2387cb062 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -65,6 +65,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1 }, { "listunspent", 2 }, { "getblock", 1 }, + { "gettransaction", 1}, { "getrawtransaction", 1 }, { "createrawtransaction", 0 }, { "createrawtransaction", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index e9a111f523..61bc0b22f4 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1475,12 +1475,13 @@ Value listsinceblock(const Array& params, bool fHelp) Value gettransaction(const Array& params, bool fHelp) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "gettransaction \"txid\"\n" "\nGet detailed information about in-wallet transaction \n" "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" + "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n" "\nResult:\n" "{\n" " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n" @@ -1517,6 +1518,11 @@ Value gettransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 1) + if(params[1].get_bool()) + filter = filter | MINE_WATCH_ONLY; + Object entry; if (!pwalletMain->mapWallet.count(hash)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); @@ -1534,7 +1540,7 @@ Value gettransaction(const Array& params, bool fHelp) WalletTxToJSON(wtx, entry); Array details; - ListTransactions(wtx, "*", 0, false, details); + ListTransactions(wtx, "*", 0, false, details, filter); entry.push_back(Pair("details", details)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); From 0fa2f8899adf8f9f0ead29ba5d708ead6c5d4eaf Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 31 May 2014 16:57:26 +0200 Subject: [PATCH 303/336] added includedWatchonly argument to listreceivedbyaddress/...account --- src/rpcclient.cpp | 3 ++- src/rpcwallet.cpp | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index b2387cb062..5edeecf933 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -37,8 +37,10 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getreceivedbyaccount", 1 }, { "listreceivedbyaddress", 0 }, { "listreceivedbyaddress", 1 }, + { "listreceivedbyaddress", 2 }, { "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 1 }, + { "listreceivedbyaccount", 2 }, { "getbalance", 1 }, { "getbalance", 2 }, { "getblockhash", 0 }, @@ -65,7 +67,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1 }, { "listunspent", 2 }, { "getblock", 1 }, - { "gettransaction", 1}, { "getrawtransaction", 1 }, { "createrawtransaction", 0 }, { "createrawtransaction", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 61bc0b22f4..1cbaadd45c 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -932,10 +932,12 @@ struct tallyitem int64_t nAmount; int nConf; vector txids; + bool fIsWatchonly; tallyitem() { nAmount = 0; nConf = std::numeric_limits::max(); + fIsWatchonly = false; } }; @@ -951,6 +953,11 @@ Value ListReceived(const Array& params, bool fByAccounts) if (params.size() > 1) fIncludeEmpty = params[1].get_bool(); + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + // Tally map mapTally; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) @@ -967,13 +974,19 @@ Value ListReceived(const Array& params, bool fByAccounts) BOOST_FOREACH(const CTxOut& txout, wtx.vout) { CTxDestination address; - if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address)) + if (!ExtractDestination(txout.scriptPubKey, address)) + continue; + + isminefilter mine = IsMine(*pwalletMain, address); + if(!mine & filter) continue; tallyitem& item = mapTally[address]; item.nAmount += txout.nValue; item.nConf = min(item.nConf, nDepth); item.txids.push_back(wtx.GetHash()); + if (mine & MINE_WATCH_ONLY) + item.fIsWatchonly = true; } } @@ -990,10 +1003,12 @@ Value ListReceived(const Array& params, bool fByAccounts) int64_t nAmount = 0; int nConf = std::numeric_limits::max(); + bool fIsWatchonly = false; if (it != mapTally.end()) { nAmount = (*it).second.nAmount; nConf = (*it).second.nConf; + fIsWatchonly = (*it).second.fIsWatchonly; } if (fByAccounts) @@ -1001,10 +1016,13 @@ Value ListReceived(const Array& params, bool fByAccounts) tallyitem& item = mapAccountTally[strAccount]; item.nAmount += nAmount; item.nConf = min(item.nConf, nConf); + item.fIsWatchonly = fIsWatchonly; } else { Object obj; + if(fIsWatchonly) + obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("address", address.ToString())); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); @@ -1029,6 +1047,8 @@ Value ListReceived(const Array& params, bool fByAccounts) int64_t nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; Object obj; + if((*it).second.fIsWatchonly) + obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("account", (*it).first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); @@ -1041,17 +1061,19 @@ Value ListReceived(const Array& params, bool fByAccounts) Value listreceivedbyaddress(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "listreceivedbyaddress ( minconf includeempty )\n" + "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n" "\nList balances by receiving address.\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n" + "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n" "\nResult:\n" "[\n" " {\n" + " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n" " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n" @@ -1063,7 +1085,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("listreceivedbyaddress", "") + HelpExampleCli("listreceivedbyaddress", "6 true") - + HelpExampleRpc("listreceivedbyaddress", "6, true") + + HelpExampleRpc("listreceivedbyaddress", "6, true, true") ); return ListReceived(params, false); @@ -1071,17 +1093,19 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) Value listreceivedbyaccount(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "listreceivedbyaccount ( minconf includeempty )\n" + "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n" "\nList balances by account.\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n" + "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n" "\nResult:\n" "[\n" " {\n" + " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n" " \"account\" : \"accountname\", (string) The account name of the receiving account\n" " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n" @@ -1092,7 +1116,7 @@ Value listreceivedbyaccount(const Array& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("listreceivedbyaccount", "") + HelpExampleCli("listreceivedbyaccount", "6 true") - + HelpExampleRpc("listreceivedbyaccount", "6, true") + + HelpExampleRpc("listreceivedbyaccount", "6, true, true") ); return ListReceived(params, true); From d5087d1ba08142bdf135333a0da08ef0f5fc7ef0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 9 Jun 2014 21:11:59 +0200 Subject: [PATCH 304/336] Use script matching rather than destination matching for watch-only. This changes the keystore data format, wallet format and IsMine logic to detect watch-only outputs based on direct script matching rather than first trying to convert outputs to destinations (addresses). The reason is that we don't know how the software that has the spending keys works. It may support the same types of scripts as us, but that is not guaranteed. Furthermore, it removes the ambiguity between addresses used as identifiers for output scripts or identifiers for public keys. One practical implication is that adding a normal pay-to-pubkey-hash address via importaddress will not cause payments to the corresponding full public key to be detected as IsMine. If that is wanted, add those scripts directly (importaddress now also accepts any hex-encoded script). Conflicts: src/wallet.cpp --- src/keystore.cpp | 4 ++-- src/keystore.h | 10 +++++----- src/rpcdump.cpp | 23 +++++++++++++++-------- src/script.cpp | 22 +++++++--------------- src/script.h | 2 +- src/wallet.cpp | 15 ++++++++------- src/wallet.h | 4 ++-- src/walletdb.cpp | 12 ++++++------ src/walletdb.h | 2 +- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/keystore.cpp b/src/keystore.cpp index c2ea1ce5a9..2a4c88d565 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -59,14 +59,14 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) return false; } -bool CBasicKeyStore::AddWatchOnly(const CTxDestination &dest) +bool CBasicKeyStore::AddWatchOnly(const CScript &dest) { LOCK(cs_KeyStore); setWatchOnly.insert(dest); return true; } -bool CBasicKeyStore::HaveWatchOnly(const CTxDestination &dest) const +bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const { LOCK(cs_KeyStore); return setWatchOnly.count(dest) > 0; diff --git a/src/keystore.h b/src/keystore.h index 90fc3a4c7b..72411a1387 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -48,13 +48,13 @@ public: virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; // Support for Watch-only addresses - virtual bool AddWatchOnly(const CTxDestination &dest) =0; - virtual bool HaveWatchOnly(const CTxDestination &dest) const =0; + virtual bool AddWatchOnly(const CScript &dest) =0; + virtual bool HaveWatchOnly(const CScript &dest) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; -typedef std::set WatchOnlySet; +typedef std::set WatchOnlySet; /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore @@ -105,8 +105,8 @@ public: virtual bool HaveCScript(const CScriptID &hash) const; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; - virtual bool AddWatchOnly(const CTxDestination &dest); - virtual bool HaveWatchOnly(const CTxDestination &dest) const; + virtual bool AddWatchOnly(const CScript &dest); + virtual bool HaveWatchOnly(const CScript &dest) const; }; typedef std::vector > CKeyingMaterial; diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 98af4695d6..e505d84b40 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -138,13 +138,19 @@ Value importaddress(const Array& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 3) throw runtime_error( "importaddress
[label] [rescan=true]\n" - "Adds an address that can be watched as if it were in your wallet but cannot be used to spend."); + "Adds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend."); + + CScript script; CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - CTxDestination dest; - dest = address.Get(); + if (address.IsValid()) { + script.SetDestination(address.Get()); + } else if (IsHex(params[0].get_str())) { + std::vector data(ParseHex(params[0].get_str())); + script = CScript(data.begin(), data.end()); + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); + } string strLabel = ""; if (params.size() > 1) @@ -159,15 +165,16 @@ Value importaddress(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // add to address book or update label - pwalletMain->SetAddressBook(dest, strLabel, "receive"); + if (address.IsValid()) + pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); // Don't throw error in case an address is already there - if (pwalletMain->HaveWatchOnly(dest)) + if (pwalletMain->HaveWatchOnly(script)) return Value::null; pwalletMain->MarkDirty(); - if (!pwalletMain->AddWatchOnly(dest)) + if (!pwalletMain->AddWatchOnly(script)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); if (fRescan) diff --git a/src/script.cpp b/src/script.cpp index 0ef0126255..89f752bd1f 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1456,13 +1456,11 @@ public: bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } }; -isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest) +isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) { - if (boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest)) - return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(dest)) - return MINE_WATCH_ONLY; - return MINE_NO; + CScript script; + script.SetDestination(dest); + return IsMine(keystore, script); } isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) @@ -1470,7 +1468,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) vector vSolutions; txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { - if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + if (keystore.HaveWatchOnly(scriptPubKey)) return MINE_WATCH_ONLY; return MINE_NO; } @@ -1485,15 +1483,11 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) keyID = CPubKey(vSolutions[0]).GetID(); if (keystore.HaveKey(keyID)) return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(keyID)) - return MINE_WATCH_ONLY; break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (keystore.HaveKey(keyID)) return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(keyID)) - return MINE_WATCH_ONLY; break; case TX_SCRIPTHASH: { @@ -1501,11 +1495,9 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript); - if (ret) + if (ret == MINE_SPENDABLE) return ret; } - if (keystore.HaveWatchOnly(scriptID)) - return MINE_WATCH_ONLY; break; } case TX_MULTISIG: @@ -1522,7 +1514,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) } } - if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + if (keystore.HaveWatchOnly(scriptPubKey)) return MINE_WATCH_ONLY; return MINE_NO; } diff --git a/src/script.h b/src/script.h index 56c7d01d4e..edba5757e4 100644 --- a/src/script.h +++ b/src/script.h @@ -812,7 +812,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutions); bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -isminetype IsMine(const CKeyStore& keystore, const CTxDestination &dest); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); diff --git a/src/wallet.cpp b/src/wallet.cpp index 4b480321ac..445d98b906 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -145,7 +145,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) return CCryptoKeyStore::AddCScript(redeemScript); } -bool CWallet::AddWatchOnly(const CTxDestination &dest) +bool CWallet::AddWatchOnly(const CScript &dest) { if (!CCryptoKeyStore::AddWatchOnly(dest)) return false; @@ -155,9 +155,8 @@ bool CWallet::AddWatchOnly(const CTxDestination &dest) return CWalletDB(strWalletFile).WriteWatchOnly(dest); } -bool CWallet::LoadWatchOnly(const CTxDestination &dest) +bool CWallet::LoadWatchOnly(const CScript &dest) { - LogPrintf("Loaded %s!\n", CBitcoinAddress(dest).ToString().c_str()); return CCryptoKeyStore::AddWatchOnly(dest); } @@ -729,17 +728,19 @@ int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const bool CWallet::IsChange(const CTxOut& txout) const { - CTxDestination address; - // TODO: fix handling of 'change' outputs. The assumption is that any - // payment to a TX_PUBKEYHASH that is mine but isn't in the address book + // payment to a script that is ours, but is not in the address book // is change. That assumption is likely to break when we implement multisignature // wallets that return change back into a multi-signature-protected address; // a better way of identifying which outputs are 'the send' and which are // 'the change' will need to be implemented (maybe extend CWalletTx to remember // which output, if any, was change). - if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address) == MINE_SPENDABLE) + if (::IsMine(*this, txout.scriptPubKey)) { + CTxDestination address; + if (!ExtractDestination(txout.scriptPubKey, address)) + return true; + LOCK(cs_wallet); if (!mapAddressBook.count(address)) return true; diff --git a/src/wallet.h b/src/wallet.h index 3453d23d97..b44b73568b 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -227,9 +227,9 @@ public: bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; // Adds a watch-only address to the store, and saves it to disk. - bool AddWatchOnly(const CTxDestination &dest); + bool AddWatchOnly(const CScript &dest); // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) - bool LoadWatchOnly(const CTxDestination &dest); + bool LoadWatchOnly(const CScript &dest); bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 9338d57097..a95baf83d0 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,10 +112,10 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } -bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +bool CWalletDB::WriteWatchOnly(const CScript &dest) { nWalletDBUpdated++; - return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); + return Write(std::make_pair(std::string("watchs"), dest), '1'); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) @@ -410,14 +410,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } - else if (strType == "watch") + else if (strType == "watchs") { - std::string strAddress; - ssKey >> strAddress; + CScript script; + ssKey >> script; char fYes; ssValue >> fYes; if (fYes == '1') - pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + pwallet->LoadWatchOnly(script); // Watch-only addresses have no birthday information for now, // so set the wallet birthday to the beginning of time. diff --git a/src/walletdb.h b/src/walletdb.h index 3a6cb152a1..58b4571b16 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -94,7 +94,7 @@ public: bool WriteCScript(const uint160& hash, const CScript& redeemScript); - bool WriteWatchOnly(const CTxDestination &dest); + bool WriteWatchOnly(const CScript &script); bool WriteBestBlock(const CBlockLocator& locator); bool ReadBestBlock(CBlockLocator& locator); From 80dda36a07d09f99be861fa5271d0da5bd4f07dc Mon Sep 17 00:00:00 2001 From: JaSK Date: Thu, 19 Jun 2014 15:24:17 +0200 Subject: [PATCH 305/336] removed default argument values for ismine filter --- src/qt/transactiondesc.cpp | 14 +++++++------- src/qt/transactionrecord.cpp | 2 +- src/rpcwallet.cpp | 18 +++++++++--------- src/wallet.cpp | 4 ++-- src/wallet.h | 25 +++++++++++++------------ 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index d94f066ed9..95c7fa7582 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -54,8 +54,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(); - int64_t nDebit = wtx.GetDebit(); + int64_t nCredit = wtx.GetCredit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -139,7 +139,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout); + nUnmatured += wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -228,10 +228,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; } } @@ -281,10 +281,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1011363f3e..49916fed55 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(); + int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1cbaadd45c..f745d25ab6 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -557,7 +557,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) { int64_t nBalance = 0; @@ -582,7 +582,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) { CWalletDB walletdb(pwalletMain->strWalletFile); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); @@ -786,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -863,7 +863,7 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -1129,7 +1129,7 @@ static void MaybePushAddress(Object & entry, const CTxDestination &dest) entry.push_back(Pair("address", addr.ToString())); } -void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter=MINE_SPENDABLE) +void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter) { int64_t nFee; string strSentAccount; @@ -1552,13 +1552,13 @@ Value gettransaction(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - int64_t nCredit = wtx.GetCredit(); - int64_t nDebit = wtx.GetDebit(); + int64_t nCredit = wtx.GetCredit(filter); + int64_t nDebit = wtx.GetDebit(filter); int64_t nNet = nCredit - nDebit; - int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); + int64_t nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); - if (wtx.IsFromMe()) + if (wtx.IsFromMe(filter)) entry.push_back(Pair("fee", ValueFromAmount(nFee))); WalletTxToJSON(wtx, entry); diff --git a/src/wallet.cpp b/src/wallet.cpp index 445d98b906..e996fca3d2 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index b44b73568b..ac90de3c9c 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -288,12 +288,12 @@ public: std::set GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter=(MINE_WATCH_ONLY|MINE_SPENDABLE)) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); @@ -313,9 +313,9 @@ public: return true; return false; } - bool IsFromMe(const CTransaction& tx) const + bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx) > 0); + return (GetDebit(tx, MINE_SPENDABLE|MINE_WATCH_ONLY) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -324,7 +324,7 @@ public: return true; return false; } - int64_t GetDebit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const { int64_t nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) @@ -335,7 +335,7 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const { int64_t nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) @@ -614,7 +614,8 @@ public: MarkDirty(); } - int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + // filter decides which addresses will count towards the debit + int64_t GetDebit(const isminefilter& filter) const { if (vin.empty()) return 0; @@ -654,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this); + nCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE|MINE_WATCH_ONLY); fCreditCached = true; return nCreditCached; } @@ -756,12 +757,12 @@ public: } void GetAmounts(std::list >& listReceived, - std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + int64_t& nSent, int64_t& nFee, const isminefilter& filter) const; - bool IsFromMe(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + bool IsFromMe(const isminefilter& filter) const { return (GetDebit(filter) > 0); } @@ -776,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe()) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: From 23b0506c91020f69092389cf8b25576dcdf4e17e Mon Sep 17 00:00:00 2001 From: JaSK Date: Thu, 19 Jun 2014 01:42:39 +0200 Subject: [PATCH 306/336] Fixed some stuff in TransactionDesc --- src/qt/transactiondesc.cpp | 32 +++++++++++++------------------- src/qt/transactionrecord.cpp | 6 +++--- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 95c7fa7582..faa2077ff7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -15,6 +15,7 @@ #include "timedata.h" #include "ui_interface.h" #include "wallet.h" +#include "script.h" #include #include @@ -89,27 +90,20 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (nNet > 0) { // Credit - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (CBitcoinAddress(rec->address).IsValid()) { - if (wallet->IsMine(txout)) + CTxDestination address = CBitcoinAddress(rec->address).Get(); + if (wallet->mapAddressBook.count(address)) { - if (CBitcoinAddress(rec->address).IsValid()) - { - CTxDestination address = CBitcoinAddress(rec->address).Get(); - if (wallet->mapAddressBook.count(address)) - { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(rec->address); - QString addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? tr("own address") : tr("watch-only"); - if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; - else - strHTML += " (" + addressOwned + ")"; - strHTML += "
"; - } - } - break; + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(rec->address); + QString addressOwned = (::IsMine(*wallet, address) == MINE_SPENDABLE) ? tr("own address") : tr("watch-only"); + if (!wallet->mapAddressBook[address].name.empty()) + strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + else + strHTML += " (" + addressOwned + ")"; + strHTML += "
"; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 49916fed55..cce2fa3f81 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -52,6 +52,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; + sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address @@ -70,7 +71,6 @@ QList TransactionRecord::decomposeTransaction(const CWallet * sub.type = TransactionRecord::Generated; } - sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; parts.append(sub); } } @@ -101,7 +101,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); - parts.last().involvesWatchAddress = involvesWatchAddress; + parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) { @@ -115,6 +115,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * const CTxOut& txout = wtx.vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = parts.size(); + sub.involvesWatchAddress = involvesWatchAddress; if(wallet->IsMine(txout)) { @@ -146,7 +147,6 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } sub.debit = -nValue; - sub.involvesWatchAddress = involvesWatchAddress; parts.append(sub); } } From 519dd1c89afa2b7d0f2720eb70cd11de23d61006 Mon Sep 17 00:00:00 2001 From: JaSK Date: Fri, 20 Jun 2014 05:02:14 +0200 Subject: [PATCH 307/336] Added MINE_ALL = (spendable|watchonly) --- src/qt/transactiondesc.cpp | 14 +++++++------- src/qt/transactionrecord.cpp | 2 +- src/script.h | 1 + src/wallet.cpp | 4 ++-- src/wallet.h | 6 +++--- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index faa2077ff7..7cfa5424f7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -55,8 +55,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(MINE_SPENDABLE|MINE_WATCH_ONLY); - int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nCredit = wtx.GetCredit(MINE_ALL); + int64_t nDebit = wtx.GetDebit(MINE_ALL); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -133,7 +133,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY); + nUnmatured += wallet->GetCredit(txout, MINE_ALL); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -222,10 +222,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; } } @@ -275,10 +275,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index cce2fa3f81..08092a5f1f 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nDebit = wtx.GetDebit(MINE_ALL); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; diff --git a/src/script.h b/src/script.h index edba5757e4..790822625a 100644 --- a/src/script.h +++ b/src/script.h @@ -200,6 +200,7 @@ enum isminetype MINE_NO = 0, MINE_WATCH_ONLY = 1, MINE_SPENDABLE = 2, + MINE_ALL = MINE_WATCH_ONLY | MINE_SPENDABLE }; /** used for bitflags of isminetype */ typedef uint8_t isminefilter; diff --git a/src/wallet.cpp b/src/wallet.cpp index e996fca3d2..2823e7fa34 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(MINE_ALL) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(MINE_ALL) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index ac90de3c9c..639f51e3ca 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -315,7 +315,7 @@ public: } bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx, MINE_SPENDABLE|MINE_WATCH_ONLY) > 0); + return (GetDebit(tx, MINE_ALL) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -655,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE|MINE_WATCH_ONLY); + nCreditCached = pwallet->GetCredit(*this, MINE_ALL); fCreditCached = true; return nCreditCached; } @@ -777,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY)) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(MINE_ALL)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: From f28707a845d4098fed55a6948887d60043fcfde7 Mon Sep 17 00:00:00 2001 From: JaSK Date: Sun, 22 Jun 2014 23:29:33 +0200 Subject: [PATCH 308/336] fixed bug in ListReceived() --- src/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index f745d25ab6..560be0570a 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -978,7 +978,7 @@ Value ListReceived(const Array& params, bool fByAccounts) continue; isminefilter mine = IsMine(*pwalletMain, address); - if(!mine & filter) + if(!(mine & filter)) continue; tallyitem& item = mapTally[address]; From 53a2148f0c182b83da255972acb3110a74e9957a Mon Sep 17 00:00:00 2001 From: JaSK Date: Mon, 23 Jun 2014 10:43:30 +0200 Subject: [PATCH 309/336] fixed bug where validateaddress doesn't display information --- src/rpcmisc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index f0b4619b26..56accc1b3a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -115,7 +115,7 @@ public: Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - if (mine == MINE_SPENDABLE) { + if (mine != MINE_NO) { CScript subscript; pwalletMain->GetCScript(scriptID, subscript); std::vector addresses; From a3e192a3274817517671f624d5744297905e20d2 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 1 Jul 2014 11:00:22 +0200 Subject: [PATCH 310/336] replaced MINE_ with ISMINE_ --- src/qt/transactiondesc.cpp | 32 ++++++++++++++++---------------- src/qt/transactionrecord.cpp | 12 ++++++------ src/rpcmisc.cpp | 12 ++++++------ src/rpcwallet.cpp | 36 ++++++++++++++++++------------------ src/script.cpp | 16 ++++++++-------- src/script.h | 8 ++++---- src/wallet.cpp | 10 +++++----- src/wallet.h | 24 ++++++++++++------------ 8 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 7cfa5424f7..36e4d50e30 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -55,8 +55,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(MINE_ALL); - int64_t nDebit = wtx.GetDebit(MINE_ALL); + int64_t nCredit = wtx.GetCredit(ISMINE_ALL); + int64_t nDebit = wtx.GetDebit(ISMINE_ALL); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -98,7 +98,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; strHTML += "" + tr("To") + ": "; strHTML += GUIUtil::HtmlEscape(rec->address); - QString addressOwned = (::IsMine(*wallet, address) == MINE_SPENDABLE) ? tr("own address") : tr("watch-only"); + QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only"); if (!wallet->mapAddressBook[address].name.empty()) strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; else @@ -133,7 +133,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout, MINE_ALL); + nUnmatured += wallet->GetCredit(txout, ISMINE_ALL); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -150,14 +150,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco } else { - isminetype fAllFromMe = MINE_SPENDABLE; + isminetype fAllFromMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); if(fAllFromMe > mine) fAllFromMe = mine; } - isminetype fAllToMe = MINE_SPENDABLE; + isminetype fAllToMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); @@ -166,7 +166,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (fAllFromMe) { - if(fAllFromMe == MINE_WATCH_ONLY) + if(fAllFromMe == ISMINE_WATCH_ONLY) strHTML += "" + tr("From") + ": " + tr("watch-only") + "
"; // @@ -176,7 +176,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco { // Ignore change isminetype toSelf = wallet->IsMine(txout); - if ((toSelf == MINE_SPENDABLE) && (fAllFromMe == MINE_SPENDABLE)) + if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE)) continue; if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) @@ -189,9 +189,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); - if(toSelf == MINE_SPENDABLE) + if(toSelf == ISMINE_SPENDABLE) strHTML += " (own address)"; - else if(toSelf == MINE_WATCH_ONLY) + else if(toSelf == ISMINE_WATCH_ONLY) strHTML += " (watch-only)"; strHTML += "
"; } @@ -222,10 +222,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; } } @@ -275,10 +275,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); @@ -305,8 +305,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); } strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue); - strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & MINE_SPENDABLE ? tr("true") : tr("false")) + ""; - strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & MINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 08092a5f1f..7d29c212b3 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(MINE_ALL); + int64_t nDebit = wtx.GetDebit(ISMINE_ALL); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; @@ -52,7 +52,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; - sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; + sub.involvesWatchAddress = mine == ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address @@ -78,19 +78,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * else { bool involvesWatchAddress = false; - isminetype fAllFromMe = MINE_SPENDABLE; + isminetype fAllFromMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); - if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; + if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } - isminetype fAllToMe = MINE_SPENDABLE; + isminetype fAllToMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); - if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; + if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 56accc1b3a..f51be2db2c 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -104,7 +104,7 @@ public: Object obj; CPubKey vchPubKey; obj.push_back(Pair("isscript", false)); - if (mine == MINE_SPENDABLE) { + if (mine == ISMINE_SPENDABLE) { pwalletMain->GetPubKey(keyID, vchPubKey); obj.push_back(Pair("pubkey", HexStr(vchPubKey))); obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); @@ -115,7 +115,7 @@ public: Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - if (mine != MINE_NO) { + if (mine != ISMINE_NO) { CScript subscript; pwalletMain->GetCScript(scriptID, subscript); std::vector addresses; @@ -170,10 +170,10 @@ Value validateaddress(const Array& params, bool fHelp) string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET - isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", (mine & MINE_SPENDABLE) ? true : false)); - if (mine != MINE_NO) { - ret.push_back(Pair("iswatchonly", (mine & MINE_WATCH_ONLY) ? true: false)); + isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; + ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); + if (mine != ISMINE_NO) { + ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 560be0570a..190c6b86b5 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -623,10 +623,10 @@ Value getbalance(const Array& params, bool fHelp) int nMinDepth = 1; if (params.size() > 1) nMinDepth = params[1].get_int(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -786,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -863,7 +863,7 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -953,10 +953,10 @@ Value ListReceived(const Array& params, bool fByAccounts) if (params.size() > 1) fIncludeEmpty = params[1].get_bool(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; // Tally map mapTally; @@ -985,7 +985,7 @@ Value ListReceived(const Array& params, bool fByAccounts) item.nAmount += txout.nValue; item.nConf = min(item.nConf, nDepth); item.txids.push_back(wtx.GetHash()); - if (mine & MINE_WATCH_ONLY) + if (mine & ISMINE_WATCH_ONLY) item.fIsWatchonly = true; } } @@ -1139,7 +1139,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter); bool fAllAccounts = (strAccount == string("*")); - bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); + bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY); // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) @@ -1147,7 +1147,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) { Object entry; - if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & MINE_WATCH_ONLY)) + if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", strSentAccount)); MaybePushAddress(entry, s.first); @@ -1171,7 +1171,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if (fAllAccounts || (account == strAccount)) { Object entry; - if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & MINE_WATCH_ONLY)) + if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.first); @@ -1285,10 +1285,10 @@ Value listtransactions(const Array& params, bool fHelp) int nFrom = 0; if (params.size() > 2) nFrom = params[2].get_int(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 3) if(params[3].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); @@ -1359,10 +1359,10 @@ Value listaccounts(const Array& params, bool fHelp) int nMinDepth = 1; if (params.size() > 0) nMinDepth = params[0].get_int(); - isminefilter includeWatchonly = MINE_SPENDABLE; + isminefilter includeWatchonly = ISMINE_SPENDABLE; if(params.size() > 1) if(params[1].get_bool()) - includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; + includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { @@ -1451,7 +1451,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if (params.size() > 0) { @@ -1473,7 +1473,7 @@ Value listsinceblock(const Array& params, bool fHelp) if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; @@ -1542,10 +1542,10 @@ Value gettransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 1) if(params[1].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; Object entry; if (!pwalletMain->mapWallet.count(hash)) diff --git a/src/script.cpp b/src/script.cpp index 89f752bd1f..238a25e72d 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1469,8 +1469,8 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { if (keystore.HaveWatchOnly(scriptPubKey)) - return MINE_WATCH_ONLY; - return MINE_NO; + return ISMINE_WATCH_ONLY; + return ISMINE_NO; } CKeyID keyID; @@ -1482,12 +1482,12 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); if (keystore.HaveKey(keyID)) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (keystore.HaveKey(keyID)) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; case TX_SCRIPTHASH: { @@ -1495,7 +1495,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript); - if (ret == MINE_SPENDABLE) + if (ret == ISMINE_SPENDABLE) return ret; } break; @@ -1509,14 +1509,14 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // in shared-wallet situations. vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); if (HaveKeys(keys, keystore) == keys.size()) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; } } if (keystore.HaveWatchOnly(scriptPubKey)) - return MINE_WATCH_ONLY; - return MINE_NO; + return ISMINE_WATCH_ONLY; + return ISMINE_NO; } bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) diff --git a/src/script.h b/src/script.h index 790822625a..e36be2db9e 100644 --- a/src/script.h +++ b/src/script.h @@ -197,10 +197,10 @@ enum /** IsMine() return codes */ enum isminetype { - MINE_NO = 0, - MINE_WATCH_ONLY = 1, - MINE_SPENDABLE = 2, - MINE_ALL = MINE_WATCH_ONLY | MINE_SPENDABLE + ISMINE_NO = 0, + ISMINE_WATCH_ONLY = 1, + ISMINE_SPENDABLE = 2, + ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE }; /** used for bitflags of isminetype */ typedef uint8_t isminefilter; diff --git a/src/wallet.cpp b/src/wallet.cpp index 2823e7fa34..84b50c0f8c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -707,7 +707,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return IsMine(prev.vout[txin.prevout.n]); } } - return MINE_NO; + return ISMINE_NO; } int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const @@ -1139,10 +1139,10 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const for (unsigned int i = 0; i < pcoin->vout.size(); i++) { isminetype mine = IsMine(pcoin->vout[i]); - if (!(IsSpent(wtxid, i)) && mine != MINE_NO && + if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth, mine & MINE_SPENDABLE)); + vCoins.push_back(COutput(pcoin, i, nDepth, mine & ISMINE_SPENDABLE)); } } } @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe(MINE_ALL) ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe(MINE_ALL) ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index 639f51e3ca..8a51bf9821 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -315,7 +315,7 @@ public: } bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx, MINE_ALL) > 0); + return (GetDebit(tx, ISMINE_ALL) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -621,24 +621,24 @@ public: return 0; int64_t debit = 0; - if(filter & MINE_SPENDABLE) + if(filter & ISMINE_SPENDABLE) { if (fDebitCached) debit += nDebitCached; else { - nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE); + nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE); fDebitCached = true; debit += nDebitCached; } } - if(filter & MINE_WATCH_ONLY) + if(filter & ISMINE_WATCH_ONLY) { if(fWatchDebitCached) debit += nWatchDebitCached; else { - nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY); + nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY); fWatchDebitCached = true; debit += nWatchDebitCached; } @@ -655,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this, MINE_ALL); + nCreditCached = pwallet->GetCredit(*this, ISMINE_ALL); fCreditCached = true; return nCreditCached; } @@ -666,7 +666,7 @@ public: { if (fUseCache && fImmatureCreditCached) return nImmatureCreditCached; - nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE); + nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE); fImmatureCreditCached = true; return nImmatureCreditCached; } @@ -693,7 +693,7 @@ public: if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE); + nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -710,7 +710,7 @@ public: { if (fUseCache && fImmatureWatchCreditCached) return nImmatureWatchCreditCached; - nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY); + nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY); fImmatureWatchCreditCached = true; return nImmatureWatchCreditCached; } @@ -736,7 +736,7 @@ public: if (!pwallet->IsSpent(GetHash(), i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY); + nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -777,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe(MINE_ALL)) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: @@ -788,7 +788,7 @@ public: if (parent == NULL) return false; const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (pwallet->IsMine(parentOut) != MINE_SPENDABLE) + if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false; } return true; From 0da6b3fd187da3aa810aaa584d8bd197ad4fa2b9 Mon Sep 17 00:00:00 2001 From: Tom Harding Date: Wed, 2 Jul 2014 09:27:29 -0700 Subject: [PATCH 311/336] Remove signal DoubleSpendDetected, use function Also removes the need for forward reference to RelayableRespend. --- src/init.cpp | 2 +- src/main.cpp | 103 +++++++++++++++++++++++---------------------------- src/main.h | 4 +- 3 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index da13218a94..6c0898c036 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1176,7 +1176,7 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); #endif - RegisterInternalSignals(); + InitRespendFilter(); StartNode(threadGroup); if (fServer) StartRPCThreads(); diff --git a/src/main.cpp b/src/main.cpp index 1294e5b2ed..7baf33c39f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -125,9 +125,14 @@ namespace { } // anon namespace -// Forward reference functions defined here: +// Bloom filter to limit respend relays to one static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000; -static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter); +static CBloomFilter doubleSpendFilter; +void InitRespendFilter() { + seed_insecure_rand(); + doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE); +} + ////////////////////////////////////////////////////////////////////////////// // @@ -151,24 +156,10 @@ struct CMainSignals { boost::signals2::signal Inventory; // Tells listeners to broadcast their data. boost::signals2::signal Broadcast; - // Notifies listeners of detection of a double-spent transaction. Arguments are outpoint that is - // double-spent, first transaction seen, double-spend transaction, and whether the second double-spend - // transaction was first seen in a block. - // Note: only notifies if the previous transaction is in the memory pool; if previous transction was in a block, - // then the double-spend simply fails when we try to lookup the inputs in the current UTXO set. - boost::signals2::signal DetectedDoubleSpend; } g_signals; } // anon namespace -void RegisterInternalSignals() { - static CBloomFilter doubleSpendFilter; - seed_insecure_rand(); - doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE); - - g_signals.DetectedDoubleSpend.connect(boost::bind(RelayableRespend, _1, _2, _3, doubleSpendFilter)); -} - void RegisterWallet(CWalletInterface* pwalletIn) { g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2)); @@ -908,6 +899,45 @@ bool RateLimitExceeded(double& dCount, int64_t& nLastTime, int64_t nLimit, unsig return false; } +static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) +{ + // Relaying double-spend attempts to our peers lets them detect when + // somebody might be trying to cheat them. However, blindly relaying + // every double-spend across the entire network gives attackers + // a denial-of-service attack: just generate a stream of double-spends + // re-spending the same (limited) set of outpoints owned by the attacker. + // So, we use a bloom filter and only relay (at most) the first double + // spend for each outpoint. False-positives ("we have already relayed") + // are OK, because if the peer doesn't hear about the double-spend + // from us they are very likely to hear about it from another peer, since + // each peer uses a different, randomized bloom filter. + + if (fInBlock || filter.contains(outPoint)) return false; + + // Apply an independent rate limit to double-spend relays + static double dRespendCount; + static int64_t nLastRespendTime; + static int64_t nRespendLimit = GetArg("-limitrespendrelay", 100); + unsigned int nSize = ::GetSerializeSize(doubleSpend, SER_NETWORK, PROTOCOL_VERSION); + + if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize)) + { + LogPrint("mempool", "Double-spend relay rejected by rate limiter\n"); + return false; + } + + LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize); + + // Clear the filter on average every MAX_DOUBLE_SPEND_BLOOM + // insertions + if (insecure_rand()%MAX_DOUBLESPEND_BLOOM == 0) + filter.clear(); + + filter.insert(outPoint); + + return true; +} + bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee) { @@ -945,7 +975,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Does tx conflict with a member of the pool, and is it not equivalent to that member? if (pool.mapNextTx.count(outpoint) && !tx.IsEquivalentTo(*pool.mapNextTx[outpoint].ptx)) { - relayableRespend = g_signals.DetectedDoubleSpend(outpoint, tx, false); + relayableRespend = RelayableRespend(outpoint, tx, false, doubleSpendFilter); if (!relayableRespend) return false; } @@ -1057,45 +1087,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return !relayableRespend; } -static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter) -{ - // Relaying double-spend attempts to our peers lets them detect when - // somebody might be trying to cheat them. However, blindly relaying - // every double-spend across the entire network gives attackers - // a denial-of-service attack: just generate a stream of double-spends - // re-spending the same (limited) set of outpoints owned by the attacker. - // So, we use a bloom filter and only relay (at most) the first double - // spend for each outpoint. False-positives ("we have already relayed") - // are OK, because if the peer doesn't hear about the double-spend - // from us they are very likely to hear about it from another peer, since - // each peer uses a different, randomized bloom filter. - - if (fInBlock || filter.contains(outPoint)) return false; - - // Apply an independent rate limit to double-spend relays - static double dRespendCount; - static int64_t nLastRespendTime; - static int64_t nRespendLimit = GetArg("-limitrespendrelay", 100); - unsigned int nSize = ::GetSerializeSize(doubleSpend, SER_NETWORK, PROTOCOL_VERSION); - - if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize)) - { - LogPrint("mempool", "Double-spend relay rejected by rate limiter\n"); - return false; - } - - LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize); - - // Clear the filter on average every MAX_DOUBLE_SPEND_BLOOM - // insertions - if (insecure_rand()%MAX_DOUBLESPEND_BLOOM == 0) - filter.clear(); - - filter.insert(outPoint); - - return true; -} - int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { diff --git a/src/main.h b/src/main.h index 19f4469008..26450bb721 100644 --- a/src/main.h +++ b/src/main.h @@ -108,8 +108,8 @@ struct CNodeStateStats; struct CBlockTemplate; -/** Set up internal signal handlers **/ -void RegisterInternalSignals(); +/** Initialize respend bloom filter **/ +void InitRespendFilter(); /** Register a wallet to receive updates from core */ void RegisterWallet(CWalletInterface* pwalletIn); From 834e46e847188df513b8b57ab30fe9940f2b2dd0 Mon Sep 17 00:00:00 2001 From: jtimon Date: Wed, 2 Jul 2014 18:36:43 +0200 Subject: [PATCH 312/336] CBlockIndex()::SetNull() method to avoid code repetition --- src/main.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/main.h b/src/main.h index 19f4469008..cc7dea75a1 100644 --- a/src/main.h +++ b/src/main.h @@ -718,7 +718,7 @@ public: // (memory only) Sequencial id assigned to distinguish order in which blocks are received. uint32_t nSequenceId; - CBlockIndex() + void SetNull() { phashBlock = NULL; pprev = NULL; @@ -740,20 +740,14 @@ public: nNonce = 0; } + CBlockIndex() + { + SetNull(); + } + CBlockIndex(CBlockHeader& block) { - phashBlock = NULL; - pprev = NULL; - pskip = NULL; - nHeight = 0; - nFile = 0; - nDataPos = 0; - nUndoPos = 0; - nChainWork = 0; - nTx = 0; - nChainTx = 0; - nStatus = 0; - nSequenceId = 0; + SetNull(); nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; From 4278b1df45d93d18dfa0a8ce8d6fd7ac9b5344a6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 3 Jul 2014 06:26:03 +0200 Subject: [PATCH 313/336] Clarify error message when invalid -rpcallowip Also add to HelpMessage() what specifications are valid. --- src/init.cpp | 2 +- src/rpcserver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index da13218a94..2dd141a735 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -323,7 +323,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 8332 or testnet: 18332)") + "\n"; - strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address. This option can be specified multiple times") + "\n"; + strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times") + "\n"; strUsage += " -rpcthreads= " + _("Set the number of threads to service RPC calls (default: 4)") + "\n"; strUsage += "\n" + _("RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n"; diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f47b3385da..5c4d307497 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -512,7 +512,7 @@ void StartRPCThreads() if(!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( - strprintf("Invalid -rpcallowip subnet specification: %s", strAllow), + strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow), "", CClientUIInterface::MSG_ERROR); StartShutdown(); return; From b33d1f5ee512da5719b793b3867f75f1eea5cf52 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Tue, 27 May 2014 15:44:57 -0400 Subject: [PATCH 314/336] Use fee/priority estimates in wallet CreateTransaction The wallet now uses the mempool fee estimator with a new command-line option: -txconfirmtarget (default: 1) instead of using hard-coded fees or priorities. A new bitcoind that hasn't seen enough transactions to estimate will fall back to the old hard-coded minimum priority or transaction fee. -paytxfee option overrides -txconfirmtarget. Relaying and mining code isn't changed. For Qt, the coin control dialog now uses priority estimates to label transaction priority (instead of hard-coded constants); unspent outputs were consistently labeled with a much higher priority than is justified by the free transactions actually being accepted into blocks. I did not implement any GUI for setting -txconfirmtarget; I would suggest getting rid of the "Pay transaction fee" GUI and replace it with either "target number of confirmations" or maybe a "faster confirmation <--> lower fee" slider or select box. --- doc/release-notes.md | 20 +++++++++++++++ src/core.h | 3 ++- src/init.cpp | 7 ++++++ src/main.cpp | 13 +++------- src/main.h | 9 +------ src/qt/coincontroldialog.cpp | 48 +++++++++++++++++++++--------------- src/qt/coincontroldialog.h | 3 ++- src/wallet.cpp | 44 +++++++++++++++++++++++++++------ src/wallet.h | 5 ++++ 9 files changed, 105 insertions(+), 47 deletions(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index 3a4079e437..66059800b6 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,6 +1,26 @@ (note: this is a temporary file, to be added-to by anybody, and moved to release-notes at release time) +Transaction fee changes +======================= + +This release automatically estimates how high a transaction fee (or how +high a priority) transactions require to be confirmed quickly. The default +settings will create transactions that confirm quickly; see the new +'txconfirmtarget' setting to control the tradeoff between fees and +confirmation times. + +Prior releases used hard-coded fees (and priorities), and would +sometimes create transactions that took a very long time to confirm. + + +New Command Line Options +======================== + +-txconfirmtarget=n : create transactions that have enough fees (or priority) +so they are likely to confirm within n blocks (default: 1). This setting +is over-ridden by the -paytxfee option. + New RPC methods =============== diff --git a/src/core.h b/src/core.h index 8606831575..d6e7ab870d 100644 --- a/src/core.h +++ b/src/core.h @@ -131,7 +131,8 @@ public: friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } - + friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; } + friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } std::string ToString() const; IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); ) diff --git a/src/init.cpp b/src/init.cpp index 2dd141a735..3ee0f2aa39 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -254,6 +254,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += "\n" + _("Wallet options:") + "\n"; strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; strUsage += " -paytxfee= " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; + strUsage += " -txconfirmtarget= " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; @@ -635,7 +636,13 @@ bool AppInit2(boost::thread_group& threadGroup) if (nFeePerK > nHighTransactionFeeWarning) InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); payTxFee = CFeeRate(nFeePerK, 1000); + if (payTxFee < CTransaction::minRelayTxFee) + { + return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), + mapArgs["-paytxfee"], CTransaction::minRelayTxFee.ToString())); + } } + nTxConfirmTarget = GetArg("-txconfirmtarget", 1); bSpendZeroConfChange = GetArg("-spendzeroconfchange", true); std::string strWalletFile = GetArg("-wallet", "wallet.dat"); diff --git a/src/main.cpp b/src/main.cpp index 04d9523e26..6be1a29c6c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -858,7 +858,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state) return true; } -int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode) +int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) { { LOCK(mempool.cs); @@ -870,10 +870,7 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, return 0; } - // Base fee is either minTxFee or minRelayTxFee - CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee; - - int64_t nMinFee = baseFeeRate.GetFee(nBytes); + int64_t nMinFee = tx.minRelayTxFee.GetFee(nBytes); if (fAllowFree) { @@ -881,9 +878,7 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, // * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000 // to be considered to fall into this category. We don't want to encourage sending // multiple transactions instead of one big transaction to avoid fees. - // * If we are creating a transaction we allow transactions up to 1,000 bytes - // to be considered safe and assume they can likely make it into this section. - if (nBytes < (mode == GMF_SEND ? 1000 : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000))) + if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)) nMinFee = 0; } @@ -1005,7 +1000,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa unsigned int nSize = entry.GetTxSize(); // Don't accept it if it can't get into a block - int64_t txMinFee = GetMinFee(tx, nSize, true, GMF_RELAY); + int64_t txMinFee = GetMinRelayFee(tx, nSize, true); if (fLimitFree && nFees < txMinFee) return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d", hash.ToString(), nFees, txMinFee), diff --git a/src/main.h b/src/main.h index 19f4469008..e8df17dda0 100644 --- a/src/main.h +++ b/src/main.h @@ -245,14 +245,7 @@ struct CDiskTxPos : public CDiskBlockPos }; - -enum GetMinFee_mode -{ - GMF_RELAY, - GMF_SEND, -}; - -int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode); +int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); // // Check transaction inputs, and make sure any diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index c6a6150392..73494f52ea 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -16,6 +16,8 @@ #include "main.h" #include "wallet.h" +#include // for 'map_list_of()' + #include #include #include @@ -400,23 +402,24 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) } // return human readable label for priority number -QString CoinControlDialog::getPriorityLabel(double dPriority) +QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPriority) { - if (AllowFree(dPriority)) // at least medium + // confirmations -> textual description + typedef std::map PriorityDescription; + static PriorityDescription priorityDescriptions = boost::assign::map_list_of + (1, tr("highest"))(2, tr("higher"))(3, tr("high")) + (5, tr("medium-high"))(6, tr("medium")) + (10, tr("low-medium"))(15, tr("low")) + (20, tr("lower")); + + BOOST_FOREACH(const PriorityDescription::value_type& i, priorityDescriptions) { - if (AllowFree(dPriority / 1000000)) return tr("highest"); - else if (AllowFree(dPriority / 100000)) return tr("higher"); - else if (AllowFree(dPriority / 10000)) return tr("high"); - else if (AllowFree(dPriority / 1000)) return tr("medium-high"); - else return tr("medium"); - } - else - { - if (AllowFree(dPriority * 10)) return tr("low-medium"); - else if (AllowFree(dPriority * 100)) return tr("low"); - else if (AllowFree(dPriority * 1000)) return tr("lower"); - else return tr("lowest"); + double p = mempool.estimatePriority(i.first); + if (p > 0 && dPriority >= p) return i.second; } + // Note: if mempool hasn't accumulated enough history (estimatePriority + // returns -1) we're conservative and classify as "lowest" + return tr("lowest"); } // shows count of locked unspent outputs @@ -518,15 +521,20 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Priority dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) - sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); + sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority); // Fee int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes)); // Min Fee - int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND); + nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); - nPayFee = max(nFee, nMinFee); + double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); + if (dPriorityNeeded <= 0) // Not enough mempool history: never send free + dPriorityNeeded = std::numeric_limits::max(); + + if (nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE && dPriority >= dPriorityNeeded) + nPayFee = 0; if (nPayAmount > 0) { @@ -591,7 +599,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) } // turn labels "red" - l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000 + l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000 l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium" l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes" @@ -732,7 +740,7 @@ void CoinControlDialog::updateView() // priority double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10 - itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority)); + itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPriority)); itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " ")); dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); nInputSum += nInputSize; @@ -765,7 +773,7 @@ void CoinControlDialog::updateView() itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " ")); - itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum)); + itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPrioritySum)); itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " ")); } } diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 465e2a009d..4f7422642f 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -19,6 +19,7 @@ namespace Ui { } class WalletModel; class CCoinControl; +class CTxMemPool; class CoinControlDialog : public QDialog { @@ -32,7 +33,7 @@ public: // static because also called from sendcoinsdialog static void updateLabels(WalletModel*, QDialog*); - static QString getPriorityLabel(double); + static QString getPriorityLabel(const CTxMemPool& pool, double); static QList payAmounts; static CCoinControl *coinControl; diff --git a/src/wallet.cpp b/src/wallet.cpp index daca7ac04b..d9187e4be3 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -18,6 +18,7 @@ using namespace std; // Settings CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); +unsigned int nTxConfirmTarget = 1; bool bSpendZeroConfChange = true; ////////////////////////////////////////////////////////////////////////////// @@ -1273,6 +1274,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, return false; } + wtxNew.fTimeReceivedIsTxTime = true; wtxNew.BindWallet(this); CMutableTransaction txNew; @@ -1393,19 +1395,31 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } dPriority = wtxNew.ComputePriority(dPriority, nBytes); - // Check that enough fee is included - int64_t nPayFee = payTxFee.GetFee(nBytes); - bool fAllowFree = AllowFree(dPriority); - int64_t nMinFee = GetMinFee(wtxNew, nBytes, fAllowFree, GMF_SEND); - if (nFeeRet < max(nPayFee, nMinFee)) + int64_t nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + + if (nFeeRet >= nFeeNeeded) + break; // Done, enough fee included. + + // Too big to send for free? Include more fee and try again: + if (nBytes > MAX_FREE_TRANSACTION_CREATE_SIZE) { - nFeeRet = max(nPayFee, nMinFee); + nFeeRet = nFeeNeeded; continue; } - wtxNew.fTimeReceivedIsTxTime = true; + // Not enough fee: enough priority? + double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); + // Not enough mempool history to estimate: use hard-coded AllowFree. + if (dPriorityNeeded <= 0 && AllowFree(dPriority)) + break; - break; + // Small enough, and priority high enough, to send for free + if (dPriority >= dPriorityNeeded) + break; + + // Include more fee and try again. + nFeeRet = nFeeNeeded; + continue; } } } @@ -1513,6 +1527,20 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV return SendMoney(scriptPubKey, nValue, wtxNew); } +int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) +{ + // payTxFee is user-set "I want to pay this much" + int64_t nFeeNeeded = payTxFee.GetFee(nTxBytes); + // User didn't set: use -txconfirmtarget to estimate... + if (nFeeNeeded == 0) + nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes); + // ... unless we don't have enough mempool data, in which case fall + // back to a hard-coded fee + if (nFeeNeeded == 0) + nFeeNeeded = CTransaction::minTxFee.GetFee(nTxBytes); + return nFeeNeeded; +} + diff --git a/src/wallet.h b/src/wallet.h index 1c2512d678..19a1b18523 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -25,12 +25,15 @@ // Settings extern CFeeRate payTxFee; +extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; // -paytxfee default static const int64_t DEFAULT_TRANSACTION_FEE = 0; // -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB static const int nHighTransactionFeeWarning = 0.01 * COIN; +// Largest (in bytes) free transaction we're willing to create +static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; class CAccountingEntry; class CCoinControl; @@ -265,6 +268,8 @@ public: std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew); std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); + bool NewKeyPool(); bool TopUpKeyPool(unsigned int kpSize = 0); void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool); From 4b7b1bb1ac54e067d889170757a8c45f0baaae3d Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Mon, 23 Jun 2014 10:58:59 -0400 Subject: [PATCH 315/336] Sanity checks for estimates Require at least 11 samples before giving fee/priority estimates. And have wallet-created transactions go throught the fee-sanity-check code path. --- src/main.cpp | 4 ++-- src/main.h | 2 +- src/txmempool.cpp | 9 +++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6be1a29c6c..d1ddf1600d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1129,10 +1129,10 @@ int CMerkleTx::GetBlocksToMaturity() const } -bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree) +bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee) { CValidationState state; - return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL); + return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee); } diff --git a/src/main.h b/src/main.h index e8df17dda0..4c7b7fd8d4 100644 --- a/src/main.h +++ b/src/main.h @@ -452,7 +452,7 @@ public: int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } int GetBlocksToMaturity() const; - bool AcceptToMemoryPool(bool fLimitFree=true); + bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true); }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 97a426dd35..0a8ad96aac 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -251,8 +251,13 @@ public: std::sort(sortedFeeSamples.begin(), sortedFeeSamples.end(), std::greater()); } - if (sortedFeeSamples.size() == 0) + if (sortedFeeSamples.size() < 11) + { + // Eleven is Gavin's Favorite Number + // ... but we also take a maximum of 10 samples per block so eleven means + // we're getting samples from at least two different blocks return CFeeRate(0); + } int nBucketSize = history.at(nBlocksToConfirm).FeeSamples(); @@ -281,7 +286,7 @@ public: std::sort(sortedPrioritySamples.begin(), sortedPrioritySamples.end(), std::greater()); } - if (sortedPrioritySamples.size() == 0) + if (sortedPrioritySamples.size() < 11) return -1.0; int nBucketSize = history.at(nBlocksToConfirm).PrioritySamples(); From 13fc83c77bb9108c00dd7709ce17719edb763273 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Thu, 3 Jul 2014 14:25:32 -0400 Subject: [PATCH 316/336] Move fee policy out of core --- src/core.cpp | 2 +- src/core.h | 6 ++---- src/init.cpp | 30 +++++++++++++++--------------- src/main.cpp | 18 ++++++++---------- src/main.h | 1 + src/miner.cpp | 2 +- src/qt/coincontroldialog.cpp | 14 +++++++------- src/qt/guiutil.cpp | 3 ++- src/qt/optionsdialog.cpp | 9 +++++++-- src/qt/paymentserver.cpp | 2 +- src/rpcmisc.cpp | 2 +- src/rpcnet.cpp | 2 +- src/txmempool.cpp | 26 +++++++++++++------------- src/txmempool.h | 4 +++- src/wallet.cpp | 9 ++++++--- src/wallet.h | 1 + 16 files changed, 70 insertions(+), 61 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index ca28624529..47f3b2a015 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -80,7 +80,7 @@ CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize) nSatoshisPerK = 0; } -int64_t CFeeRate::GetFee(size_t nSize) +int64_t CFeeRate::GetFee(size_t nSize) const { return nSatoshisPerK*nSize / 1000; } diff --git a/src/core.h b/src/core.h index d6e7ab870d..0387336c98 100644 --- a/src/core.h +++ b/src/core.h @@ -125,8 +125,8 @@ public: CFeeRate(int64_t nFeePaid, size_t nSize); CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } - int64_t GetFee(size_t size); // unit returned is satoshis - int64_t GetFeePerK() { return GetFee(1000); } // satoshis-per-1000-bytes + int64_t GetFee(size_t size) const; // unit returned is satoshis + int64_t GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } @@ -217,8 +217,6 @@ private: void UpdateHash() const; public: - static CFeeRate minTxFee; - static CFeeRate minRelayTxFee; static const int CURRENT_VERSION=1; // The local variables are made const to prevent unintended modification diff --git a/src/init.cpp b/src/init.cpp index 3ee0f2aa39..5afae32327 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -253,15 +253,16 @@ std::string HelpMessage(HelpMessageMode mode) #ifdef ENABLE_WALLET strUsage += "\n" + _("Wallet options:") + "\n"; strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n"; + strUsage += " -mintxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n"; strUsage += " -paytxfee= " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; - strUsage += " -txconfirmtarget= " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; + strUsage += " -respendnotify= " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n"; + strUsage += " -txconfirmtarget= " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n"; strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; strUsage += " -wallet= " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n"; strUsage += " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; - strUsage += " -respendnotify= " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n"; strUsage += " -zapwallettxes= " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n"; strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n"; #endif @@ -295,8 +296,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -limitfreerelay= " + _("Continuously rate-limit free transactions to *1000 bytes per minute (default:15)") + "\n"; strUsage += " -maxsigcachesize= " + _("Limit size of signature cache to entries (default: 50000)") + "\n"; } - strUsage += " -mintxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CTransaction::minTxFee.GetFeePerK())) + "\n"; - strUsage += " -minrelaytxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(CTransaction::minRelayTxFee.GetFeePerK())) + "\n"; + strUsage += " -minrelaytxfee= " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n"; strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { @@ -610,24 +610,24 @@ bool AppInit2(boost::thread_group& threadGroup) // a transaction spammer can cheaply fill blocks using // 1-satoshi-fee transactions. It should be set above the real // cost to you of processing a transaction. - if (mapArgs.count("-mintxfee")) - { - int64_t n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CTransaction::minTxFee = CFeeRate(n); - else - return InitError(strprintf(_("Invalid amount for -mintxfee=: '%s'"), mapArgs["-mintxfee"])); - } if (mapArgs.count("-minrelaytxfee")) { int64_t n = 0; if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) - CTransaction::minRelayTxFee = CFeeRate(n); + ::minRelayTxFee = CFeeRate(n); else return InitError(strprintf(_("Invalid amount for -minrelaytxfee=: '%s'"), mapArgs["-minrelaytxfee"])); } #ifdef ENABLE_WALLET + if (mapArgs.count("-mintxfee")) + { + int64_t n = 0; + if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) + CWallet::minTxFee = CFeeRate(n); + else + return InitError(strprintf(_("Invalid amount for -mintxfee=: '%s'"), mapArgs["-mintxfee"])); + } if (mapArgs.count("-paytxfee")) { int64_t nFeePerK = 0; @@ -636,10 +636,10 @@ bool AppInit2(boost::thread_group& threadGroup) if (nFeePerK > nHighTransactionFeeWarning) InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); payTxFee = CFeeRate(nFeePerK, 1000); - if (payTxFee < CTransaction::minRelayTxFee) + if (payTxFee < ::minRelayTxFee) { return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - mapArgs["-paytxfee"], CTransaction::minRelayTxFee.ToString())); + mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); } } nTxConfirmTarget = GetArg("-txconfirmtarget", 1); diff --git a/src/main.cpp b/src/main.cpp index d1ddf1600d..54b926abdb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,8 +38,6 @@ using namespace boost; CCriticalSection cs_main; -CTxMemPool mempool; - map mapBlockIndex; CChain chainActive; int64_t nTimeBestReceived = 0; @@ -50,10 +48,10 @@ bool fBenchmark = false; bool fTxIndex = false; unsigned int nCoinCacheSize = 5000; -/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ -CFeeRate CTransaction::minTxFee = CFeeRate(10000); // Override with -mintxfee /** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */ -CFeeRate CTransaction::minRelayTxFee = CFeeRate(1000); +CFeeRate minRelayTxFee = CFeeRate(1000); + +CTxMemPool mempool(::minRelayTxFee); struct COrphanBlock { uint256 hashBlock; @@ -617,7 +615,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason) } if (whichType == TX_NULL_DATA) nDataOut++; - else if (txout.IsDust(CTransaction::minRelayTxFee)) { + else if (txout.IsDust(::minRelayTxFee)) { reason = "dust"; return false; } @@ -870,7 +868,7 @@ int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF return 0; } - int64_t nMinFee = tx.minRelayTxFee.GetFee(nBytes); + int64_t nMinFee = ::minRelayTxFee.GetFee(nBytes); if (fAllowFree) { @@ -1009,7 +1007,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Continuously rate-limit free (really, very-low-fee)transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize)) + if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize)) { static double dFreeCount; static int64_t nLastFreeTime; @@ -1022,10 +1020,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize); } - if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000) + if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000) return error("AcceptToMemoryPool: : insane fees %s, %d > %d", hash.ToString(), - nFees, CTransaction::minRelayTxFee.GetFee(nSize) * 10000); + nFees, ::minRelayTxFee.GetFee(nSize) * 10000); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. diff --git a/src/main.h b/src/main.h index 4c7b7fd8d4..961f2e78af 100644 --- a/src/main.h +++ b/src/main.h @@ -93,6 +93,7 @@ extern bool fBenchmark; extern int nScriptCheckThreads; extern bool fTxIndex; extern unsigned int nCoinCacheSize; +extern CFeeRate minRelayTxFee; // Minimum disk space required - used in CheckDiskSpace() static const uint64_t nMinDiskSpace = 52428800; diff --git a/src/miner.cpp b/src/miner.cpp index 69e53756e0..17918a1280 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -236,7 +236,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) double dPriorityDelta = 0; int64_t nFeeDelta = 0; mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); - if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; // Prioritise by fee once past the priority size or we run out of high-priority diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 73494f52ea..e0a524a55e 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -406,7 +406,7 @@ QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPrio { // confirmations -> textual description typedef std::map PriorityDescription; - static PriorityDescription priorityDescriptions = boost::assign::map_list_of + const static PriorityDescription priorityDescriptions = boost::assign::map_list_of (1, tr("highest"))(2, tr("higher"))(3, tr("high")) (5, tr("medium-high"))(6, tr("medium")) (10, tr("low-medium"))(15, tr("low")) @@ -452,7 +452,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { CTxOut txout(amount, (CScript)vector(24, 0)); txDummy.vout.push_back(txout); - if (txout.IsDust(CTransaction::minRelayTxFee)) + if (txout.IsDust(::minRelayTxFee)) fDust = true; } } @@ -544,7 +544,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (nChange > 0 && nChange < CENT) { CTxOut txout(nChange, (CScript)vector(24, 0)); - if (txout.IsDust(CTransaction::minRelayTxFee)) + if (txout.IsDust(::minRelayTxFee)) { nPayFee += nChange; nChange = 0; @@ -605,17 +605,17 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // tool tips QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "

"; - toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "

"; + toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK())) + "

"; toolTip1 += tr("Can vary +/- 1 byte per input."); QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "

"; toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "

"; - toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())); + toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK())); - QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546))); + QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546))); // how many satoshis the estimated fee can vary per byte we guess wrong - double dFeeVary = (double)std::max(CTransaction::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000; + double dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000; QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); l3->setToolTip(toolTip4); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 81b9054252..60a131df7e 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -11,6 +11,7 @@ #include "core.h" #include "init.h" +#include "main.h" #include "protocol.h" #include "util.h" @@ -212,7 +213,7 @@ bool isDust(const QString& address, qint64 amount) CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script; script.SetDestination(dest); CTxOut txOut(amount, script); - return txOut.IsDust(CTransaction::minRelayTxFee); + return txOut.IsDust(::minRelayTxFee); } QString HtmlEscape(const QString& str, bool fMultiLine) diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 12d54dff64..9502dba904 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -14,7 +14,10 @@ #include "monitoreddatamapper.h" #include "optionsmodel.h" -#include "main.h" // for CTransaction::minTxFee and MAX_SCRIPTCHECK_THREADS +#include "main.h" // for MAX_SCRIPTCHECK_THREADS +#ifdef ENABLE_WALLET +#include "wallet.h" // for CWallet::minTxFee +#endif #include "netbase.h" #include "txdb.h" // for -dbcache defaults @@ -101,7 +104,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) : #endif ui->unit->setModel(new BitcoinUnits(this)); - ui->transactionFee->setSingleStep(CTransaction::minTxFee.GetFeePerK()); +#ifdef ENABLE_WALLET + ui->transactionFee->setSingleStep(CWallet::minTxFee.GetFeePerK()); +#endif /* Widget-to-option mapper */ mapper = new MonitoredDataMapper(this); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 6ca90f0513..53db2c5cd9 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -551,7 +551,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); - if (txOut.IsDust(CTransaction::minRelayTxFee)) { + if (txOut.IsDust(::minRelayTxFee)) { emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 5b470516a1..9ed6b52513 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -84,7 +84,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("unlocked_until", nWalletUnlockTime)); obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK()))); #endif - obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK()))); + obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 2d7abb2d58..cd3bd59f8f 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -372,7 +372,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); - obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK()))); + obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); Array localAddresses; { LOCK(cs_mapLocalHost); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 0a8ad96aac..a852de5da8 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -80,13 +80,13 @@ public: // Used as belt-and-suspenders check when reading to detect // file corruption - bool AreSane(const std::vector& vecFee) + bool AreSane(const std::vector& vecFee, const CFeeRate& minRelayFee) { BOOST_FOREACH(CFeeRate fee, vecFee) { if (fee < CFeeRate(0)) return false; - if (fee.GetFee(1000) > CTransaction::minRelayTxFee.GetFee(1000) * 10000) + if (fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000) return false; } return true; @@ -109,10 +109,10 @@ public: fileout << vecPriority; } - void Read(CAutoFile& filein) { + void Read(CAutoFile& filein, const CFeeRate& minRelayFee) { std::vector vecFee; filein >> vecFee; - if (AreSane(vecFee)) + if (AreSane(vecFee, minRelayFee)) feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end()); else throw runtime_error("Corrupt fee value in estimates file."); @@ -141,7 +141,7 @@ private: // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc. - void seenTxConfirm(CFeeRate feeRate, double dPriority, int nBlocksAgo) + void seenTxConfirm(const CFeeRate& feeRate, const CFeeRate& minRelayFee, double dPriority, int nBlocksAgo) { // Last entry records "everything else". int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1); @@ -149,7 +149,7 @@ private: // We need to guess why the transaction was included in a block-- either // because it is high-priority or because it has sufficient fees. - bool sufficientFee = (feeRate > CTransaction::minRelayTxFee); + bool sufficientFee = (feeRate > minRelayFee); bool sufficientPriority = AllowFree(dPriority); const char* assignedTo = "unassigned"; if (sufficientFee && !sufficientPriority) @@ -177,7 +177,7 @@ public: history.resize(nEntries); } - void seenBlock(const std::vector& entries, int nBlockHeight) + void seenBlock(const std::vector& entries, int nBlockHeight, const CFeeRate minRelayFee) { if (nBlockHeight <= nBestSeenHeight) { @@ -222,7 +222,7 @@ public: // Fees are stored and reported as BTC-per-kb: CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN - seenTxConfirm(feeRate, dPriority, i); + seenTxConfirm(feeRate, minRelayFee, dPriority, i); } } for (size_t i = 0; i < history.size(); i++) { @@ -313,7 +313,7 @@ public: } } - void Read(CAutoFile& filein) + void Read(CAutoFile& filein, const CFeeRate& minRelayFee) { filein >> nBestSeenHeight; size_t numEntries; @@ -322,14 +322,14 @@ public: for (size_t i = 0; i < numEntries; i++) { CBlockAverage entry; - entry.Read(filein); + entry.Read(filein, minRelayFee); history.push_back(entry); } } }; -CTxMemPool::CTxMemPool() +CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) : minRelayFee(_minRelayFee) { // Sanity checks off by default for performance, because otherwise // accepting transactions becomes O(N^2) where N is the number @@ -445,7 +445,7 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigned i if (mapTx.count(hash)) entries.push_back(mapTx[hash]); } - minerPolicyEstimator->seenBlock(entries, nBlockHeight); + minerPolicyEstimator->seenBlock(entries, nBlockHeight, minRelayFee); BOOST_FOREACH(const CTransaction& tx, vtx) { std::list dummy; @@ -560,7 +560,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein) return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired); LOCK(cs); - minerPolicyEstimator->Read(filein); + minerPolicyEstimator->Read(filein, minRelayFee); } catch (std::exception &e) { LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)"); diff --git a/src/txmempool.h b/src/txmempool.h index f7dbb126a0..41b2c52f39 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -67,13 +67,15 @@ private: unsigned int nTransactionsUpdated; CMinerPolicyEstimator* minerPolicyEstimator; + CFeeRate minRelayFee; // Passed to constructor to avoid dependency on main + public: mutable CCriticalSection cs; std::map mapTx; std::map mapNextTx; std::map > mapDeltas; - CTxMemPool(); + CTxMemPool(const CFeeRate& _minRelayFee); ~CTxMemPool(); /* diff --git a/src/wallet.cpp b/src/wallet.cpp index d9187e4be3..318a1388d2 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -21,6 +21,9 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = 1; bool bSpendZeroConfChange = true; +/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ +CFeeRate CWallet::minTxFee = CFeeRate(10000); // Override with -mintxfee + ////////////////////////////////////////////////////////////////////////////// // // mapWallet @@ -1294,7 +1297,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) { CTxOut txout(s.second, s.first); - if (txout.IsDust(CTransaction::minRelayTxFee)) + if (txout.IsDust(::minRelayTxFee)) { strFailReason = _("Transaction amount too small"); return false; @@ -1355,7 +1358,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, // Never create dust outputs; if we would, just // add the dust to the fee. - if (newTxOut.IsDust(CTransaction::minRelayTxFee)) + if (newTxOut.IsDust(::minRelayTxFee)) { nFeeRet += nChange; reservekey.ReturnKey(); @@ -1537,7 +1540,7 @@ int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge // ... unless we don't have enough mempool data, in which case fall // back to a hard-coded fee if (nFeeNeeded == 0) - nFeeNeeded = CTransaction::minTxFee.GetFee(nTxBytes); + nFeeNeeded = minTxFee.GetFee(nTxBytes); return nFeeNeeded; } diff --git a/src/wallet.h b/src/wallet.h index 19a1b18523..a5162bb838 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -268,6 +268,7 @@ public: std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew); std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + static CFeeRate minTxFee; static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); bool NewKeyPool(); From 2e36866fecb7420cd73047a7aa762a6e5e225695 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Wed, 26 Feb 2014 17:55:04 -0800 Subject: [PATCH 317/336] Show nodeid instead of addresses (for anonymity) unless otherwise requested. --- src/init.cpp | 2 ++ src/main.cpp | 34 +++++++++++++++++----------------- src/net.cpp | 13 +++++++------ src/net.h | 9 +++++++-- src/util.cpp | 1 + src/util.h | 1 + 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index da13218a94..397ce6e065 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -288,6 +288,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -gen " + _("Generate coins (default: 0)") + "\n"; strUsage += " -genproclimit= " + _("Set the processor limit for when generation is on (-1 = unlimited, default: -1)") + "\n"; strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n"; + strUsage += " -logips " + _("Include IP addresses in debug output (default: 0)") + "\n"; strUsage += " -logtimestamps " + _("Prepend debug output with timestamp (default: 1)") + "\n"; if (GetBoolArg("-help-debug", false)) { @@ -585,6 +586,7 @@ bool AppInit2(boost::thread_group& threadGroup) fServer = GetBoolArg("-server", false); fPrintToConsole = GetBoolArg("-printtoconsole", false); fLogTimestamps = GetBoolArg("-logtimestamps", true); + fLogIPs = GetBoolArg("-logips", false); setvbuf(stdout, NULL, _IOLBF, 0); #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); diff --git a/src/main.cpp b/src/main.cpp index 04d9523e26..a461c5c613 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3547,7 +3547,7 @@ void static ProcessGetData(CNode* pfrom) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { RandAddSeedPerfmon(); - LogPrint("net", "received: %s (%u bytes)\n", strCommand, vRecv.size()); + LogPrint("net", "received: %s (%u bytes) peer=%d\n", strCommand, vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -3579,7 +3579,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pfrom->nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version - LogPrintf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString(), pfrom->nVersion); + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)); pfrom->fDisconnect = true; @@ -3660,7 +3660,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->fSuccessfullyConnected = true; - LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), addrFrom.ToString(), pfrom->addr.ToString()); + LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d\n", pfrom->cleanSubVer, pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString(), pfrom->id); AddTimeData(pfrom->addr, nTime); } @@ -3767,7 +3767,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->AddInventoryKnown(inv); bool fAlreadyHave = AlreadyHave(inv); - LogPrint("net", " got inventory: %s %s\n", inv.ToString(), fAlreadyHave ? "have" : "new"); + LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); if (!fAlreadyHave) { if (!fImporting && !fReindex) { @@ -3800,10 +3800,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } if (fDebug || (vInv.size() != 1)) - LogPrint("net", "received getdata (%u invsz)\n", vInv.size()); + LogPrint("net", "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id); if ((fDebug && vInv.size() > 0) || (vInv.size() == 1)) - LogPrint("net", "received getdata for: %s\n", vInv[0].ToString()); + LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); ProcessGetData(pfrom); @@ -3825,7 +3825,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pindex) pindex = chainActive.Next(pindex); int nLimit = 500; - LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop==uint256(0) ? "end" : hashStop.ToString(), nLimit); + LogPrint("net", "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop==uint256(0) ? "end" : hashStop.ToString(), nLimit, pfrom->id); for (; pindex; pindex = chainActive.Next(pindex)) { if (pindex->GetBlockHash() == hashStop) @@ -3908,8 +3908,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) vEraseQueue.push_back(inv.hash); - LogPrint("mempool", "AcceptToMemoryPool: %s %s : accepted %s (poolsz %u)\n", - pfrom->addr.ToString(), pfrom->cleanSubVer, + LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s : accepted %s (poolsz %u)\n", + pfrom->id, pfrom->cleanSubVer, tx.GetHash().ToString(), mempool.mapTx.size()); @@ -3962,8 +3962,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) int nDoS = 0; if (state.IsInvalid(nDoS)) { - LogPrint("mempool", "%s from %s %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(), - pfrom->addr.ToString(), pfrom->cleanSubVer, + LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(), + pfrom->id, pfrom->cleanSubVer, state.GetRejectReason()); pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), state.GetRejectReason(), inv.hash); @@ -3978,7 +3978,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CBlock block; vRecv >> block; - LogPrint("net", "received block %s\n", block.GetHash().ToString()); + LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id); // block.print(); CInv inv(MSG_BLOCK, block.GetHash()); @@ -4095,8 +4095,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } if (!(sProblem.empty())) { - LogPrint("net", "pong %s %s: %s, %x expected, %x received, %u bytes\n", - pfrom->addr.ToString(), + LogPrint("net", "pong peer=%d %s: %s, %x expected, %x received, %u bytes\n", + pfrom->id, pfrom->cleanSubVer, sProblem, pfrom->nPingNonceSent, @@ -4336,7 +4336,7 @@ bool ProcessMessages(CNode* pfrom) } if (!fRet) - LogPrintf("ProcessMessage(%s, %u bytes) FAILED\n", strCommand, nMessageSize); + LogPrintf("ProcessMessage(%s, %u bytes) FAILED peer=%d\n", strCommand, nMessageSize, pfrom->id); break; } @@ -4540,7 +4540,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) uint256 hash = state.vBlocksToDownload.front(); vGetData.push_back(CInv(MSG_BLOCK, hash)); MarkBlockAsInFlight(pto->GetId(), hash); - LogPrint("net", "Requesting block %s from %s\n", hash.ToString(), state.name); + LogPrint("net", "Requesting block %s peer=%d\n", hash.ToString(), pto->id); if (vGetData.size() >= 1000) { pto->PushMessage("getdata", vGetData); @@ -4557,7 +4557,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) if (!AlreadyHave(inv)) { if (fDebug) - LogPrint("net", "sending getdata: %s\n", inv.ToString()); + LogPrint("net", "Requesting %s peer=%d\n", inv.ToString(), pto->id); vGetData.push_back(inv); if (vGetData.size() >= 1000) { diff --git a/src/net.cpp b/src/net.cpp index 934c45ca4c..c7bdb83aad 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -491,8 +491,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) { addrman.Attempt(addrConnect); - LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString()); - // Set to non-blocking #ifdef WIN32 u_long nOne = 1; @@ -513,6 +511,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) } pnode->nTimeConnected = GetTime(); + return pnode; } @@ -524,7 +523,7 @@ void CNode::CloseSocketDisconnect() fDisconnect = true; if (hSocket != INVALID_SOCKET) { - LogPrint("net", "disconnecting node %s\n", addrName); + LogPrint("net", "disconnecting peer=%d\n", id); closesocket(hSocket); hSocket = INVALID_SOCKET; } @@ -548,7 +547,10 @@ void CNode::PushVersion() CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); CAddress addrMe = GetLocalAddress(&addr); RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); - LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), addr.ToString()); + if (fLogIPs) + LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), id); + else + LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight, true); } @@ -950,7 +952,6 @@ void ThreadSocketHandler() } else { - LogPrint("net", "accepted connection %s\n", addr.ToString()); CNode* pnode = new CNode(hSocket, addr, "", true); pnode->AddRef(); @@ -1040,7 +1041,7 @@ void ThreadSocketHandler() { if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { - LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0); + LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); pnode->fDisconnect = true; } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) diff --git a/src/net.h b/src/net.h index 2ee798d468..3b169f442f 100644 --- a/src/net.h +++ b/src/net.h @@ -330,6 +330,11 @@ public: id = nLastNodeId++; } + if (fLogIPs) + LogPrint("net", "Added connection to %s peer=%d\n", addrName, id); + else + LogPrint("net", "Added connection peer=%d\n", id); + // Be shy and don't send version until we hear if (hSocket != INVALID_SOCKET && !fInbound) PushVersion(); @@ -446,7 +451,7 @@ public: nRequestTime = it->second; else nRequestTime = 0; - LogPrint("net", "askfor %s %d (%s)\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); + LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id); // Make sure not to reuse time indexes to keep things in the same order int64_t nNow = GetTimeMicros() - 1000000; @@ -514,7 +519,7 @@ public: assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum)); - LogPrint("net", "(%d bytes)\n", nSize); + LogPrint("net", "(%d bytes) peer=%d\n", nSize, id); std::deque::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData()); ssSend.GetAndClear(*it); diff --git a/src/util.cpp b/src/util.cpp index 5a8f85ade7..081484c37d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -95,6 +95,7 @@ bool fDaemon = false; bool fServer = false; string strMiscWarning; bool fLogTimestamps = false; +bool fLogIPs = false; volatile bool fReopenDebugLog = false; CClientUIInterface uiInterface; diff --git a/src/util.h b/src/util.h index 707b8f2d76..60db71bfd0 100644 --- a/src/util.h +++ b/src/util.h @@ -100,6 +100,7 @@ extern bool fPrintToDebugLog; extern bool fServer; extern std::string strMiscWarning; extern bool fLogTimestamps; +extern bool fLogIPs; extern volatile bool fReopenDebugLog; void RandAddSeed(); From 81efcd76e644d52e2296fd95c594ab49b7b3fca5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 4 Jul 2014 08:15:59 +0200 Subject: [PATCH 318/336] Add libtool generated files to .gitignore --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 564fe68fd9..4169a2d96c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,13 @@ src/config/stamp-h1 src/build-aux/ share/setup.nsi share/qt/Info.plist +# Libtool +libtool +src/m4/libtool.m4 +src/m4/ltoptions.m4 +src/m4/ltsugar.m4 +src/m4/ltversion.m4 +src/m4/lt~obsolete.m4 src/qt/*.moc src/qt/moc_*.cpp From 2ec5a3d212ac4b09e6c32d495f34ee3cdedc8c66 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 20 Jun 2014 15:21:30 +0200 Subject: [PATCH 319/336] rpc: Prevent easy memory exhaustion attack Allocate memory for POST message data only as bytes come in, instead of all at once at the beginning. Fixes #4343. --- src/rpcprotocol.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index dd8692e802..9e18ca847e 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -25,6 +25,9 @@ using namespace boost; using namespace boost::asio; using namespace json_spirit; +// Number of bytes to allocate and read at most at once in post data +const size_t POST_READ_SIZE = 256 * 1024; + // // HTTP protocol // @@ -204,8 +207,17 @@ int ReadHTTPMessage(std::basic_istream& stream, map 0) { - vector vch(nLen); - stream.read(&vch[0], nLen); + vector vch; + size_t ptr = 0; + while (ptr < (size_t)nLen) + { + size_t bytes_to_read = std::min((size_t)nLen - ptr, POST_READ_SIZE); + vch.resize(ptr + bytes_to_read); + stream.read(&vch[ptr], bytes_to_read); + if (!stream) // Connection lost while reading + return HTTP_INTERNAL_SERVER_ERROR; + ptr += bytes_to_read; + } strMessageRet = string(vch.begin(), vch.end()); } From 3d0e92dc83a1aaa462124707388d79da7b2b59aa Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 4 Jul 2014 16:51:25 +0200 Subject: [PATCH 320/336] [Qt] remove dup includes in bitcoingui --- src/qt/bitcoingui.cpp | 5 ----- src/qt/bitcoingui.h | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index f2fb8c877e..b45d861b87 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -34,13 +34,10 @@ #include #include #include -#include #include -#include #include #include #include -#include #include #include #include @@ -51,8 +48,6 @@ #include #include - - #if QT_VERSION < 0x050000 #include #include diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 705e629a69..30dd7ae317 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -21,18 +21,14 @@ class Notificator; class OptionsModel; class RPCConsole; class SendCoinsRecipient; +class UnitDisplayStatusBarControl; class WalletFrame; class WalletModel; class CWallet; -class UnitDisplayStatusBarControl; - QT_BEGIN_NAMESPACE class QAction; -class QLabel; -class QMenu; -class QPoint; class QProgressBar; class QProgressDialog; QT_END_NAMESPACE From 674c070e5d28bdf1e4e631abc157f6ea0b0b1698 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 24 Jun 2014 14:33:38 +0200 Subject: [PATCH 321/336] [Qt] seed OpenSSL PNRG with Windows event data - see https://bitcointalk.org/index.php?topic=113496.msg1228193#msg1228193 for the initial suggestion for this - also ensure consistent debug.log message format --- src/qt/winshutdownmonitor.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp index f8f9bf45b3..a06f42f66e 100644 --- a/src/qt/winshutdownmonitor.cpp +++ b/src/qt/winshutdownmonitor.cpp @@ -6,11 +6,14 @@ #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 #include "init.h" +#include "util.h" #include #include +#include + // If we don't want a message to be processed by Qt, return true and set result to // the value that the window procedure should return. Otherwise return false. bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) @@ -19,6 +22,16 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM MSG *pMsg = static_cast(pMessage); + // Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions) + if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) { + // Warn only once as this is performance-critical + static bool warned = false; + if (!warned) { + LogPrint("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); + warned = true; + } + } + switch(pMsg->message) { case WM_QUERYENDSESSION: @@ -45,13 +58,13 @@ void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, c typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate"); if (shutdownBRCreate == NULL) { - qWarning() << "registerShutdownBlockReason : GetProcAddress for ShutdownBlockReasonCreate failed"; + qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed"; return; } if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str())) - qWarning() << "registerShutdownBlockReason : Successfully registered: " + strReason; + qWarning() << "registerShutdownBlockReason: Successfully registered: " + strReason; else - qWarning() << "registerShutdownBlockReason : Failed to register: " + strReason; + qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason; } #endif From ad87bc4de10d8ff9934635f2a30078ccf531a124 Mon Sep 17 00:00:00 2001 From: Cozz Lovan Date: Sat, 5 Jul 2014 17:14:43 +0200 Subject: [PATCH 322/336] [Qt] Replace status bar unit icon with actual images --- src/Makefile.qt.include | 5 ++++- src/qt/bitcoin.qrc | 3 +++ src/qt/bitcoingui.cpp | 3 +-- src/qt/bitcoinunits.cpp | 11 +++++++++++ src/qt/bitcoinunits.h | 2 ++ src/qt/res/icons/unit_btc.png | Bin 0 -> 2107 bytes src/qt/res/icons/unit_mbtc.png | Bin 0 -> 2107 bytes src/qt/res/icons/unit_ubtc.png | Bin 0 -> 2107 bytes 8 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 src/qt/res/icons/unit_btc.png create mode 100644 src/qt/res/icons/unit_mbtc.png create mode 100644 src/qt/res/icons/unit_ubtc.png diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 4563bb3565..29279aff81 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -252,7 +252,10 @@ RES_ICONS = \ qt/res/icons/tx_inout.png \ qt/res/icons/tx_input.png \ qt/res/icons/tx_output.png \ - qt/res/icons/tx_mined.png + qt/res/icons/tx_mined.png \ + qt/res/icons/unit_btc.png \ + qt/res/icons/unit_mbtc.png \ + qt/res/icons/unit_ubtc.png BITCOIN_QT_CPP = \ qt/bitcoinaddressvalidator.cpp \ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index f38200c7f7..357c6470d3 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -35,6 +35,9 @@ res/icons/tx_input.png res/icons/tx_output.png res/icons/tx_inout.png + res/icons/unit_btc.png + res/icons/unit_mbtc.png + res/icons/unit_ubtc.png res/icons/lock_closed.png res/icons/lock_open.png res/icons/key.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index f2fb8c877e..89cad2ce49 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1014,7 +1014,6 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl():QLabel() { optionsModel = 0; createContextMenu(); - setStyleSheet("font:11pt; color: #333333"); setToolTip(tr("Unit to show amounts in. Click to select another unit.")); } @@ -1059,7 +1058,7 @@ void UnitDisplayStatusBarControl::setOptionsModel(OptionsModel *optionsModel) /** When Display Units are changed on OptionsModel it will refresh the display text of the control on the status bar */ void UnitDisplayStatusBarControl::updateDisplayUnit(int newUnits) { - setText(BitcoinUnits::name(newUnits)); + setPixmap(QIcon(":/icons/unit_" + BitcoinUnits::id(newUnits)).pixmap(31,STATUSBAR_ICONSIZE)); } /** Shows context menu with Display Unit options by the mouse coordinates */ diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 4ba6aba551..bbc9b2e5af 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -34,6 +34,17 @@ bool BitcoinUnits::valid(int unit) } } +QString BitcoinUnits::id(int unit) +{ + switch(unit) + { + case BTC: return QString("btc"); + case mBTC: return QString("mbtc"); + case uBTC: return QString("ubtc"); + default: return QString("???"); + } +} + QString BitcoinUnits::name(int unit) { switch(unit) diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index 451b52ee21..da34ed8976 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -36,6 +36,8 @@ public: static QList availableUnits(); //! Is unit ID valid? static bool valid(int unit); + //! Identifier, e.g. for image names + static QString id(int unit); //! Short name static QString name(int unit); //! Longer description diff --git a/src/qt/res/icons/unit_btc.png b/src/qt/res/icons/unit_btc.png new file mode 100644 index 0000000000000000000000000000000000000000..ec3497435c9bd96caa594d5fa007a80efda05a04 GIT binary patch literal 2107 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%W!3HGX{aEq_NUzopr0F#DPf&c&j literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/unit_mbtc.png b/src/qt/res/icons/unit_mbtc.png new file mode 100644 index 0000000000000000000000000000000000000000..32bf2f2ca05a4768fc8e280a1e4620e3daf42538 GIT binary patch literal 2107 zcmeH|Jxc>Y5QaAh`O*Z_YGGk1l2)`*E+&U~hy=k8F!%=)ZN(y;wb=Rrf}MXL2r8B$ z79vU%L=Y4-HYza)@qOd%F)mR_rNvEnGCMPGW_Fiww>;vcW6`##QYvO=tWo$5&>9Zn zyHwtKfD6tHr7czEXJdDJ1)0cPW_&@Z_#p|bcE#J33KeauKiiWCoP?5PXngZ;z`ue2 zcLP;yN%MmB5lFe))cJazk_m7M-oPcufrgBYwMDQP1NS;1ywov02yOs3+6+3uI;fpw z5&j9>0Y1Q%KndIe8)%bF_3#T_6kh6>-Up7TdrJ!QfIG?pKK2;5xbZo>Hfkl$hy_9kzrEDQW{(X3-IO0KinGl()_oWO*K3*UY9D#9~ov2XL$;ofeI*s YY4CT}S8=*GuO0Y$rMz>J*zEB-luA|0dSJXSpSVgDYS6?MpFn&9 z&J(C3YxsnJ0g4T!$-7ocrolD%26vzWA{hr8%fOic&n6*OsbhKwJOX~uR?r1@LCEYz z8B5=6ejA$bcRDhCiXf1Q|9rUtH8Q3z`9R!Hk!7-nrB{%*G|td&l(F=A Date: Sat, 5 Jul 2014 22:43:12 +0700 Subject: [PATCH 323/336] Remove unused variable --- src/qt/coincontroldialog.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index e0a524a55e..c73cf416a8 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -523,9 +523,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority); - // Fee - int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes)); - // Min Fee nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); From 3c85d2ec37c3725e407649e487fbeb2a36606d74 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 6 Jul 2014 13:37:32 +0200 Subject: [PATCH 324/336] Fix CChain::GetLocator --- src/main.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b2773953d1..3de60ee3ec 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -423,15 +423,13 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const { break; // Exponentially larger steps back, plus the genesis block. int nHeight = std::max(pindex->nHeight - nStep, 0); - // Jump back quickly to the same height as the chain. - if (pindex->nHeight > nHeight) - pindex = pindex->GetAncestor(nHeight); - // In case pindex is not in this chain, iterate pindex->pprev to find blocks. - while (!Contains(pindex)) - pindex = pindex->pprev; - // If pindex is in this chain, use direct height-based access. - if (pindex->nHeight > nHeight) + if (Contains(pindex)) { + // Use O(1) CChain index if possible. pindex = (*this)[nHeight]; + } else { + // Otherwise, use O(log n) skiplist. + pindex = pindex->GetAncestor(nHeight); + } if (vHave.size() > 10) nStep *= 2; } From f4b00beae52f22fc6958855a85e1012387c3c33e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 6 Jul 2014 14:40:31 +0200 Subject: [PATCH 325/336] Add CChain::GetLocator() unit test --- src/test/skiplist_tests.cpp | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index ea301685c9..11762c6ea0 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -41,5 +41,61 @@ BOOST_AUTO_TEST_CASE(skiplist_test) } } +BOOST_AUTO_TEST_CASE(getlocator_test) +{ + // Build a main chain 100000 blocks long. + std::vector vHashMain(100000); + std::vector vBlocksMain(100000); + for (unsigned int i=0; inHeight + 1); + } + + // Build a branch that splits off at block 49999, 50000 blocks long. + std::vector vHashSide(50000); + std::vector vBlocksSide(50000); + for (unsigned int i=0; inHeight + 1); + } + + // Build a CChain for the main branch. + CChain chain; + chain.SetTip(&vBlocksMain.back()); + + // Test 100 random starting points for locators. + for (int n=0; n<100; n++) { + int r = insecure_rand() % 150000; + CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000]; + CBlockLocator locator = chain.GetLocator(tip); + + // The first result must be the block itself, the last one must be genesis. + BOOST_CHECK(locator.vHave.front() == tip->GetBlockHash()); + BOOST_CHECK(locator.vHave.back() == vBlocksMain[0].GetBlockHash()); + + // Entries 1 through 11 (inclusive) go back one step each. + for (unsigned int i = 1; i < 12 && i < locator.vHave.size() - 1; i++) { + BOOST_CHECK_EQUAL(locator.vHave[i].GetLow64(), tip->nHeight - i); + } + + // The further ones (excluding the last one) go back with exponential steps. + unsigned int dist = 2; + for (unsigned int i = 12; i < locator.vHave.size() - 1; i++) { + BOOST_CHECK_EQUAL(locator.vHave[i - 1].GetLow64() - locator.vHave[i].GetLow64(), dist); + dist *= 2; + } + } +} + BOOST_AUTO_TEST_SUITE_END() From 40f5cb878edd04b4be14f0d73ab706dc2e69124c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 6 Jul 2014 14:47:23 +0200 Subject: [PATCH 326/336] Send rejects and apply DoS scoring for errors in direct block validation. 75f51f2a introduced asynchronous processing for blocks, where reject messages and DoS scoring could be applied outside of ProcessBlock, because block validation may happen later. However, some types of errors are still detected immediately (in particular, CheckBlock violations), which need acting after ProcessBlock returns. --- src/main.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index b2773953d1..04af88ba46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3984,6 +3984,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CValidationState state; ProcessBlock(state, pfrom, &block); + int nDoS; + if (state.IsInvalid(nDoS)) { + pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), + state.GetRejectReason(), inv.hash); + if (nDoS > 0) { + LOCK(cs_main); + Misbehaving(pfrom->GetId(), nDoS); + } + } + } From 9f4da19babf6989a639be29c70c1d2470c5829a6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 6 Jul 2014 16:06:46 +0200 Subject: [PATCH 327/336] Use pong receive time rather than processing time --- src/main.cpp | 6 +++--- src/net.cpp | 3 +++ src/net.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 04d9523e26..7eb4190134 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3544,7 +3544,7 @@ void static ProcessGetData(CNode* pfrom) } } -bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) +bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { RandAddSeedPerfmon(); LogPrint("net", "received: %s (%u bytes)\n", strCommand, vRecv.size()); @@ -4054,7 +4054,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else if (strCommand == "pong") { - int64_t pingUsecEnd = GetTimeMicros(); + int64_t pingUsecEnd = nTimeReceived; uint64_t nonce = 0; size_t nAvail = vRecv.in_avail(); bool bPingFinished = false; @@ -4305,7 +4305,7 @@ bool ProcessMessages(CNode* pfrom) bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv); + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime); boost::this_thread::interruption_point(); } catch (std::ios_base::failure& e) diff --git a/src/net.cpp b/src/net.cpp index 934c45ca4c..fbf13b41cb 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -653,6 +653,9 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) pch += handled; nBytes -= handled; + + if (msg.complete()) + msg.nTime = GetTimeMicros(); } return true; diff --git a/src/net.h b/src/net.h index 2ee798d468..e85fc5f9b6 100644 --- a/src/net.h +++ b/src/net.h @@ -173,11 +173,14 @@ public: CDataStream vRecv; // received message data unsigned int nDataPos; + int64_t nTime; // time (in microseconds) of message receipt. + CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn) { hdrbuf.resize(24); in_data = false; nHdrPos = 0; nDataPos = 0; + nTime = 0; } bool complete() const From 0127a9be14089b3f352ec349b2ecf4488234a4d8 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Wed, 11 Jun 2014 13:20:59 +0200 Subject: [PATCH 328/336] remove SOCKS4 support from core and GUI - now we support SOCKS5 only --- src/init.cpp | 19 ++---- src/netbase.cpp | 124 ++++++++-------------------------- src/netbase.h | 6 +- src/qt/forms/optionsdialog.ui | 20 ------ src/qt/optionsdialog.cpp | 8 --- src/qt/optionsmodel.cpp | 28 ++------ src/qt/paymentserver.cpp | 14 ++-- src/rpcmisc.cpp | 2 +- src/rpcnet.cpp | 2 +- 9 files changed, 49 insertions(+), 174 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index c514facbbe..a92d2aad67 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -238,9 +238,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -onion= " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n"; strUsage += " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6 or Tor)") + "\n"; strUsage += " -port= " + _("Listen for connections on (default: 8333 or testnet: 18333)") + "\n"; - strUsage += " -proxy= " + _("Connect through SOCKS proxy") + "\n"; + strUsage += " -proxy= " + _("Connect through SOCKS5 proxy") + "\n"; strUsage += " -seednode= " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n"; - strUsage += " -socks= " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n"; strUsage += " -timeout= " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n"; #ifdef USE_UPNP #if USE_UPNP @@ -745,10 +744,6 @@ bool AppInit2(boost::thread_group& threadGroup) RegisterNodeSignals(GetNodeSignals()); - int nSocksVersion = GetArg("-socks", 5); - if (nSocksVersion != 4 && nSocksVersion != 5) - return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); - if (mapArgs.count("-onlynet")) { std::set nets; BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { @@ -772,12 +767,10 @@ bool AppInit2(boost::thread_group& threadGroup) return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); if (!IsLimited(NET_IPV4)) - SetProxy(NET_IPV4, addrProxy, nSocksVersion); - if (nSocksVersion > 4) { - if (!IsLimited(NET_IPV6)) - SetProxy(NET_IPV6, addrProxy, nSocksVersion); - SetNameProxy(addrProxy, nSocksVersion); - } + SetProxy(NET_IPV4, addrProxy); + if (!IsLimited(NET_IPV6)) + SetProxy(NET_IPV6, addrProxy); + SetNameProxy(addrProxy); fProxy = true; } @@ -791,7 +784,7 @@ bool AppInit2(boost::thread_group& threadGroup) addrOnion = CService(mapArgs["-onion"], 9050); if (!addrOnion.IsValid()) return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); - SetProxy(NET_TOR, addrOnion, 5); + SetProxy(NET_TOR, addrOnion); SetReachable(NET_TOR); } diff --git a/src/netbase.cpp b/src/netbase.cpp index f47b0f3563..2567c4c780 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -37,7 +37,7 @@ using namespace std; // Settings static proxyType proxyInfo[NET_MAX]; -static proxyType nameproxyInfo; +static CService nameProxy; static CCriticalSection cs_proxyInfos; int nConnectTimeout = 5000; bool fNameLookup = false; @@ -214,50 +214,6 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault) return Lookup(pszName, addr, portDefault, false); } -bool static Socks4(const CService &addrDest, SOCKET& hSocket) -{ - LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString()); - if (!addrDest.IsIPv4()) - { - closesocket(hSocket); - return error("Proxy destination is not IPv4"); - } - char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user"; - struct sockaddr_in addr; - socklen_t len = sizeof(addr); - if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET) - { - closesocket(hSocket); - return error("Cannot get proxy destination address"); - } - memcpy(pszSocks4IP + 2, &addr.sin_port, 2); - memcpy(pszSocks4IP + 4, &addr.sin_addr, 4); - char* pszSocks4 = pszSocks4IP; - int nSize = sizeof(pszSocks4IP); - - int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL); - if (ret != nSize) - { - closesocket(hSocket); - return error("Error sending to proxy"); - } - char pchRet[8]; - if (recv(hSocket, pchRet, 8, 0) != 8) - { - closesocket(hSocket); - return error("Error reading proxy response"); - } - if (pchRet[1] != 0x5a) - { - closesocket(hSocket); - if (pchRet[1] != 0x5b) - LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]); - return false; - } - LogPrintf("SOCKS4 connected %s\n", addrDest.ToString()); - return true; -} - bool static Socks5(string strDest, int port, SOCKET& hSocket) { LogPrintf("SOCKS5 connecting %s\n", strDest); @@ -468,53 +424,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe return true; } -bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) { +bool SetProxy(enum Network net, CService addrProxy) { assert(net >= 0 && net < NET_MAX); - if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5) - return false; - if (nSocksVersion != 0 && !addrProxy.IsValid()) + if (!addrProxy.IsValid()) return false; LOCK(cs_proxyInfos); - proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion); + proxyInfo[net] = addrProxy; return true; } bool GetProxy(enum Network net, proxyType &proxyInfoOut) { assert(net >= 0 && net < NET_MAX); LOCK(cs_proxyInfos); - if (!proxyInfo[net].second) + if (!proxyInfo[net].IsValid()) return false; proxyInfoOut = proxyInfo[net]; return true; } -bool SetNameProxy(CService addrProxy, int nSocksVersion) { - if (nSocksVersion != 0 && nSocksVersion != 5) - return false; - if (nSocksVersion != 0 && !addrProxy.IsValid()) +bool SetNameProxy(CService addrProxy) { + if (!addrProxy.IsValid()) return false; LOCK(cs_proxyInfos); - nameproxyInfo = std::make_pair(addrProxy, nSocksVersion); + nameProxy = addrProxy; return true; } -bool GetNameProxy(proxyType &nameproxyInfoOut) { +bool GetNameProxy(CService &nameProxyOut) { LOCK(cs_proxyInfos); - if (!nameproxyInfo.second) + if(!nameProxy.IsValid()) return false; - nameproxyInfoOut = nameproxyInfo; + nameProxyOut = nameProxy; return true; } bool HaveNameProxy() { LOCK(cs_proxyInfos); - return nameproxyInfo.second != 0; + return nameProxy.IsValid(); } bool IsProxy(const CNetAddr &addr) { LOCK(cs_proxyInfos); for (int i = 0; i < NET_MAX; i++) { - if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first)) + if (addr == (CNetAddr)proxyInfo[i]) return true; } return false; @@ -523,31 +475,18 @@ bool IsProxy(const CNetAddr &addr) { bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) { proxyType proxy; - - // no proxy needed + // no proxy needed (none set for target network) if (!GetProxy(addrDest.GetNetwork(), proxy)) return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); SOCKET hSocket = INVALID_SOCKET; // first connect to proxy server - if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) + if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) return false; - // do socks negotiation - switch (proxy.second) { - case 4: - if (!Socks4(addrDest, hSocket)) - return false; - break; - case 5: - if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) - return false; - break; - default: - closesocket(hSocket); + if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) return false; - } hSocketRet = hSocket; return true; @@ -561,30 +500,25 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest SOCKET hSocket = INVALID_SOCKET; - proxyType nameproxy; - GetNameProxy(nameproxy); + CService nameProxy; + GetNameProxy(nameProxy); - CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port); + CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port); if (addrResolved.IsValid()) { addr = addrResolved; return ConnectSocket(addr, hSocketRet, nTimeout); } - addr = CService("0.0.0.0:0"); - if (!nameproxy.second) - return false; - if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout)) - return false; - switch(nameproxy.second) { - default: - case 4: - closesocket(hSocket); - return false; - case 5: - if (!Socks5(strDest, port, hSocket)) - return false; - break; - } + addr = CService("0.0.0.0:0"); + + if (!HaveNameProxy()) + return false; + // first connect to name proxy server + if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) + return false; + // do socks negotiation + if (!Socks5(strDest, (unsigned short)port, hSocket)) + return false; hSocketRet = hSocket; return true; diff --git a/src/netbase.h b/src/netbase.h index 40a3d25676..ad1e230834 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -161,14 +161,14 @@ class CService : public CNetAddr ) }; -typedef std::pair proxyType; +typedef CService proxyType; enum Network ParseNetwork(std::string net); void SplitHostPort(std::string in, int &portOut, std::string &hostOut); -bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5); +bool SetProxy(enum Network net, CService addrProxy); bool GetProxy(enum Network net, proxyType &proxyInfoOut); bool IsProxy(const CNetAddr &addr); -bool SetNameProxy(CService addrProxy, int nSocksVersion = 5); +bool SetNameProxy(CService addrProxy); bool HaveNameProxy(); bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 0c5b8895aa..1f535a4a62 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -328,26 +328,6 @@ - - - - SOCKS &Version: - - - Qt::PlainText - - - socksVersion - - - - - - - SOCKS version of the proxy (e.g. 5) - - - diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 9502dba904..597be40abd 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -52,15 +52,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) : ui->proxyPort->setEnabled(false); ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); - /** SOCKS version is only selectable for default proxy and is always 5 for IPv6 and Tor */ - ui->socksVersion->setEnabled(false); - ui->socksVersion->addItem("5", 5); - ui->socksVersion->addItem("4", 4); - ui->socksVersion->setCurrentIndex(0); - connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool))); connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool))); - connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); ui->proxyIp->installEventFilter(this); @@ -182,7 +175,6 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); - mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); /* Window */ #ifndef Q_OS_MAC diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 09553a2587..f07e66bf04 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -122,11 +122,6 @@ void OptionsModel::Init() // Only try to set -proxy, if user has enabled fUseProxy if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) addOverriddenOption("-proxy"); - if (!settings.contains("nSocksVersion")) - settings.setValue("nSocksVersion", 5); - // Only try to set -socks, if user has enabled fUseProxy - if (settings.value("fUseProxy").toBool() && !SoftSetArg("-socks", settings.value("nSocksVersion").toString().toStdString())) - addOverriddenOption("-socks"); // Display if (!settings.contains("language")) @@ -188,8 +183,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts); return strlIpPort.at(1); } - case ProxySocksVersion: - return settings.value("nSocksVersion", 5); #ifdef ENABLE_WALLET case Fee: { @@ -284,13 +277,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } } break; - case ProxySocksVersion: { - if (settings.value("nSocksVersion") != value) { - settings.setValue("nSocksVersion", value.toInt()); - setRestartRequired(true); - } - } - break; #ifdef ENABLE_WALLET case Fee: { // core option - can be changed on-the-fly // Todo: Add is valid check and warn via message, if not @@ -378,20 +364,16 @@ bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const // GUI settings can be overridden with -proxy. proxyType curProxy; if (GetProxy(NET_IPV4, curProxy)) { - if (curProxy.second == 5) { - proxy.setType(QNetworkProxy::Socks5Proxy); - proxy.setHostName(QString::fromStdString(curProxy.first.ToStringIP())); - proxy.setPort(curProxy.first.GetPort()); + proxy.setType(QNetworkProxy::Socks5Proxy); + proxy.setHostName(QString::fromStdString(curProxy.ToStringIP())); + proxy.setPort(curProxy.GetPort()); - return true; - } - else - return false; + return true; } else proxy.setType(QNetworkProxy::NoProxy); - return true; + return false; } void OptionsModel::setRestartRequired(bool fRequired) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 53db2c5cd9..5471625a67 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -341,20 +341,14 @@ void PaymentServer::initNetManager() QNetworkProxy proxy; - // Query active proxy (fails if no SOCKS5 proxy) + // Query active SOCKS5 proxy if (optionsModel->getProxySettings(proxy)) { - if (proxy.type() == QNetworkProxy::Socks5Proxy) { - netManager->setProxy(proxy); + netManager->setProxy(proxy); - qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port(); - } - else - qDebug() << "PaymentServer::initNetManager : No active proxy server found."; + qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port(); } else - emit message(tr("Net manager warning"), - tr("Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy."), - CClientUIInterface::MSG_WARNING); + qDebug() << "PaymentServer::initNetManager : No active proxy server found."; connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(netRequestFinished(QNetworkReply*))); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 9ed6b52513..1e84393025 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -72,7 +72,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); - obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); + obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string()))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("testnet", Params().NetworkID() == CBaseChainParams::TESTNET)); #ifdef ENABLE_WALLET diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index cd3bd59f8f..cf2c293caf 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -371,7 +371,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices))); obj.push_back(Pair("timeoffset", GetTimeOffset())); obj.push_back(Pair("connections", (int)vNodes.size())); - obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); + obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string()))); obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); Array localAddresses; { From a339a37b28176135c7fe5adbd3b50da77a45373d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 16 Jun 2014 08:48:32 +0200 Subject: [PATCH 329/336] error out, when we detect -socks argument --- src/init.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index a92d2aad67..db9247ef6f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -565,6 +565,9 @@ bool AppInit2(boost::thread_group& threadGroup) // Check for -debugnet (deprecated) if (GetBoolArg("-debugnet", false)) InitWarning(_("Warning: Deprecated argument -debugnet ignored, use -debug=net")); + // Check for -socks - as this is a privacy risk to continue, exit here + if (mapArgs.count("-socks")) + return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); // Check for -tor - as this is a privacy risk to continue, exit here if (GetBoolArg("-tor", false)) return InitError(_("Error: Unsupported argument -tor found, use -onion.")); From e832ab7754732af7fd46ad7f16eef973e238c357 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Mon, 7 Jul 2014 09:34:43 +0200 Subject: [PATCH 330/336] Rename SendMoneyToDestination to SendMoney. Get rid of SendMoney and replace it by the functionality of SendMoneyToDestination. This cleans up the code, since only SendMoneyToDestination was actually used (SendMoney internally from this routine). --- src/rpcwallet.cpp | 4 ++-- src/wallet.cpp | 55 +++++++++++++++++++++-------------------------- src/wallet.h | 3 +-- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 38e96133b4..639b21f120 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -346,7 +346,7 @@ Value sendtoaddress(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx); if (strError != "") throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -786,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoney(address.Get(), nAmount, wtx); if (strError != "") throw JSONRPCError(RPC_WALLET_ERROR, strError); diff --git a/src/wallet.cpp b/src/wallet.cpp index 318a1388d2..ed1b178600 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1487,35 +1487,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) -string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew) -{ - CReserveKey reservekey(this); - int64_t nFeeRequired; - - if (IsLocked()) - { - string strError = _("Error: Wallet locked, unable to create transaction!"); - LogPrintf("SendMoney() : %s", strError); - return strError; - } - string strError; - if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) - { - if (nValue + nFeeRequired > GetBalance()) - strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired)); - LogPrintf("SendMoney() : %s\n", strError); - return strError; - } - - if (!CommitTransaction(wtxNew, reservekey)) - return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); - - return ""; -} - - - -string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew) +string CWallet::SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew) { // Check amount if (nValue <= 0) @@ -1523,13 +1495,36 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV if (nValue > GetBalance()) return _("Insufficient funds"); + string strError; + if (IsLocked()) + { + strError = _("Error: Wallet locked, unable to create transaction!"); + LogPrintf("SendMoney() : %s", strError); + return strError; + } + // Parse Bitcoin address CScript scriptPubKey; scriptPubKey.SetDestination(address); - return SendMoney(scriptPubKey, nValue, wtxNew); + // Create and send the transaction + CReserveKey reservekey(this); + int64_t nFeeRequired; + if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) + { + if (nValue + nFeeRequired > GetBalance()) + strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired)); + LogPrintf("SendMoney() : %s\n", strError); + return strError; + } + if (!CommitTransaction(wtxNew, reservekey)) + return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + + return ""; } + + int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { // payTxFee is user-set "I want to pay this much" diff --git a/src/wallet.h b/src/wallet.h index a5162bb838..62f13e4630 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -265,8 +265,7 @@ public: bool CreateTransaction(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); - std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew); - std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + std::string SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); static CFeeRate minTxFee; static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); From 509030344c66d2a2e27e50a690c43d577e5b943b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 3 Jul 2014 07:31:50 +0200 Subject: [PATCH 331/336] qt: Pick translation messages only from necessary files Utility libraries (common, util) as well as extra tools shouldn't be parsed for translation messages, only the server and wallet part qualify here. --- share/qt/extract_strings_qt.py | 5 ++- src/Makefile.qt.include | 4 +- src/qt/bitcoinstrings.cpp | 74 +++++++++++++++++++--------------- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py index e6afe3b48b..d4bd585138 100755 --- a/share/qt/extract_strings_qt.py +++ b/share/qt/extract_strings_qt.py @@ -7,8 +7,9 @@ from subprocess import Popen, PIPE import glob import operator import os +import sys -OUT_CPP="src/qt/bitcoinstrings.cpp" +OUT_CPP="qt/bitcoinstrings.cpp" EMPTY=['""'] def parse_po(text): @@ -47,7 +48,7 @@ def parse_po(text): return messages -files = glob.glob('src/*.cpp') + glob.glob('src/*.h') +files = sys.argv[1:] # xgettext -n --keyword=_ $FILES XGETTEXT=os.getenv('XGETTEXT', 'xgettext') diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 4563bb3565..f2b6c2ccd6 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -367,9 +367,9 @@ QT_QM=$(QT_TS:.ts=.qm) .SECONDARY: $(QT_QM) -qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_cli_a_SOURCES) $(libbitcoin_util_a_SOURCES) +qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" - $(AM_V_GEN) cd $(top_srcdir); XGETTEXT=$(XGETTEXT) share/qt/extract_strings_qt.py + $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) ../share/qt/extract_strings_qt.py $^ translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 10b44bbc3f..b717546708 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -22,31 +22,42 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "It is also recommended to set alertnotify so you are notified of problems;\n" "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"(default: 1, 1 = keep tx meta data e.g. account owner and payment request " +"information, 2 = drop tx meta data)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!" "3DES:@STRENGTH)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"An error occurred while setting up the RPC port %u for listening on IPv4: %s"), +"Allow JSON-RPC connections from specified source. Valid for are a " +"single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or " +"a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"An error occurred while setting up the RPC port %u for listening on IPv6, " -"falling back to IPv4: %s"), +"An error occurred while setting up the RPC address %s port %u for listening: " +"%s"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Bind to given address and always listen on it. Use [host]:port notation for " "IPv6"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Bind to given address to listen for JSON-RPC connections. Use [host]:port " +"notation for IPv6. This option can be specified multiple times (default: " +"bind to all interfaces)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Cannot obtain a lock on data directory %s. Bitcoin Core is probably already " "running."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Continuously rate-limit free transactions to *1000 bytes per minute " "(default:15)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Enter regression test mode, which uses a special chain in which blocks can " -"be solved instantly. This is intended for regression testing tools and app " -"development."), +"Delete all wallet transactions and only recover those part of the blockchain " +"through -rescan on startup"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Distributed under the MIT/X11 software license, see the accompanying file " +"COPYING or ."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Enter regression test mode, which uses a special chain in which blocks can " "be solved instantly."), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Error: Listening for incoming connections failed (listen returned error %d)"), +"Error: Listening for incoming connections failed (listen returned error %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Error: The transaction was rejected! This might happen if some of the coins " "in your wallet were already spent, such as if you used a copy of wallet.dat " @@ -55,6 +66,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Error: This transaction requires a transaction fee of at least %s because of " "its amount, complexity, or use of recently received funds!"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Execute command when a network tx respends wallet tx input (%s=respend TxID, " +"%t=wallet TxID)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Execute command when a relevant alert is received or we see a really long " "fork (%s in cmd is replaced by message)"), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -64,8 +78,11 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Execute command when the best block changes (%s in cmd is replaced by block " "hash)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Fees smaller than this are considered zero fee (for transaction creation) " -"(default:"), +"Fees (in BTC/Kb) smaller than this are considered zero fee for relaying " +"(default: %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" +"Fees (in BTC/Kb) smaller than this are considered zero fee for transaction " +"creation (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Flush database activity from memory pool to disk log every megabytes " "(default: 100)"), @@ -93,6 +110,10 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "This is a pre-release test build - use at your own risk - do not use for " "mining or merchant applications"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"This product includes software developed by the OpenSSL Project for use in " +"the OpenSSL Toolkit and cryptographic software " +"written by Eric Young and UPnP software written by Thomas Bernard."), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Unable to bind to %s on this computer. Bitcoin Core is probably already " "running."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -117,11 +138,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as " "wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect " "you should restore from a backup."), -QT_TRANSLATE_NOOP("bitcoin-core", "" -"You must set rpcpassword= in the configuration file:\n" -"%s\n" -"If the file does not exist, create it with owner-readable-only file " -"permissions."), QT_TRANSLATE_NOOP("bitcoin-core", "(default: 1)"), QT_TRANSLATE_NOOP("bitcoin-core", "(default: wallet.dat)"), QT_TRANSLATE_NOOP("bitcoin-core", " can be:"), @@ -129,22 +145,19 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"), QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"), QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"), -QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"), QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"), -QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core Daemon"), -QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core RPC client version"), QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"), -QT_TRANSLATE_NOOP("bitcoin-core", "Clear list of wallet transactions (diagnostic tool; implies -rescan)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS proxy"), -QT_TRANSLATE_NOOP("bitcoin-core", "Connect to JSON-RPC on (default: 8332 or testnet: 18332)"), QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"), QT_TRANSLATE_NOOP("bitcoin-core", "Connection options:"), +QT_TRANSLATE_NOOP("bitcoin-core", "Copyright (C) 2009-%i The Bitcoin Core Developers"), QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"), +QT_TRANSLATE_NOOP("bitcoin-core", "Could not parse -rpcbind value %s as network address"), QT_TRANSLATE_NOOP("bitcoin-core", "Debugging/Testing options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Disable safemode, override a real safe mode event (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Discover own IP address (default: 1 when listening and no -externalip)"), @@ -160,6 +173,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet.dat: Wallet requires new QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"), QT_TRANSLATE_NOOP("bitcoin-core", "Error"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"), +QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unsupported argument -tor found, use -onion."), QT_TRANSLATE_NOOP("bitcoin-core", "Error: Wallet locked, unable to create transaction!"), QT_TRANSLATE_NOOP("bitcoin-core", "Error: system error: "), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."), @@ -173,18 +187,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write file info"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write to coin database"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"), QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"), -QT_TRANSLATE_NOOP("bitcoin-core", "Fee per kB to add to transactions you send"), -QT_TRANSLATE_NOOP("bitcoin-core", "Fees smaller than this are considered zero fee (for relaying) (default:"), +QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in BTC/kB) to add to transactions you send (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"), QT_TRANSLATE_NOOP("bitcoin-core", "Force safe mode (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: 0)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"), QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"), QT_TRANSLATE_NOOP("bitcoin-core", "If is not supplied, output all debugging information."), QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."), QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file"), QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Information"), +QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. Bitcoin Core is shutting down."), QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), @@ -192,8 +205,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -minrelaytxfee=: ' QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"), +QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most unconnectable blocks in memory (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Limit size of signature cache to entries (default: 50000)"), -QT_TRANSLATE_NOOP("bitcoin-core", "List commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on (default: 8333 or testnet: 18333)"), QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."), QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index..."), @@ -203,6 +216,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Maintain a full transaction index (default: 0 QT_TRANSLATE_NOOP("bitcoin-core", "Maintain at most connections to peers (default: 125)"), QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection receive buffer, *1000 bytes (default: 5000)"), QT_TRANSLATE_NOOP("bitcoin-core", "Maximum per-connection send buffer, *1000 bytes (default: 1000)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Node relay options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."), QT_TRANSLATE_NOOP("bitcoin-core", "Only accept block chain matching built-in checkpoints (default: 1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network (IPv4, IPv6 or Tor)"), @@ -212,19 +226,16 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp (default: QT_TRANSLATE_NOOP("bitcoin-core", "Print block on startup, if found in block index"), QT_TRANSLATE_NOOP("bitcoin-core", "Print block tree on startup (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "RPC SSL options: (see the Bitcoin Wiki for SSL setup instructions)"), -QT_TRANSLATE_NOOP("bitcoin-core", "RPC client options:"), QT_TRANSLATE_NOOP("bitcoin-core", "RPC server options:"), QT_TRANSLATE_NOOP("bitcoin-core", "Randomly drop 1 of every network messages"), QT_TRANSLATE_NOOP("bitcoin-core", "Randomly fuzz 1 of every network messages"), QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild block chain index from current blk000??.dat files"), +QT_TRANSLATE_NOOP("bitcoin-core", "Relay and mine data carrier transactions (default: 1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"), QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), QT_TRANSLATE_NOOP("bitcoin-core", "Run a thread to flush wallet periodically (default: 1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), -QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"), QT_TRANSLATE_NOOP("bitcoin-core", "Select SOCKS version for -proxy (4 or 5, default: 5)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Send command to Bitcoin Core"), -QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on (default: 127.0.0.1)"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert)"), QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"), @@ -245,21 +256,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Specify pid file (default: bitcoind.pid)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify wallet file (within data directory)"), QT_TRANSLATE_NOOP("bitcoin-core", "Specify your own public address"), QT_TRANSLATE_NOOP("bitcoin-core", "Spend unconfirmed change when sending transactions (default: 1)"), -QT_TRANSLATE_NOOP("bitcoin-core", "Start Bitcoin Core Daemon"), +QT_TRANSLATE_NOOP("bitcoin-core", "Stop running after importing blocks from disk (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "System error: "), QT_TRANSLATE_NOOP("bitcoin-core", "This help message"), +QT_TRANSLATE_NOOP("bitcoin-core", "This is experimental software."), QT_TRANSLATE_NOOP("bitcoin-core", "This is intended for regression testing tools and app development."), QT_TRANSLATE_NOOP("bitcoin-core", "Threshold for disconnecting misbehaving peers (default: 100)"), QT_TRANSLATE_NOOP("bitcoin-core", "To use the %s option"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amount too small"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction amounts must be positive"), QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"), -QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %d, %s)"), +QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -socks proxy version requested: %i"), QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"), -QT_TRANSLATE_NOOP("bitcoin-core", "Usage (deprecated, use bitcoin-cli):"), -QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"), QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"), @@ -267,7 +277,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"), QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."), QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."), -QT_TRANSLATE_NOOP("bitcoin-core", "Wait for RPC server to start"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"), QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"), @@ -277,6 +286,5 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade re QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"), QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."), QT_TRANSLATE_NOOP("bitcoin-core", "on startup"), -QT_TRANSLATE_NOOP("bitcoin-core", "version"), QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"), }; From 73ac7abd08a70adf22e24d0f5f7631e7f8b7c5bb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 3 Jul 2014 07:45:16 +0200 Subject: [PATCH 332/336] Move ui_interface to bitcoin_server.a There is no need for it in the utility libraries or tools. Put it in init.cpp, and in the tests separately (as they can't link init). --- src/bitcoin-cli.cpp | 3 ++- src/init.cpp | 1 + src/qt/bitcoinstrings.cpp | 5 +++++ src/test/test_bitcoin.cpp | 2 +- src/util.cpp | 2 -- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index db39df4b17..016b2f50f5 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -7,11 +7,12 @@ #include "init.h" #include "rpcclient.h" #include "rpcprotocol.h" -#include "ui_interface.h" /* for _(...) */ #include "chainparamsbase.h" #include +#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */ + using namespace std; using namespace boost; using namespace boost::asio; diff --git a/src/init.cpp b/src/init.cpp index c514facbbe..dcb71c4206 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -62,6 +62,7 @@ enum BindFlags { }; static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; +CClientUIInterface uiInterface; ////////////////////////////////////////////////////////////////////////////// // diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index b717546708..e852c468a8 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -89,6 +89,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", "" "How thorough the block verification of -checkblocks is (0-4, default: 3)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"If paytxfee is not set, include enough fee so transactions are confirmed on " +"average within n blocks (default: 1)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "In this mode -genproclimit controls how many blocks are generated " "immediately."), QT_TRANSLATE_NOOP("bitcoin-core", "" @@ -195,6 +198,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: QT_TRANSLATE_NOOP("bitcoin-core", "If is not supplied, output all debugging information."), QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."), QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file"), +QT_TRANSLATE_NOOP("bitcoin-core", "Include IP addresses in debug output (default: 0)"), QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Information"), QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. Bitcoin Core is shutting down."), @@ -203,6 +207,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -minrelaytxfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -mintxfee=: '%s'"), +QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s' (must be at least %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount"), QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most unconnectable blocks in memory (default: %u)"), diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 8cae0a4c34..bcd2f75f55 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -18,7 +18,7 @@ #include #include - +CClientUIInterface uiInterface; CWallet* pwalletMain; extern bool fPrintToConsole; diff --git a/src/util.cpp b/src/util.cpp index 081484c37d..9adbbdec48 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -7,7 +7,6 @@ #include "chainparamsbase.h" #include "sync.h" -#include "ui_interface.h" #include "uint256.h" #include "version.h" @@ -97,7 +96,6 @@ string strMiscWarning; bool fLogTimestamps = false; bool fLogIPs = false; volatile bool fReopenDebugLog = false; -CClientUIInterface uiInterface; // Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; From 209377a7cb5a9ea5d724faf94846ee5bacd289e7 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 28 Jun 2014 23:36:06 +0200 Subject: [PATCH 333/336] Use GetBlockTime() more --- src/checkpoints.cpp | 2 +- src/main.cpp | 8 ++++---- src/pow.cpp | 2 +- src/qt/clientmodel.cpp | 2 +- src/rpcdump.cpp | 6 +++--- src/rpcmining.cpp | 2 +- src/rpcrawtransaction.cpp | 4 ++-- src/rpcwallet.cpp | 2 +- src/wallet.cpp | 10 +++++----- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 80479b47fb..4cab11db3d 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -127,7 +127,7 @@ namespace Checkpoints { } else { double nCheapBefore = data.nTransactionsLastCheckpoint; double nExpensiveBefore = pindex->nChainTx - data.nTransactionsLastCheckpoint; - double nExpensiveAfter = (nNow - pindex->nTime)/86400.0*data.fTransactionsPerDay; + double nExpensiveAfter = (nNow - pindex->GetBlockTime())/86400.0*data.fTransactionsPerDay; fWorkBefore = nCheapBefore + nExpensiveBefore*fSigcheckVerificationFactor; fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor; } diff --git a/src/main.cpp b/src/main.cpp index e08b794184..4bc6e8e38d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1788,7 +1788,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C // BIP16 didn't become active until Apr 1 2012 int64_t nBIP16SwitchTime = 1333238400; - bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime); + bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime); unsigned int flags = SCRIPT_VERIFY_NOCACHE | (fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); @@ -2437,7 +2437,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) { // Extra checks to prevent "fill up memory by spamming with bogus blocks" - int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime; + int64_t deltaTime = block.GetBlockTime() - pcheckpoint->GetBlockTime(); if (deltaTime < 0) { return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), @@ -2548,7 +2548,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos blockPos; if (dbp != NULL) blockPos = *dbp; - if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.nTime, dbp != NULL)) + if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != NULL)) return error("AcceptBlock() : FindBlockPos failed"); if (dbp == NULL) if (!WriteBlockToDisk(block, blockPos)) @@ -3146,7 +3146,7 @@ bool InitBlockIndex() { unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); CDiskBlockPos blockPos; CValidationState state; - if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.nTime)) + if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime())) return error("LoadBlockIndex() : FindBlockPos failed"); if (!WriteBlockToDisk(block, blockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); diff --git a/src/pow.cpp b/src/pow.cpp index 952250decd..c0d0a7ca20 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -26,7 +26,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. - if (pblock->nTime > pindexLast->nTime + Params().TargetSpacing()*2) + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + Params().TargetSpacing()*2) return nProofOfWorkLimit; else { diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 9c9565be67..4c21eb5594 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -85,7 +85,7 @@ QDateTime ClientModel::getLastBlockDate() const if (chainActive.Tip()) return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); else - return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network + return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network } double ClientModel::getVerificationProgress() const diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 593e0d2b6b..d20bfcf095 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -157,7 +157,7 @@ Value importwallet(const Array& params, bool fHelp) if (!file.is_open()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); - int64_t nTimeBegin = chainActive.Tip()->nTime; + int64_t nTimeBegin = chainActive.Tip()->GetBlockTime(); bool fGood = true; @@ -215,7 +215,7 @@ Value importwallet(const Array& params, bool fHelp) pwalletMain->ShowProgress("", 100); // hide progress dialog in GUI CBlockIndex *pindex = chainActive.Tip(); - while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200) + while (pindex && pindex->pprev && pindex->GetBlockTime() > nTimeBegin - 7200) pindex = pindex->pprev; if (!pwalletMain->nTimeFirstKey || nTimeBegin < pwalletMain->nTimeFirstKey) @@ -301,7 +301,7 @@ Value dumpwallet(const Array& params, bool fHelp) file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); - file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->nTime)); + file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); file << "\n"; for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { const CKeyID &keyid = it->second; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index db60ef3592..c7621dc137 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -442,7 +442,7 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("noncerange", "00000000ffffffff")); result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); - result.push_back(Pair("curtime", (int64_t)pblock->nTime)); + result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 9771f8e685..45a227d1dc 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -99,8 +99,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) if (chainActive.Contains(pindex)) { entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); - entry.push_back(Pair("time", (int64_t)pindex->nTime)); - entry.push_back(Pair("blocktime", (int64_t)pindex->nTime)); + entry.push_back(Pair("time", pindex->GetBlockTime())); + entry.push_back(Pair("blocktime", pindex->GetBlockTime())); } else entry.push_back(Pair("confirmations", 0)); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 38e96133b4..6fd46fdcc5 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -50,7 +50,7 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); - entry.push_back(Pair("blocktime", (int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); + entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime())); } uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); diff --git a/src/wallet.cpp b/src/wallet.cpp index 318a1388d2..14235f310b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -515,8 +515,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) { if (mapBlockIndex.count(wtxIn.hashBlock)) { - unsigned int latestNow = wtx.nTimeReceived; - unsigned int latestEntry = 0; + int64_t latestNow = wtx.nTimeReceived; + int64_t latestEntry = 0; { // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future int64_t latestTolerated = latestNow + 300; @@ -547,7 +547,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet) } } - unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime; + int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime(); wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); } else @@ -889,7 +889,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) // no need to read and scan block, if block was created before // our wallet birthday (as adjusted for block time variability) - while (pindex && nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) + while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200))) pindex = chainActive.Next(pindex); ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup @@ -2092,7 +2092,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { // Extract block timestamps for those keys for (std::map::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++) - mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off + mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off } bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value) From 18c7ba8d999a9e6adf16b0a71f05acce66e9ae15 Mon Sep 17 00:00:00 2001 From: Michael Ford Date: Mon, 7 Jul 2014 16:32:38 +0800 Subject: [PATCH 334/336] Add translation mailing list to README.md Link to the new translation mailing list from README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c2fe12f3a..081af80dcf 100644 --- a/README.md +++ b/README.md @@ -76,12 +76,14 @@ Translations Changes to translations as well as new translations can be submitted to [Bitcoin Core's Transifex page](https://www.transifex.com/projects/p/bitcoin/). -Periodically the translations are pulled from Transifex and merged into the git repository. See the +Translations are periodically pulled from Transifex and merged into the git repository. See the [translation process](doc/translation_process.md) for details on how this works. -**Important**: We do not accept translation changes as github pull request because the next +**Important**: We do not accept translation changes as GitHub pull requests because the next pull from Transifex would automatically overwrite them again. +Translators should also subscribe to the [mailing list](https://groups.google.com/forum/#!forum/bitcoin-translators). + Development tips and tricks --------------------------- From afe380ef0f1c70185fc7c50e1a75e589ff3382dd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 7 Jul 2014 10:44:30 +0200 Subject: [PATCH 335/336] Fix the build for windows Problem introduced in caf6150. Thanks to @drak for noticing. Fixes #4473. --- src/netbase.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 2567c4c780..175406322a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -7,10 +7,6 @@ #include "bitcoin-config.h" #endif -#ifdef HAVE_INET_PTON -#include -#endif - #ifdef HAVE_GETADDRINFO_A #include #endif @@ -23,6 +19,9 @@ #include "util.h" #ifndef WIN32 +#if HAVE_INET_PTON +#include +#endif #include #endif From 2227725fcb68cf70bc3b33e68d4288df6c4a219a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 7 Jul 2014 15:42:59 +0000 Subject: [PATCH 336/336] test/bloom_tests: Use UL suffix for unsigned long number to ensure compatibility --- src/test/bloom_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 5c6c7d8588..2cdafa4bdd 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize) BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak) { // Same test as bloom_create_insert_serialize, but we add a nTweak of 100 - CBloomFilter filter(3, 0.01, 2147483649, BLOOM_UPDATE_ALL); + CBloomFilter filter(3, 0.01, 2147483649UL, BLOOM_UPDATE_ALL); filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")); BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");