Skip to content

Commit ba0cfe4

Browse files
committed
Daemon RPC: getblocks.bin block_ids_exclusive req param
When the request includes block_ids, the daemon uses find_blockchain_supplement to identify the highest block hash passed in block_ids that the daemon also knows about, and then serves subsequent blocks contiguous to that block. When block_ids_skip_exclusive is false (default current behavior), the daemon includes the highest block requested in the response, in addition to contiguous blocks after it. When block_ids_skip_exclusive is true (new param), the daemon serves blocks starting from the block 1 higher than the highest known block included in block_ids. Thus, the daemon skips the common block known to the client and daemon. Clients can make sure the daemon is serving expected contiguous blocks to its highest known block by checking the first block's prev_id included in the response, and making sure it is equivalent to the block the client already knows about that was included in block_ids. This avoids the daemon serving 1 extra block it does not need to serve to the client, since the client should already know about that block.
1 parent 8e9ab96 commit ba0cfe4

File tree

7 files changed

+29
-10
lines changed

7 files changed

+29
-10
lines changed

src/cryptonote_core/blockchain.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2736,17 +2736,18 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
27362736
// find split point between ours and foreign blockchain (or start at
27372737
// blockchain height <req_start_block>), and return up to max_count FULL
27382738
// blocks by reference.
2739-
bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const
2739+
bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, const bool qblock_ids_exclusive, size_t max_block_count, size_t max_tx_count) const
27402740
{
27412741
LOG_PRINT_L3("Blockchain::" << __func__);
27422742
CRITICAL_REGION_LOCAL(m_blockchain_lock);
27432743

2744+
top_hash = m_db->top_block_hash(&total_height);
2745+
++total_height;
2746+
27442747
// if a specific start height has been requested
27452748
if(req_start_block > 0)
27462749
{
27472750
// if requested height is higher than our chain, return false -- we can't help
2748-
top_hash = m_db->top_block_hash(&total_height);
2749-
++total_height;
27502751
if (req_start_block >= total_height)
27512752
{
27522753
return false;
@@ -2755,15 +2756,30 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
27552756
}
27562757
else
27572758
{
2759+
// find_blockchain_supplement's start_height is the highest block idx included in qblock_ids that's *also* in the main chain
27582760
if(!find_blockchain_supplement(qblock_ids, start_height))
27592761
{
27602762
return false;
27612763
}
2764+
if (qblock_ids_exclusive)
2765+
{
2766+
// start from 1 block higher than the first common block (i.e. from the first block the client might not know about)
2767+
++start_height;
2768+
2769+
// if start_height is now the chain tip, we can return a truthy empty resp
2770+
if (start_height == total_height)
2771+
{
2772+
LOG_PRINT_L3("Returning empty find_blockchain_supplement, start_height: " << start_height);
2773+
blocks.clear();
2774+
return true;
2775+
}
2776+
}
27622777
}
27632778

27642779
db_rtxn_guard rtxn_guard(m_db);
27652780
top_hash = m_db->top_block_hash(&total_height);
27662781
++total_height;
2782+
CHECK_AND_ASSERT_MES(total_height >= start_height, false, "chain height expected to be higher than start block");
27672783
blocks.reserve(std::min(std::min(max_block_count, (size_t)10000), (size_t)(total_height - start_height)));
27682784
CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_block_count, max_tx_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash),
27692785
false, "Error getting blocks");

src/cryptonote_core/blockchain.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,12 +504,13 @@ namespace cryptonote
504504
* @param top_hash return-by-reference top block hash
505505
* @param start_height return-by-reference the height of the first block returned
506506
* @param pruned whether to return full or pruned tx blobs
507+
* @param qblock_ids_exclusive when using qblock_ids, whether or not to include highest common block in response
507508
* @param max_block_count the max number of blocks to get
508509
* @param max_tx_count the max number of txes to get (it can get overshot by the last block's number of txes minus 1)
509510
*
510511
* @return true if a block found in common or req_start_block specified, else false
511512
*/
512-
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const;
513+
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, const bool qblock_ids_exclusive, size_t max_block_count, size_t max_tx_count) const;
513514

