Changeset View
Changeset View
Standalone View
Standalone View
src/test/blockencodings_tests.cpp
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | static CBlock BuildBlockTestCase() { | ||||
const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); | const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); | ||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, params)) { | while (!CheckProofOfWork(block.GetHash(), block.nBits, params)) { | ||||
++block.nNonce; | ++block.nNonce; | ||||
} | } | ||||
return block; | return block; | ||||
} | } | ||||
// BOOST_CHECK_EXCEPTION predicates to check the exception message | |||||
class HasReason { | |||||
public: | |||||
HasReason(const std::string &reason) : m_reason(reason) {} | |||||
bool operator()(const std::exception &e) const { | |||||
return std::string(e.what()).find(m_reason) != std::string::npos; | |||||
}; | |||||
private: | |||||
const std::string m_reason; | |||||
}; | |||||
// Number of shared use_counts we expect for a tx we haven't touched | // Number of shared use_counts we expect for a tx we haven't touched | ||||
// (block + mempool + our copy from the GetSharedTx call) | // (block + mempool + our copy from the GetSharedTx call) | ||||
constexpr long SHARED_TX_OFFSET{3}; | constexpr long SHARED_TX_OFFSET{3}; | ||||
BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) { | BOOST_AUTO_TEST_CASE(SimpleRoundTripTest) { | ||||
CTxMemPool pool; | CTxMemPool pool; | ||||
TestMemPoolEntryHelper entry; | TestMemPoolEntryHelper entry; | ||||
CBlock block(BuildBlockTestCase()); | CBlock block(BuildBlockTestCase()); | ||||
▲ Show 20 Lines • Show All 333 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { | ||||
BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString()); | BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString()); | ||||
BOOST_CHECK_EQUAL(req1.indices.size(), req2.indices.size()); | BOOST_CHECK_EQUAL(req1.indices.size(), req2.indices.size()); | ||||
BOOST_CHECK_EQUAL(req1.indices[0], req2.indices[0]); | BOOST_CHECK_EQUAL(req1.indices[0], req2.indices[0]); | ||||
BOOST_CHECK_EQUAL(req1.indices[1], req2.indices[1]); | BOOST_CHECK_EQUAL(req1.indices[1], req2.indices[1]); | ||||
BOOST_CHECK_EQUAL(req1.indices[2], req2.indices[2]); | BOOST_CHECK_EQUAL(req1.indices[2], req2.indices[2]); | ||||
BOOST_CHECK_EQUAL(req1.indices[3], req2.indices[3]); | BOOST_CHECK_EQUAL(req1.indices[3], req2.indices[3]); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) { | |||||
// Check that the highest legal index is decoded correctly | |||||
BlockTransactionsRequest req0; | |||||
req0.blockhash = BlockHash(InsecureRand256()); | |||||
req0.indices.resize(1); | |||||
using indiceType = decltype(req0.indices)::value_type; | |||||
jasonbcox: Nit: the plurality here is weird. should be `indexType` or `indicesType`, of which the latter… | |||||
FabienAuthorUnsubmitted Done Inline ActionsThis is the type of an element of the vector of indices, so I think indiceType is correct. Fabien: This is the type of an element of the vector of indices, so I think `indiceType` is correct. | |||||
static_assert(MAX_SIZE < std::numeric_limits<indiceType>::max(), | |||||
"The max payload size cannot fit into the indice type"); | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsThis isn't the first place I would put this check (somewhere near the definition seems more natural to me), but I'm not able to put my finger on a strong objective reasoning for this. jasonbcox: This isn't the first place I would put this check (somewhere near the definition seems more… | |||||
FabienAuthorUnsubmitted Done Inline ActionsI'm not sure this assertion should hold as a general case. If one day we raise MAX_SIZE to something larger, I'm make sure that this test will fail and will need to be updated. I'm not sure that the code will fail, only this test (and eventually the next one). Fabien: I'm not sure this assertion should hold as a general case. If one day we raise MAX_SIZE to… | |||||
req0.indices[0] = MAX_SIZE; | |||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); | |||||
stream << req0; | |||||
BlockTransactionsRequest req1; | |||||
stream >> req1; | |||||
BOOST_CHECK_EQUAL(req0.indices.size(), req1.indices.size()); | |||||
BOOST_CHECK_EQUAL(req0.indices[0], req1.indices[0]); | |||||
req0.indices[0] += 1; | |||||
stream << req0; | |||||
BlockTransactionsRequest req2; | |||||
BOOST_CHECK_EXCEPTION(stream >> req2, std::ios_base::failure, | |||||
HasReason("ReadCompactSize(): size too large")); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) { | |||||
// Any set of index deltas that starts with N values that sum to | |||||
// (0x100000000 - N) causes the edge-case overflow that was originally not | |||||
// checked for. Such a request cannot be created by serializing a real | |||||
// BlockTransactionsRequest due to the overflow, so here we'll serialize | |||||
// from raw deltas. This can only occur if MAX_SIZE is greater than the | |||||
// maximum value for that the indice type can handle. | |||||
BlockTransactionsRequest req0; | |||||
req0.blockhash = BlockHash(InsecureRand256()); | |||||
req0.indices.resize(3); | |||||
using indiceType = decltype(req0.indices)::value_type; | |||||
jasonbcoxUnsubmitted Not Done Inline Actionsditto jasonbcox: ditto | |||||
FabienAuthorUnsubmitted Done Inline ActionsDitto :) Fabien: Ditto :) | |||||
static_assert(std::is_same<indiceType, uint32_t>::value, | |||||
"This test expects the indice type to be an uint32_t"); | |||||
req0.indices[0] = 0x7000; | |||||
req0.indices[1] = 0x100000000 - 0x7000 - 2; | |||||
req0.indices[2] = 0; | |||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); | |||||
stream << req0.blockhash; | |||||
WriteCompactSize(stream, req0.indices.size()); | |||||
WriteCompactSize(stream, req0.indices[0]); | |||||
WriteCompactSize(stream, req0.indices[1]); | |||||
WriteCompactSize(stream, req0.indices[2]); | |||||
BlockTransactionsRequest req1; | |||||
// If MAX_SIZE is the limiting factor, the deserialization should throw. | |||||
// Otherwise make sure that the overflow edge-case is under control. | |||||
BOOST_CHECK_EXCEPTION(stream >> req1, std::ios_base::failure, | |||||
HasReason((MAX_SIZE < req0.indices[1]) | |||||
? "ReadCompactSize(): size too large" | |||||
: "indices overflowed 32 bits")); | |||||
jasonbcoxUnsubmitted Not Done Inline Actionsjasonbcox: {meme, src=likestamp}
| |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |
Nit: the plurality here is weird. should be indexType or indicesType, of which the latter is probably more correct.