2019-04-11 09:53:04 -04:00
// Copyright (c) 2011-2019 The Bitcoin Core developers
2016-04-25 19:51:08 -03:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-09 21:57:53 -03:00
# include <blockencodings.h>
# include <chainparams.h>
2019-09-24 12:23:19 -03:00
# include <consensus/merkle.h>
2018-05-14 02:39:53 -04:00
# include <pow.h>
2019-06-24 11:22:28 -04:00
# include <streams.h>
2016-04-25 19:51:08 -03:00
2019-11-05 17:18:59 -03:00
# include <test/util/setup_common.h>
2016-04-25 19:51:08 -03:00
# include <boost/test/unit_test.hpp>
2016-12-05 01:44:37 -03:00
std : : vector < std : : pair < uint256 , CTransactionRef > > extra_txn ;
2019-09-24 12:23:19 -03:00
BOOST_FIXTURE_TEST_SUITE ( blockencodings_tests , RegTestingSetup )
2016-04-25 19:51:08 -03:00
static CBlock BuildBlockTestCase ( ) {
CBlock block ;
CMutableTransaction tx ;
tx . vin . resize ( 1 ) ;
tx . vin [ 0 ] . scriptSig . resize ( 10 ) ;
tx . vout . resize ( 1 ) ;
tx . vout [ 0 ] . nValue = 42 ;
block . vtx . resize ( 3 ) ;
2016-11-10 22:34:17 -03:00
block . vtx [ 0 ] = MakeTransactionRef ( tx ) ;
2016-04-25 19:51:08 -03:00
block . nVersion = 42 ;
2017-06-07 15:03:17 -04:00
block . hashPrevBlock = InsecureRand256 ( ) ;
2016-04-25 19:51:08 -03:00
block . nBits = 0x207fffff ;
2017-06-07 15:03:17 -04:00
tx . vin [ 0 ] . prevout . hash = InsecureRand256 ( ) ;
2016-04-25 19:51:08 -03:00
tx . vin [ 0 ] . prevout . n = 0 ;
2016-11-10 22:34:17 -03:00
block . vtx [ 1 ] = MakeTransactionRef ( tx ) ;
2016-04-25 19:51:08 -03:00
tx . vin . resize ( 10 ) ;
for ( size_t i = 0 ; i < tx . vin . size ( ) ; i + + ) {
2017-06-07 15:03:17 -04:00
tx . vin [ i ] . prevout . hash = InsecureRand256 ( ) ;
2016-04-25 19:51:08 -03:00
tx . vin [ i ] . prevout . n = 0 ;
}
2016-11-10 22:34:17 -03:00
block . vtx [ 2 ] = MakeTransactionRef ( tx ) ;
2016-04-25 19:51:08 -03:00
bool mutated ;
block . hashMerkleRoot = BlockMerkleRoot ( block , & mutated ) ;
assert ( ! mutated ) ;
while ( ! CheckProofOfWork ( block . GetHash ( ) , block . nBits , Params ( ) . GetConsensus ( ) ) ) + + block . nNonce ;
return block ;
}
2017-08-15 19:24:39 -03:00
// Number of shared use_counts we expect for a tx we haven't touched
2018-04-11 14:51:28 -03:00
// (block + mempool + our copy from the GetSharedTx call)
constexpr long SHARED_TX_OFFSET { 3 } ;
2016-04-25 19:51:08 -03:00
BOOST_AUTO_TEST_CASE ( SimpleRoundTripTest )
{
2017-01-13 18:53:21 -03:00
CTxMemPool pool ;
2016-04-25 19:51:08 -03:00
TestMemPoolEntryHelper entry ;
CBlock block ( BuildBlockTestCase ( ) ) ;
2018-12-17 16:27:43 -03:00
LOCK2 ( cs_main , pool . cs ) ;
2018-07-30 09:11:13 -04:00
pool . addUnchecked ( entry . FromTx ( block . vtx [ 2 ] ) ) ;
2016-11-10 22:26:00 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 0 ) ;
2016-04-25 19:51:08 -03:00
// Do a simple ShortTxIDs RT
{
2016-06-25 13:17:45 -04:00
CBlockHeaderAndShortTxIDs shortIDs ( block , true ) ;
2016-04-25 19:51:08 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < shortIDs ;
CBlockHeaderAndShortTxIDs shortIDs2 ;
stream > > shortIDs2 ;
PartiallyDownloadedBlock partialBlock ( & pool ) ;
2016-12-05 01:44:37 -03:00
BOOST_CHECK ( partialBlock . InitData ( shortIDs2 , extra_txn ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK ( partialBlock . IsTxAvailable ( 0 ) ) ;
BOOST_CHECK ( ! partialBlock . IsTxAvailable ( 1 ) ) ;
BOOST_CHECK ( partialBlock . IsTxAvailable ( 2 ) ) ;
2016-11-10 22:26:00 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 1 ) ;
2016-04-25 19:51:08 -03:00
2016-11-29 19:51:26 -03:00
size_t poolSize = pool . size ( ) ;
2019-07-22 07:42:01 -04:00
pool . removeRecursive ( * block . vtx [ 2 ] , MemPoolRemovalReason : : REPLACED ) ;
2016-11-29 19:51:26 -03:00
BOOST_CHECK_EQUAL ( pool . size ( ) , poolSize - 1 ) ;
2016-04-25 19:51:08 -03:00
CBlock block2 ;
2016-11-11 18:01:27 -03:00
{
PartiallyDownloadedBlock tmp = partialBlock ;
BOOST_CHECK ( partialBlock . FillBlock ( block2 , { } ) = = READ_STATUS_INVALID ) ; // No transactions
partialBlock = tmp ;
}
2016-04-25 19:51:08 -03:00
2016-11-11 18:01:27 -03:00
// Wrong transaction
{
PartiallyDownloadedBlock tmp = partialBlock ;
partialBlock . FillBlock ( block2 , { block . vtx [ 2 ] } ) ; // Current implementation doesn't check txn here, but don't require that
partialBlock = tmp ;
}
2016-04-25 19:51:08 -03:00
bool mutated ;
BOOST_CHECK ( block . hashMerkleRoot ! = BlockMerkleRoot ( block2 , & mutated ) ) ;
CBlock block3 ;
2016-11-11 18:01:27 -03:00
BOOST_CHECK ( partialBlock . FillBlock ( block3 , { block . vtx [ 1 ] } ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK_EQUAL ( block . GetHash ( ) . ToString ( ) , block3 . GetHash ( ) . ToString ( ) ) ;
BOOST_CHECK_EQUAL ( block . hashMerkleRoot . ToString ( ) , BlockMerkleRoot ( block3 , & mutated ) . ToString ( ) ) ;
BOOST_CHECK ( ! mutated ) ;
}
}
class TestHeaderAndShortIDs {
// Utility to encode custom CBlockHeaderAndShortTxIDs
public :
CBlockHeader header ;
uint64_t nonce ;
std : : vector < uint64_t > shorttxids ;
std : : vector < PrefilledTransaction > prefilledtxn ;
2017-08-01 06:22:41 -04:00
explicit TestHeaderAndShortIDs ( const CBlockHeaderAndShortTxIDs & orig ) {
2016-04-25 19:51:08 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < orig ;
stream > > * this ;
}
2017-08-01 06:22:41 -04:00
explicit TestHeaderAndShortIDs ( const CBlock & block ) :
2016-06-25 13:17:45 -04:00
TestHeaderAndShortIDs ( CBlockHeaderAndShortTxIDs ( block , true ) ) { }
2016-04-25 19:51:08 -03:00
uint64_t GetShortID ( const uint256 & txhash ) const {
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < * this ;
CBlockHeaderAndShortTxIDs base ;
stream > > base ;
return base . GetShortID ( txhash ) ;
}
ADD_SERIALIZE_METHODS ;
template < typename Stream , typename Operation >
2016-10-28 20:29:17 -03:00
inline void SerializationOp ( Stream & s , Operation ser_action ) {
2016-04-25 19:51:08 -03:00
READWRITE ( header ) ;
READWRITE ( nonce ) ;
size_t shorttxids_size = shorttxids . size ( ) ;
READWRITE ( VARINT ( shorttxids_size ) ) ;
shorttxids . resize ( shorttxids_size ) ;
for ( size_t i = 0 ; i < shorttxids . size ( ) ; i + + ) {
uint32_t lsb = shorttxids [ i ] & 0xffffffff ;
uint16_t msb = ( shorttxids [ i ] > > 32 ) & 0xffff ;
READWRITE ( lsb ) ;
READWRITE ( msb ) ;
shorttxids [ i ] = ( uint64_t ( msb ) < < 32 ) | uint64_t ( lsb ) ;
}
READWRITE ( prefilledtxn ) ;
}
} ;
BOOST_AUTO_TEST_CASE ( NonCoinbasePreforwardRTTest )
{
2017-01-13 18:53:21 -03:00
CTxMemPool pool ;
2016-04-25 19:51:08 -03:00
TestMemPoolEntryHelper entry ;
CBlock block ( BuildBlockTestCase ( ) ) ;
2018-12-17 16:27:43 -03:00
LOCK2 ( cs_main , pool . cs ) ;
2018-07-30 09:11:13 -04:00
pool . addUnchecked ( entry . FromTx ( block . vtx [ 2 ] ) ) ;
2016-11-10 22:26:00 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 0 ) ;
uint256 txhash ;
2016-04-25 19:51:08 -03:00
// Test with pre-forwarding tx 1, but not coinbase
{
TestHeaderAndShortIDs shortIDs ( block ) ;
shortIDs . prefilledtxn . resize ( 1 ) ;
shortIDs . prefilledtxn [ 0 ] = { 1 , block . vtx [ 1 ] } ;
shortIDs . shorttxids . resize ( 2 ) ;
2016-11-10 22:26:00 -03:00
shortIDs . shorttxids [ 0 ] = shortIDs . GetShortID ( block . vtx [ 0 ] - > GetHash ( ) ) ;
shortIDs . shorttxids [ 1 ] = shortIDs . GetShortID ( block . vtx [ 2 ] - > GetHash ( ) ) ;
2016-04-25 19:51:08 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < shortIDs ;
CBlockHeaderAndShortTxIDs shortIDs2 ;
stream > > shortIDs2 ;
PartiallyDownloadedBlock partialBlock ( & pool ) ;
2016-12-05 01:44:37 -03:00
BOOST_CHECK ( partialBlock . InitData ( shortIDs2 , extra_txn ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK ( ! partialBlock . IsTxAvailable ( 0 ) ) ;
BOOST_CHECK ( partialBlock . IsTxAvailable ( 1 ) ) ;
BOOST_CHECK ( partialBlock . IsTxAvailable ( 2 ) ) ;
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 1 ) ; // +1 because of partialBlock
2016-04-25 19:51:08 -03:00
CBlock block2 ;
2016-11-11 18:01:27 -03:00
{
PartiallyDownloadedBlock tmp = partialBlock ;
BOOST_CHECK ( partialBlock . FillBlock ( block2 , { } ) = = READ_STATUS_INVALID ) ; // No transactions
partialBlock = tmp ;
}
2016-04-25 19:51:08 -03:00
2016-11-11 18:01:27 -03:00
// Wrong transaction
{
PartiallyDownloadedBlock tmp = partialBlock ;
partialBlock . FillBlock ( block2 , { block . vtx [ 1 ] } ) ; // Current implementation doesn't check txn here, but don't require that
partialBlock = tmp ;
}
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 2 ) ; // +2 because of partialBlock and block2
2016-04-25 19:51:08 -03:00
bool mutated ;
BOOST_CHECK ( block . hashMerkleRoot ! = BlockMerkleRoot ( block2 , & mutated ) ) ;
CBlock block3 ;
2016-11-11 18:01:27 -03:00
PartiallyDownloadedBlock partialBlockCopy = partialBlock ;
BOOST_CHECK ( partialBlock . FillBlock ( block3 , { block . vtx [ 0 ] } ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK_EQUAL ( block . GetHash ( ) . ToString ( ) , block3 . GetHash ( ) . ToString ( ) ) ;
BOOST_CHECK_EQUAL ( block . hashMerkleRoot . ToString ( ) , BlockMerkleRoot ( block3 , & mutated ) . ToString ( ) ) ;
BOOST_CHECK ( ! mutated ) ;
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 2 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 3 ) ; // +2 because of partialBlock and block2 and block3
2016-11-10 22:26:00 -03:00
txhash = block . vtx [ 2 ] - > GetHash ( ) ;
block . vtx . clear ( ) ;
block2 . vtx . clear ( ) ;
block3 . vtx . clear ( ) ;
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( txhash ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 1 - 1 ) ; // + 1 because of partialBlock; -1 because of block.
2016-04-25 19:51:08 -03:00
}
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( txhash ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET - 1 ) ; // -1 because of block
2016-04-25 19:51:08 -03:00
}
BOOST_AUTO_TEST_CASE ( SufficientPreforwardRTTest )
{
2017-01-13 18:53:21 -03:00
CTxMemPool pool ;
2016-04-25 19:51:08 -03:00
TestMemPoolEntryHelper entry ;
CBlock block ( BuildBlockTestCase ( ) ) ;
2018-12-17 16:27:43 -03:00
LOCK2 ( cs_main , pool . cs ) ;
2018-07-30 09:11:13 -04:00
pool . addUnchecked ( entry . FromTx ( block . vtx [ 1 ] ) ) ;
2016-11-10 22:26:00 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 1 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 0 ) ;
uint256 txhash ;
2016-04-25 19:51:08 -03:00
// Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
{
TestHeaderAndShortIDs shortIDs ( block ) ;
shortIDs . prefilledtxn . resize ( 2 ) ;
shortIDs . prefilledtxn [ 0 ] = { 0 , block . vtx [ 0 ] } ;
shortIDs . prefilledtxn [ 1 ] = { 1 , block . vtx [ 2 ] } ; // id == 1 as it is 1 after index 1
shortIDs . shorttxids . resize ( 1 ) ;
2016-11-10 22:26:00 -03:00
shortIDs . shorttxids [ 0 ] = shortIDs . GetShortID ( block . vtx [ 1 ] - > GetHash ( ) ) ;
2016-04-25 19:51:08 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < shortIDs ;
CBlockHeaderAndShortTxIDs shortIDs2 ;
stream > > shortIDs2 ;
PartiallyDownloadedBlock partialBlock ( & pool ) ;
2016-12-05 01:44:37 -03:00
BOOST_CHECK ( partialBlock . InitData ( shortIDs2 , extra_txn ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK ( partialBlock . IsTxAvailable ( 0 ) ) ;
BOOST_CHECK ( partialBlock . IsTxAvailable ( 1 ) ) ;
BOOST_CHECK ( partialBlock . IsTxAvailable ( 2 ) ) ;
2016-11-10 22:26:00 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( block . vtx [ 1 ] - > GetHash ( ) ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 1 ) ;
2016-04-25 19:51:08 -03:00
CBlock block2 ;
2016-11-11 18:01:27 -03:00
PartiallyDownloadedBlock partialBlockCopy = partialBlock ;
BOOST_CHECK ( partialBlock . FillBlock ( block2 , { } ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK_EQUAL ( block . GetHash ( ) . ToString ( ) , block2 . GetHash ( ) . ToString ( ) ) ;
bool mutated ;
BOOST_CHECK_EQUAL ( block . hashMerkleRoot . ToString ( ) , BlockMerkleRoot ( block2 , & mutated ) . ToString ( ) ) ;
BOOST_CHECK ( ! mutated ) ;
2016-11-10 22:26:00 -03:00
txhash = block . vtx [ 1 ] - > GetHash ( ) ;
block . vtx . clear ( ) ;
block2 . vtx . clear ( ) ;
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( txhash ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET + 1 - 1 ) ; // + 1 because of partialBlock; -1 because of block.
2016-04-25 19:51:08 -03:00
}
2018-04-11 14:51:28 -03:00
BOOST_CHECK_EQUAL ( pool . mapTx . find ( txhash ) - > GetSharedTx ( ) . use_count ( ) , SHARED_TX_OFFSET - 1 ) ; // -1 because of block
2016-04-25 19:51:08 -03:00
}
BOOST_AUTO_TEST_CASE ( EmptyBlockRoundTripTest )
{
2017-01-13 18:53:21 -03:00
CTxMemPool pool ;
2016-04-25 19:51:08 -03:00
CMutableTransaction coinbase ;
coinbase . vin . resize ( 1 ) ;
coinbase . vin [ 0 ] . scriptSig . resize ( 10 ) ;
coinbase . vout . resize ( 1 ) ;
coinbase . vout [ 0 ] . nValue = 42 ;
CBlock block ;
block . vtx . resize ( 1 ) ;
2016-11-10 22:34:17 -03:00
block . vtx [ 0 ] = MakeTransactionRef ( std : : move ( coinbase ) ) ;
2016-04-25 19:51:08 -03:00
block . nVersion = 42 ;
2017-06-07 15:03:17 -04:00
block . hashPrevBlock = InsecureRand256 ( ) ;
2016-04-25 19:51:08 -03:00
block . nBits = 0x207fffff ;
bool mutated ;
block . hashMerkleRoot = BlockMerkleRoot ( block , & mutated ) ;
assert ( ! mutated ) ;
while ( ! CheckProofOfWork ( block . GetHash ( ) , block . nBits , Params ( ) . GetConsensus ( ) ) ) + + block . nNonce ;
// Test simple header round-trip with only coinbase
{
2016-06-25 13:17:45 -04:00
CBlockHeaderAndShortTxIDs shortIDs ( block , false ) ;
2016-04-25 19:51:08 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < shortIDs ;
CBlockHeaderAndShortTxIDs shortIDs2 ;
stream > > shortIDs2 ;
PartiallyDownloadedBlock partialBlock ( & pool ) ;
2016-12-05 01:44:37 -03:00
BOOST_CHECK ( partialBlock . InitData ( shortIDs2 , extra_txn ) = = READ_STATUS_OK ) ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK ( partialBlock . IsTxAvailable ( 0 ) ) ;
CBlock block2 ;
2016-11-10 22:34:17 -03:00
std : : vector < CTransactionRef > vtx_missing ;
2016-04-25 19:51:08 -03:00
BOOST_CHECK ( partialBlock . FillBlock ( block2 , vtx_missing ) = = READ_STATUS_OK ) ;
BOOST_CHECK_EQUAL ( block . GetHash ( ) . ToString ( ) , block2 . GetHash ( ) . ToString ( ) ) ;
BOOST_CHECK_EQUAL ( block . hashMerkleRoot . ToString ( ) , BlockMerkleRoot ( block2 , & mutated ) . ToString ( ) ) ;
BOOST_CHECK ( ! mutated ) ;
}
}
BOOST_AUTO_TEST_CASE ( TransactionsRequestSerializationTest ) {
BlockTransactionsRequest req1 ;
2017-06-07 15:03:17 -04:00
req1 . blockhash = InsecureRand256 ( ) ;
2016-04-25 19:51:08 -03:00
req1 . indexes . resize ( 4 ) ;
req1 . indexes [ 0 ] = 0 ;
req1 . indexes [ 1 ] = 1 ;
req1 . indexes [ 2 ] = 3 ;
req1 . indexes [ 3 ] = 4 ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < req1 ;
BlockTransactionsRequest req2 ;
stream > > req2 ;
BOOST_CHECK_EQUAL ( req1 . blockhash . ToString ( ) , req2 . blockhash . ToString ( ) ) ;
BOOST_CHECK_EQUAL ( req1 . indexes . size ( ) , req2 . indexes . size ( ) ) ;
BOOST_CHECK_EQUAL ( req1 . indexes [ 0 ] , req2 . indexes [ 0 ] ) ;
BOOST_CHECK_EQUAL ( req1 . indexes [ 1 ] , req2 . indexes [ 1 ] ) ;
BOOST_CHECK_EQUAL ( req1 . indexes [ 2 ] , req2 . indexes [ 2 ] ) ;
BOOST_CHECK_EQUAL ( req1 . indexes [ 3 ] , req2 . indexes [ 3 ] ) ;
}
2018-11-07 17:36:23 -03:00
BOOST_AUTO_TEST_CASE ( TransactionsRequestDeserializationMaxTest ) {
// Check that the highest legal index is decoded correctly
BlockTransactionsRequest req0 ;
req0 . blockhash = InsecureRand256 ( ) ;
req0 . indexes . resize ( 1 ) ;
req0 . indexes [ 0 ] = 0xffff ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < req0 ;
BlockTransactionsRequest req1 ;
stream > > req1 ;
BOOST_CHECK_EQUAL ( req0 . indexes . size ( ) , req1 . indexes . size ( ) ) ;
BOOST_CHECK_EQUAL ( req0 . indexes [ 0 ] , req1 . indexes [ 0 ] ) ;
}
BOOST_AUTO_TEST_CASE ( TransactionsRequestDeserializationOverflowTest ) {
// Any set of index deltas that starts with N values that sum to (0x10000 - 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.
BlockTransactionsRequest req0 ;
req0 . blockhash = InsecureRand256 ( ) ;
req0 . indexes . resize ( 3 ) ;
req0 . indexes [ 0 ] = 0x7000 ;
req0 . indexes [ 1 ] = 0x10000 - 0x7000 - 2 ;
req0 . indexes [ 2 ] = 0 ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < req0 . blockhash ;
WriteCompactSize ( stream , req0 . indexes . size ( ) ) ;
WriteCompactSize ( stream , req0 . indexes [ 0 ] ) ;
WriteCompactSize ( stream , req0 . indexes [ 1 ] ) ;
WriteCompactSize ( stream , req0 . indexes [ 2 ] ) ;
BlockTransactionsRequest req1 ;
try {
stream > > req1 ;
// before patch: deserialize above succeeds and this check fails, demonstrating the overflow
BOOST_CHECK ( req1 . indexes [ 1 ] < req1 . indexes [ 2 ] ) ;
// this shouldn't be reachable before or after patch
BOOST_CHECK ( 0 ) ;
} catch ( std : : ios_base : : failure & ) {
// deserialize should fail
2019-03-29 11:22:48 -03:00
BOOST_CHECK ( true ) ; // Needed to suppress "Test case [...] did not check any assertions"
2018-11-07 17:36:23 -03:00
}
}
2016-04-25 19:51:08 -03:00
BOOST_AUTO_TEST_SUITE_END ( )