514515
/**
515516
* @brief retrieves a set of blocks and their transactions, and possibly other transactions

src/cryptonote_core/cryptonote_core.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,9 +1225,9 @@ namespace cryptonote
12251225
return m_blockchain_storage.find_blockchain_supplement(qblock_ids, clip_pruned, resp);
12261226
}
12271227
//-----------------------------------------------------------------------------------------------
1228-
bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const
1228+
bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, const bool qblock_ids_exclusive, size_t max_block_count, size_t max_tx_count) const
12291229
{
1230-
return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, top_hash, start_height, pruned, get_miner_tx_hash, max_block_count, max_tx_count);
1230+
return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, top_hash, start_height, pruned, get_miner_tx_hash, qblock_ids_exclusive, max_block_count, max_tx_count);
12311231
}
12321232
//-----------------------------------------------------------------------------------------------
12331233
bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const

src/cryptonote_core/cryptonote_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ namespace cryptonote
593593
*
594594
* @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::vector<std::pair<cryptonote::blobdata, std::vector<transaction> > >&, uint64_t&, uint64_t&, size_t) const
595595
*/
596-
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_block_count, size_t max_tx_count) const;
596+
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, crypto::hash& top_hash, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, const bool qblock_ids_exclusive, size_t max_block_count, size_t max_tx_count) const;
597597

598598
/**
599599
* @copydoc Blockchain::get_tx_outputs_gindexs

src/rpc/core_rpc_server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ namespace cryptonote
755755
}
756756

757757
std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > > bs;
758-
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.top_block_hash, res.start_height, req.prune, !req.no_miner_tx, max_blocks, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
758+
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.top_block_hash, res.start_height, req.prune, !req.no_miner_tx, req.block_ids_exclusive, max_blocks, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
759759
{
760760
res.status = "Failed";
761761
add_host_fail(ctx);

src/rpc/core_rpc_server_commands_defs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
101101
// advance which version they will stop working with
102102
// Don't go over 32767 for any of these
103103
#define CORE_RPC_VERSION_MAJOR 3
104-
#define CORE_RPC_VERSION_MINOR 16
104+
#define CORE_RPC_VERSION_MINOR 17
105105
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
106106
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
107107

@@ -189,6 +189,7 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
189189
uint64_t start_height;
190190
bool prune;
191191
bool no_miner_tx;
192+
bool block_ids_exclusive;
192193
uint64_t pool_info_since;
193194
uint64_t max_block_count;
194195

@@ -199,6 +200,7 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
199200
KV_SERIALIZE(start_height)
200201
KV_SERIALIZE(prune)
201202
KV_SERIALIZE_OPT(no_miner_tx, false)
203+
KV_SERIALIZE_OPT(block_ids_exclusive, false)
202204
KV_SERIALIZE_OPT(pool_info_since, (uint64_t)0)
203205
KV_SERIALIZE_OPT(max_block_count, (uint64_t)0)
204206
END_KV_SERIALIZE_MAP()

src/rpc/daemon_handler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ namespace rpc
128128
{
129129
std::vector<std::pair<std::pair<blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, blobdata> > > > blocks;
130130

131-
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.top_block_hash, res.start_height, req.prune, true, COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
131+
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.top_block_hash, res.start_height, req.prune, true, false, COMMAND_RPC_GET_BLOCKS_FAST_MAX_BLOCK_COUNT, COMMAND_RPC_GET_BLOCKS_FAST_MAX_TX_COUNT))
132132
{
133133
res.status = Message::STATUS_FAILED;
134134
res.error_details = "core::find_blockchain_supplement() returned false";

0 commit comments

Comments
 (0)