forked from lthn/blockchain
signature refactoring: pre-core tests
This commit is contained in:
parent
4f80c7c334
commit
fa4b8ab130
8 changed files with 92 additions and 59 deletions
|
|
@ -6673,7 +6673,7 @@ bool blockchain_storage::is_output_allowed_for_input(const output_key_or_htlc_v&
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, const signature_v& input_sigs_v, uint64_t split_height, const alt_chain_type& alt_chain) const
|
||||
bool blockchain_storage::validate_alt_block_ms_input(const transaction& input_tx, const crypto::hash& input_tx_hash, size_t input_index, uint64_t split_height, const alt_chain_type& alt_chain) const
|
||||
{
|
||||
// Main and alt chain outline:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ namespace currency
|
|||
FIELDS(*static_cast<transaction_prefix *>(this))
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_INITAL, transaction_v1)
|
||||
CHAIN_TRANSITION_VER(TRANSACTION_VERSION_PRE_HF4, transaction_v1)
|
||||
FIELD(signature)
|
||||
FIELD(signatures)
|
||||
FIELD(attachment)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
|
@ -774,7 +774,7 @@ namespace currency
|
|||
vin.clear();
|
||||
vout.clear();
|
||||
extra.clear();
|
||||
signature = NLSAG_sig();
|
||||
signatures.clear();
|
||||
attachment.clear();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,13 +90,15 @@ template<typename transaction_current_t>
|
|||
bool transition_convert(const transaction_current_t& from, transaction_v1& to)
|
||||
{
|
||||
to.attachment = from.attachment;
|
||||
if (from.signature.type() == typeid(NLSAG_sig))
|
||||
for (const auto& s : from.signatures)
|
||||
{
|
||||
to.signatures = boost::get<NLSAG_sig>(from.signature).s;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Unexpected type in signature_v");
|
||||
if (s.type() == typeid(NLSAG_sig))
|
||||
{
|
||||
to.signatures.push_back(boost::get<NLSAG_sig>(s).s); ;
|
||||
}else
|
||||
{
|
||||
throw std::runtime_error("Unexpected type in signature_v");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -106,6 +108,10 @@ bool transition_convert(const transaction_v1& from, transaction_current_t& to)
|
|||
{
|
||||
// TODO: consider using move semantic for 'from'
|
||||
to.attachment = from.attachment;
|
||||
to.signature = NLSAG_sig({from.signatures});
|
||||
to.signatures.resize(from.signatures.size());
|
||||
for (size_t i = 0; i != from.signatures.size(); i++)
|
||||
{
|
||||
boost::get<NLSAG_sig>(to.signatures[i]).s = from.signatures[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ namespace currency
|
|||
posin.k_image = pe.keyimage;
|
||||
tx.vin.push_back(posin);
|
||||
//reserve place for ring signature
|
||||
//tx.signature = NLSAG_sig();
|
||||
tx.signatures.resize(1);
|
||||
tx.signatures[0] = NLSAG_sig();
|
||||
boost::get<NLSAG_sig>(tx.signatures[0]).s.resize(posin.key_offsets.size());
|
||||
|
|
|
|||
|
|
@ -56,7 +56,9 @@ namespace currency
|
|||
bool operator ==(const currency::transaction& a, const currency::transaction& b);
|
||||
bool operator ==(const currency::block& a, const currency::block& b);
|
||||
bool operator ==(const currency::extra_attachment_info& a, const currency::extra_attachment_info& b);
|
||||
|
||||
bool operator ==(const currency::NLSAG_sig& a, const currency::NLSAG_sig& b);
|
||||
bool operator ==(const currency::void_sig& a, const currency::void_sig& b);
|
||||
bool operator ==(const currency::zarcanum_sig& a, const currency::zarcanum_sig& b);
|
||||
|
||||
typedef boost::multiprecision::uint128_t uint128_tl;
|
||||
|
||||
|
|
|
|||
|
|
@ -3507,8 +3507,9 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b,
|
|||
return false; // to get rid of warning
|
||||
}else
|
||||
{
|
||||
NLSAG_sig& signatures = boost::get<NLSAG_sig>(b.miner_tx.signature);
|
||||
WLT_CHECK_AND_ASSERT_MES(signatures.s.size() == 1 && signatures.s[0].size() == txin.key_offsets.size(),
|
||||
WLT_CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1 &&
|
||||
b.miner_tx.signatures[0].type() == typeid(NLSAG_sig) &&
|
||||
boost::get<NLSAG_sig>(b.miner_tx.signatures[0]).s.size() == txin.key_offsets.size(),
|
||||
false, "Wrong signatures amount in coinbase transacton");
|
||||
|
||||
|
||||
|
|
@ -3536,12 +3537,12 @@ bool wallet2::prepare_and_sign_pos_block(currency::block& b,
|
|||
keys_ptrs,
|
||||
derived_secret_ephemeral_key,
|
||||
0,
|
||||
&signatures.s[0][0]);
|
||||
&boost::get<NLSAG_sig>(b.miner_tx.signatures[0]).s[0]);
|
||||
|
||||
WLT_LOG_L4("GENERATED RING SIGNATURE: block_id " << block_hash
|
||||
<< "txin.k_image" << txin.k_image
|
||||
<< "key_ptr:" << *keys_ptrs[0]
|
||||
<< "signature:" << signatures.s[0][0]);
|
||||
<< "signature:" << boost::get<NLSAG_sig>(b.miner_tx.signatures[0]).s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,14 +234,14 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n
|
|||
|
||||
|
||||
// (5/5) signatures
|
||||
VARIANT_SWITCH_BEGIN(tx.signature);
|
||||
VARIANT_CASE_CONST(NLSAG_sig, signatures)
|
||||
{
|
||||
LOC_CHK(signatures.s.size() == 1, "invalid singatures size: " << signatures.s.size()); // only 1 input means only 1 signature vector
|
||||
LOC_CHK(tx.signatures.size() == 1, "invalid singatures size: " << tx.signatures.size()); // only 1 input means only 1 signature vector
|
||||
|
||||
// As we don't have b_keys we can't be sure which signature is B's and which is reserved for A (should be a null-placeholder, if present).
|
||||
// Having a_keys, we determine index of A key in multisig output keys array.
|
||||
// Thus it's possible to determine the order of signatures (A, B or B, A), and, eventually, validate B signature.
|
||||
VARIANT_SWITCH_BEGIN(tx.signatures[0]);
|
||||
VARIANT_CASE_CONST(NLSAG_sig, signature)
|
||||
{
|
||||
// As we don't have b_keys we can't be sure which signature is B's and which is reserved for A (should be a null-placeholder, if present).
|
||||
// Having a_keys, we determine index of A key in multisig output keys array.
|
||||
// Thus it's possible to determine the order of signatures (A, B or B, A), and, eventually, validate B signature.
|
||||
crypto::public_key source_tx_pub_key = get_tx_pub_key_from_extra(source_tx);
|
||||
r = crypto::generate_key_derivation(source_tx_pub_key, a_keys.view_secret_key, der);
|
||||
LOC_CHK(r, "generate_key_derivation failed");
|
||||
|
|
@ -250,14 +250,14 @@ bool wallet2::validate_escrow_release(const transaction& tx, bool release_type_n
|
|||
LOC_CHK(r, "derive_public_key failed");
|
||||
|
||||
LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid ms output keys array, size: " << source_ms_out.keys.size());
|
||||
LOC_CHK(signatures.s[0].size() == 2, "internal error: invalid signature size for input #0: " << signatures.s[0].size())
|
||||
LOC_CHK(signature.size() == 2, "internal error: invalid signature size for input #0: " << signature.size())
|
||||
size_t ms_out_key_a_index = std::find(source_ms_out.keys.begin(), source_ms_out.keys.end(), ephemeral_pub_key) - source_ms_out.keys.begin();
|
||||
LOC_CHK(ms_out_key_a_index < source_ms_out.keys.size(), "internal error: can't find A ephemeral pub key within ms output keys");
|
||||
size_t ms_out_key_b_index = 1 - ms_out_key_a_index;
|
||||
|
||||
// in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in signatures.s[0]
|
||||
// in this particular case (source_ms_out.minimum_sigs == source_ms_out.keys.size() == 2) index in 'keys' is the same as index in signature
|
||||
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx));
|
||||
r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], signatures.s[0][ms_out_key_b_index]);
|
||||
r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[ms_out_key_b_index], signature[ms_out_key_b_index]);
|
||||
LOC_CHK(r, "B signature for multisig input is invalid");
|
||||
}
|
||||
VARIANT_CASE_CONST(zarcanum_sig, s);
|
||||
|
|
@ -418,17 +418,18 @@ bool wallet2::validate_escrow_cancel_release(const currency::transaction& tx, co
|
|||
|
||||
|
||||
// (5/5) signatures
|
||||
VARIANT_SWITCH_BEGIN(tx.signature);
|
||||
LOC_CHK(tx.signatures.size() == 1, "invalid singatures size: " << tx.signatures.size()); // only 1 input means only 1 signature vector
|
||||
VARIANT_SWITCH_BEGIN(tx.signatures[0]);
|
||||
VARIANT_CASE_CONST(NLSAG_sig, signatures)
|
||||
{
|
||||
LOC_CHK(signatures.s.size() == 1, "invalid singatures size: " << signatures.s.size()); // only 1 input means only 1 signature vector
|
||||
LOC_CHK(signatures.s[0].size() == 2, "invalid signature[0] size: " << signatures.s[0].size()); // it's expected to contain A-party signature and null-sig placeholder
|
||||
|
||||
LOC_CHK(signature.size() == 2, "invalid signature[0] size: " << signature.size()); // it's expected to contain A-party signature and null-sig placeholder
|
||||
LOC_CHK(source_ms_out.keys.size() == 2, "internal error: invalid source ms output keys array, size: " << source_ms_out.keys.size());
|
||||
|
||||
size_t a_sign_index = (signatures.s[0][0] != null_sig) ? 0 : 1;
|
||||
size_t a_sign_index = (signature[0] != null_sig) ? 0 : 1;
|
||||
|
||||
crypto::hash tx_hash_for_signature = prepare_prefix_hash_for_sign(tx, 0, get_transaction_hash(tx));
|
||||
r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], signatures.s[0][a_sign_index]);
|
||||
r = crypto::check_signature(tx_hash_for_signature, source_ms_out.keys[a_sign_index], signature[a_sign_index]);
|
||||
LOC_CHK(r, "A signature for multisig input is invalid");
|
||||
}
|
||||
VARIANT_CASE_CONST(zarcanum_sig, s);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ struct Struct
|
|||
char blob[8];
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator <<(std::ostream& o, const currency::signature_v& v)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
struct serializer<Archive, Struct>
|
||||
{
|
||||
|
|
@ -270,6 +276,18 @@ namespace
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> linearize_vector2(const std::vector< currency::signature_v >& vec_vec)
|
||||
{
|
||||
std::vector<T> res;
|
||||
BOOST_FOREACH(const auto& vec, vec_vec)
|
||||
{
|
||||
res.insert(res.end(), vec.begin(), vec.end());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool test_get_varint_packed_size_for_num(uint64_t n)
|
||||
|
|
@ -330,7 +348,8 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
ASSERT_TRUE(false);
|
||||
}
|
||||
|
||||
ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
ASSERT_EQ(tx.signatures, tx1.signatures);
|
||||
//ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
// Miner tx without signatures
|
||||
txin_gen txin_gen1;
|
||||
|
|
@ -344,10 +363,11 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
ASSERT_EQ(tx.signatures, tx1.signatures);
|
||||
//ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
// Miner tx with empty signatures 2nd vector
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(1);
|
||||
tx.signatures.resize(1);
|
||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures + counter
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||
|
|
@ -355,29 +375,30 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
ASSERT_EQ(tx.signatures, tx1.signatures);
|
||||
//ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
//TX VALIDATION REMOVED FROM SERIALIZATION
|
||||
/*
|
||||
// Miner tx with one signature
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(1);
|
||||
tx.signatures[0].resize(1);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// Miner tx with 2 empty vectors
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(0);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(0);
|
||||
tx.signatures.resize(2);
|
||||
tx.signatures[0].resize(0);
|
||||
tx.signatures[1].resize(0);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// Miner tx with 2 signatures
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(1);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(1);
|
||||
tx.signatures[0].resize(1);
|
||||
tx.signatures[1].resize(1);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
*/
|
||||
|
||||
// Two txin_gen, no signatures
|
||||
tx.vin.push_back(txin_gen1);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(0);
|
||||
tx.signatures.resize(0);
|
||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||
ASSERT_EQ(10, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||
|
|
@ -385,14 +406,15 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
ASSERT_EQ(tx.signatures, tx1.signatures);
|
||||
//ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
// Two txin_gen, signatures vector contains only one empty element
|
||||
//signatures.resize(1);
|
||||
//ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// Two txin_gen, signatures vector contains two empty elements
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(2);
|
||||
tx.signatures.resize(2);
|
||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||
ASSERT_EQ(12, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||
|
|
@ -400,7 +422,9 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
{
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
ASSERT_EQ(tx.signatures, tx1.signatures);
|
||||
//ASSERT_EQ(linearize_vector2(boost::get<currency::NLSAG_sig>(tx.signature).s), linearize_vector2(boost::get<currency::NLSAG_sig>(tx1.signature).s));
|
||||
|
||||
// Two txin_gen, signatures vector contains three empty elements
|
||||
//signatures.resize(3);
|
||||
|
|
@ -415,7 +439,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
// A few bytes instead of signature
|
||||
tx.vin.clear();
|
||||
tx.vin.push_back(txin_gen1);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.clear();
|
||||
tx.signatures.clear();
|
||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||
blob.append(std::string(sizeof(crypto::signature) / 2, 'x'));
|
||||
ASSERT_FALSE(serialization::parse_binary(blob, tx1));
|
||||
|
|
@ -438,28 +462,28 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
|
|||
|
||||
/*
|
||||
// Too much signatures for two inputs
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(3);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[2].resize(2);
|
||||
tx.signatures.resize(3);
|
||||
tx.signatures[0].resize(2);
|
||||
tx.signatures[1].resize(2);
|
||||
tx.signatures[2].resize(2);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// First signatures vector contains too little elements
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(1);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(2);
|
||||
tx.signatures.resize(2);
|
||||
tx.signatures[0].resize(1);
|
||||
tx.signatures[1].resize(2);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// First signatures vector contains too much elements
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(3);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(2);
|
||||
tx.signatures.resize(2);
|
||||
tx.signatures[0].resize(3);
|
||||
tx.signatures[1].resize(2);
|
||||
ASSERT_FALSE(serialization::dump_binary(tx, blob));
|
||||
|
||||
// There are signatures for each input
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s.resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[0].resize(2);
|
||||
boost::get<currency::NLSAG_sig>(tx.signature).s[1].resize(2);
|
||||
tx.signatures.resize(2);
|
||||
tx.signatures[0].resize(2);
|
||||
tx.signatures[1].resize(2);
|
||||
ASSERT_TRUE(serialization::dump_binary(tx, blob));
|
||||
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
|
||||
ASSERT_EQ(tx, tx1);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue