From 5f5e761ca8c2dde236fa79f5cdf084acf76c61a2 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 30 Jun 2015 17:02:21 -0400 Subject: [PATCH] db_block.cpp: Fix tapos rollover logic --- libraries/chain/db_block.cpp | 58 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 758ec444..bc26f5a9 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -468,10 +468,62 @@ processed_transaction database::_apply_transaction( const signed_transaction& tr //Check the TaPoS reference and expiration time //Remember that the TaPoS block number is abbreviated; it contains only the lower 16 bits. //Lookup TaPoS block summary by block number (remember block summary instances are the block numbers) + + // Let N = head_block_num(), a = N & 0xFFFF, and r = trx.ref_block_num + // + // We want to solve for the largest block height x such that + // these two conditions hold: + // + // (a) 0x10000 divides x-r + // (b) x <= N + // + // Let us define: + // + // x1 = N-a+r + // x0 = x1-2^16 + // x2 = x1+2^16 + // + // It is clear that x0, x1, x2 are consecutive solutions to (a). + // + // Since r < 2^16 and a < 2^16, it follows that + // -2^16 < r-a < 2^16. From this we know that x0 < N and x2 > N. + // + // Case (1): x1 <= N. In this case, x1 must be the greatest + // integer that satisfies (a) and (b); for x2, the next + // largest integer that satisfies (a), does not satisfy (b). + // + // Case (2): x1 > N. In this case, x0 must be the greatest + // integer that satisfies (a) and (b); for x1, the next + // largest integer that satisfies (a), does not satisfy (b). + // + int64_t N = head_block_num(); + int64_t a = N & 0xFFFF; + int64_t r = trx.ref_block_num; + + int64_t x1 = N-a+r; + int64_t x0 = x1 - 0x10000; + int64_t x2 = x1 + 0x10000; + + assert( x0 < N ); + assert( x1 >= 0 ); + assert( x2 > N ); + + uint32_t ref_block_height; + if( x1 <= N ) + { + FC_ASSERT( x1 > 0 ); + ref_block_height = uint32_t( x1 ); + } + else + { + ref_block_height = uint32_t( x0 ); + } + const block_summary_object& tapos_block_summary - = static_cast(get_index() - .get(block_summary_id_type((head_block_num() & ~0xffff) - + trx.ref_block_num))); + = static_cast( + get_index() + .get(block_summary_id_type(ref_block_height)) + ); //This is the signature check for transactions with relative expiration. if( !(skip & skip_transaction_signatures) )