diff options
-rw-r--r-- | doc/translation_process.md | 2 | ||||
-rwxr-xr-x | qa/rpc-tests/p2p-segwit.py | 18 | ||||
-rw-r--r-- | src/main.cpp | 20 | ||||
-rw-r--r-- | src/test/arith_uint256_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/prevector_tests.cpp | 62 |
5 files changed, 74 insertions, 30 deletions
diff --git a/doc/translation_process.md b/doc/translation_process.md index d8a85292e8..a443a16fe2 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -94,7 +94,7 @@ When new plurals are added to the source file, it's important to do the followin 7. Save the source file ### Translating a new language -To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the English language entry. +To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin_locale.qrc` and add a new entry. Below is an example of the English language entry. ```xml <qresource prefix="/translations"> diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index eb857ed983..ca784644d8 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -964,8 +964,24 @@ class SegWitTest(BitcoinTestFramework): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) - tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))) tx3.wit.vtxinwit.append(CTxInWitness()) + + # Add too-large for IsStandard witness and check that it does not enter reject filter + p2sh_program = CScript([OP_TRUE]) + p2sh_pubkey = hash160(p2sh_program) + witness_program2 = CScript([b'a'*400000]) + tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]))) + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program2] + tx3.rehash() + + # Node will not be blinded to the transaction + self.std_node.announce_tx_and_wait_for_getdata(tx3) + self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + self.std_node.announce_tx_and_wait_for_getdata(tx3) + self.std_node.test_transaction_acceptance(tx3, True, False, b'tx-size') + + # Remove witness stuffing, instead add extra witness push on stack + tx3.vout[0] = CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE])) tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ] tx3.rehash() diff --git a/src/main.cpp b/src/main.cpp index 4b42afb561..2c98de070a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1501,9 +1501,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && + if (tx.wit.IsNull() && CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) { - // Only the witness is wrong, so the transaction itself may be fine. + // Only the witness is missing, so the transaction itself may be fine. state.SetCorruptionPossible(); } return false; @@ -5493,7 +5493,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (!fMissingInputs2) { int nDos = 0; - if (stateDummy.IsInvalid(nDos) && nDos > 0 && (!state.CorruptionPossible() || State(fromPeer)->fHaveWitness)) + if (stateDummy.IsInvalid(nDos) && nDos > 0) { // Punish peer that gave us an invalid orphan tx Misbehaving(fromPeer, nDos); @@ -5504,7 +5504,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Probably non-standard or insufficient fee/priority LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); vEraseQueue.push_back(orphanHash); - if (!stateDummy.CorruptionPossible()) { + if (orphanTx.wit.IsNull() && !stateDummy.CorruptionPossible()) { + // Do not use rejection cache for witness transactions or + // witness-stripped transactions, as they can have been malleated. + // See https://github.com/bitcoin/bitcoin/issues/8279 for details. assert(recentRejects); recentRejects->insert(orphanHash); } @@ -5542,7 +5545,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); } } else { - if (!state.CorruptionPossible()) { + if (tx.wit.IsNull() && !state.CorruptionPossible()) { + // Do not use rejection cache for witness transactions or + // witness-stripped transactions, as they can have been malleated. + // See https://github.com/bitcoin/bitcoin/issues/8279 for details. assert(recentRejects); recentRejects->insert(tx.GetHash()); } @@ -5574,9 +5580,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); - if (nDoS > 0 && (!state.CorruptionPossible() || State(pfrom->id)->fHaveWitness)) { - // When a non-witness-supporting peer gives us a transaction that would - // be accepted if witness validation was off, we can't blame them for it. + if (nDoS > 0) { Misbehaving(pfrom->GetId(), nDoS); } } diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 53ab7e95ee..b19d2faea0 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -112,7 +112,7 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality BOOST_CHECK( (R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64)); BOOST_CHECK(ZeroL == arith_uint256(0)); BOOST_CHECK(OneL == arith_uint256(1)); - BOOST_CHECK(arith_uint256("0xffffffffffffffff") = arith_uint256(0xffffffffffffffffULL)); + BOOST_CHECK(arith_uint256("0xffffffffffffffff") == arith_uint256(0xffffffffffffffffULL)); // Assignment (from base_uint) arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index d1407c1da9..b8c45ca564 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -26,57 +26,70 @@ class prevector_tester { pretype pre_vector_alt; typedef typename pretype::size_type Size; + bool passed = true; + uint32_t insecure_rand_Rz_cache; + uint32_t insecure_rand_Rw_cache; + + template <typename A, typename B> + void local_check_equal(A a, B b) + { + local_check(a == b); + } + void local_check(bool b) + { + passed &= b; + } void test() { const pretype& const_pre_vector = pre_vector; - BOOST_CHECK_EQUAL(real_vector.size(), pre_vector.size()); - BOOST_CHECK_EQUAL(real_vector.empty(), pre_vector.empty()); + local_check_equal(real_vector.size(), pre_vector.size()); + local_check_equal(real_vector.empty(), pre_vector.empty()); for (Size s = 0; s < real_vector.size(); s++) { - BOOST_CHECK(real_vector[s] == pre_vector[s]); - BOOST_CHECK(&(pre_vector[s]) == &(pre_vector.begin()[s])); - BOOST_CHECK(&(pre_vector[s]) == &*(pre_vector.begin() + s)); - BOOST_CHECK(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size())); + local_check(real_vector[s] == pre_vector[s]); + local_check(&(pre_vector[s]) == &(pre_vector.begin()[s])); + local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s)); + local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size())); } - // BOOST_CHECK(realtype(pre_vector) == real_vector); - BOOST_CHECK(pretype(real_vector.begin(), real_vector.end()) == pre_vector); - BOOST_CHECK(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); + // local_check(realtype(pre_vector) == real_vector); + local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector); + local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); size_t pos = 0; BOOST_FOREACH(const T& v, pre_vector) { - BOOST_CHECK(v == real_vector[pos++]); + local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, pre_vector) { - BOOST_CHECK(v == real_vector[--pos]); + local_check(v == real_vector[--pos]); } BOOST_FOREACH(const T& v, const_pre_vector) { - BOOST_CHECK(v == real_vector[pos++]); + local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, const_pre_vector) { - BOOST_CHECK(v == real_vector[--pos]); + local_check(v == real_vector[--pos]); } CDataStream ss1(SER_DISK, 0); CDataStream ss2(SER_DISK, 0); ss1 << real_vector; ss2 << pre_vector; - BOOST_CHECK_EQUAL(ss1.size(), ss2.size()); + local_check_equal(ss1.size(), ss2.size()); for (Size s = 0; s < ss1.size(); s++) { - BOOST_CHECK_EQUAL(ss1[s], ss2[s]); + local_check_equal(ss1[s], ss2[s]); } } public: void resize(Size s) { real_vector.resize(s); - BOOST_CHECK_EQUAL(real_vector.size(), s); + local_check_equal(real_vector.size(), s); pre_vector.resize(s); - BOOST_CHECK_EQUAL(pre_vector.size(), s); + local_check_equal(pre_vector.size(), s); test(); } void reserve(Size s) { real_vector.reserve(s); - BOOST_CHECK(real_vector.capacity() >= s); + local_check(real_vector.capacity() >= s); pre_vector.reserve(s); - BOOST_CHECK(pre_vector.capacity() >= s); + local_check(pre_vector.capacity() >= s); test(); } @@ -157,6 +170,17 @@ public: pre_vector.swap(pre_vector_alt); test(); } + ~prevector_tester() { + BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " + << insecure_rand_Rz_cache + << ", insecure_rand_Rw: " + << insecure_rand_Rw_cache); + } + prevector_tester() { + seed_insecure_rand(); + insecure_rand_Rz_cache = insecure_rand_Rz; + insecure_rand_Rw_cache = insecure_rand_Rw; + } }; BOOST_AUTO_TEST_CASE(PrevectorTestInt) |