diff --git a/src/currency_core/currency_format_utils_transactions.cpp b/src/currency_core/currency_format_utils_transactions.cpp index ffb6d813..0c552fa1 100644 --- a/src/currency_core/currency_format_utils_transactions.cpp +++ b/src/currency_core/currency_format_utils_transactions.cpp @@ -215,12 +215,35 @@ namespace currency return total; } //--------------------------------------------------------------- + inline size_t get_input_expected_signature_size_local(const txin_v& tx_in, bool last_input_in_separately_signed_tx) + { + struct txin_signature_size_visitor : public boost::static_visitor + { + txin_signature_size_visitor(size_t add) : a(add) {} + size_t a; + size_t operator()(const txin_gen& /*txin*/) const { return 0; } + size_t operator()(const txin_to_key& txin) const { return tools::get_varint_packed_size(txin.key_offsets.size() + a) + sizeof(crypto::signature) * (txin.key_offsets.size() + a); } + size_t operator()(const txin_multisig& txin) const { return tools::get_varint_packed_size(txin.sigs_count + a) + sizeof(crypto::signature) * (txin.sigs_count + a); } + size_t operator()(const txin_htlc& txin) const { return tools::get_varint_packed_size(1 + a) + sizeof(crypto::signature) * (1 + a); } + size_t operator()(const txin_zc_input& txin) const { return 96 + tools::get_varint_packed_size(txin.key_offsets.size()) + txin.key_offsets.size() * 32; } + }; + + return boost::apply_visitor(txin_signature_size_visitor(last_input_in_separately_signed_tx ? 1 : 0), tx_in); + } + //--------------------------------------------------------------- size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size) { size_t tx_blob_size = prefix_blob_size; if (is_coinbase(t)) + { + if (is_pos_miner_tx(t) && t.version > TRANSACTION_VERSION_PRE_HF4) + { + // Zarcanum + return tx_blob_size; + } return tx_blob_size; + } // for purged tx, with empty signatures and attachments, this function should return the blob size // which the tx would have if the signatures and attachments were correctly filled with actual data @@ -229,10 +252,12 @@ namespace currency bool separately_signed_tx = get_tx_flags(t) & TX_FLAG_SIGNATURE_MODE_SEPARATE; tx_blob_size += tools::get_varint_packed_size(t.vin.size()); // size of transaction::signatures (equals to total inputs count) + if (t.version > TRANSACTION_VERSION_PRE_HF4) + tx_blob_size += t.vin.size(); // for HF4 txs 'signatures' is a verctor of variants, so it's +1 byte per signature (assuming sigs count equals to inputs count) for (size_t i = 0; i != t.vin.size(); i++) { - size_t sig_size = get_input_expected_signature_size(t.vin[i], separately_signed_tx && i == t.vin.size() - 1); + size_t sig_size = get_input_expected_signature_size_local(t.vin[i], separately_signed_tx && i == t.vin.size() - 1); tx_blob_size += sig_size; } diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index 6b794341..8a1e145f 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -772,8 +772,6 @@ int main(int argc, char* argv[]) MARK_TEST_AS_POSTPONED(before_hard_fork_1_cumulative_difficulty); MARK_TEST_AS_POSTPONED(inthe_middle_hard_fork_1_cumulative_difficulty); - MARK_TEST_AS_POSTPONED(zarcanum_basic_test); - #undef MARK_TEST_AS_POSTPONED diff --git a/tests/unit_tests/basic_struct_packing.cpp b/tests/unit_tests/basic_struct_packing.cpp index 54521528..7d75ff8d 100644 --- a/tests/unit_tests/basic_struct_packing.cpp +++ b/tests/unit_tests/basic_struct_packing.cpp @@ -84,9 +84,10 @@ TEST(tx_signatures_packing, 1) { // empty NLSAG - // v(0) + (1 + v(0) + 0 * 2 * 32) = 3 + // v(1) + (1 + v(0) + 0 * 2 * 32) = 3 sigs.clear(); sigs.emplace_back(std::move(NLSAG_sig())); + ASSERT_EQ(3, t_serializable_object_to_blob(sigs).size()); ASSERT_EQ(3, get_object_blobsize(sigs)); } @@ -96,14 +97,28 @@ TEST(tx_signatures_packing, 1) sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(std::move(NLSAG_sig())); + ASSERT_EQ(258, t_serializable_object_to_blob(sigs).size()); ASSERT_EQ(258, get_object_blobsize(sigs)); } + { + // 128 10-ring NLSAGs + // v(128) + 128 * (1 + v(10) + 10 * 2 * 32) = 82178 + sigs.clear(); + NLSAG_sig nlsag = AUTO_VAL_INIT(nlsag); + nlsag.s.resize(10); + for(size_t i = 0; i < 128; ++i) + sigs.push_back(nlsag); + ASSERT_EQ(82178, t_serializable_object_to_blob(sigs).size()); + ASSERT_EQ(82178, get_object_blobsize(sigs)); + } + { // empty ZC_sig - // v(0) + (1 + 32 + 32 + (1 + 10*32) + 32) = 99 + // v(1) + (1 + 32 + 32 + (1 + 10*32) + 32) = 99 sigs.clear(); sigs.emplace_back(std::move(ZC_sig())); + ASSERT_EQ(99, t_serializable_object_to_blob(sigs).size()); ASSERT_EQ(99, get_object_blobsize(sigs)); } @@ -113,6 +128,7 @@ TEST(tx_signatures_packing, 1) sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(std::move(ZC_sig())); + ASSERT_EQ(12546, t_serializable_object_to_blob(sigs).size()); ASSERT_EQ(12546, get_object_blobsize(sigs)); } @@ -124,6 +140,7 @@ TEST(tx_signatures_packing, 1) sigs.clear(); for(size_t i = 0; i < 128; ++i) sigs.emplace_back(zc); + ASSERT_EQ(53506, t_serializable_object_to_blob(sigs).size()); ASSERT_EQ(53506, get_object_blobsize(sigs)); } }