forked from lthn/blockchain
added inputs sorting validation
This commit is contained in:
parent
84b702fa3f
commit
11298992d2
4 changed files with 117 additions and 4 deletions
|
|
@ -5220,7 +5220,16 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
if (var_is_after_hardfork_4_zone && !is_allowed_after_hardfork4(el))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (var_is_after_hardfork_4_zone)
|
||||
{
|
||||
if(!validate_inputs_sorting(tx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,6 +148,96 @@ namespace currency
|
|||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const crypto::key_image & get_key_image_txin_v(const txin_v& in_v)
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
{
|
||||
return boost::get<txin_to_key>(in_v).k_image;
|
||||
}
|
||||
else if (in_v.type() == typeid(txin_htlc))
|
||||
{
|
||||
return boost::get<txin_htlc>(in_v).k_image;
|
||||
}
|
||||
else if (in_v.type() == typeid(txin_zc_input))
|
||||
{
|
||||
return boost::get<txin_zc_input>(in_v).k_image;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("[get_to_key_input_from_txin_v] Wrong type " << in_v.type().name());
|
||||
}
|
||||
}
|
||||
|
||||
//, txin_htlc, txin_zc_input
|
||||
bool compare_varian_by_types(const txin_multisig& left, typename txin_multisig& right)
|
||||
{
|
||||
return (left.multisig_out_id < right.multisig_out_id);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool compare_varian_by_types(const txin_gen& left, typename txin_gen& right)
|
||||
{
|
||||
//actually this should never happen, should we leave it in case it happen in unit tests? @sowle
|
||||
return (left.height < right.height);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename type_with_kimage_t>
|
||||
bool compare_varian_by_types(const type_with_kimage_t& left, typename type_with_kimage_t& right)
|
||||
{
|
||||
return (left.k_image < right.k_image);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_type_left, typename t_type_right>
|
||||
bool compare_varian_by_types(const t_type_left& left, const t_type_right& right)
|
||||
{
|
||||
if (typeid(t_type_left) == typeid(t_type_right))
|
||||
{
|
||||
ASSERT_MES_AND_THROW("[compare_varian_by_types] Left and Right types matched type " << typeid(t_type_left).name());
|
||||
}
|
||||
//@sowle should we use here variant index instead? (tags takes since it's ids something more "unchangebale", but we can reconsider)
|
||||
return (variant_serialization_traits<typename binary_archive<true>, typename t_type_left>::get_tag() < variant_serialization_traits<typename binary_archive<true>, typename t_type_right>::get_tag());
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename t_type_left>
|
||||
struct right_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
const t_type_left& m_rleft;
|
||||
|
||||
right_visitor(const t_type_left& left) : m_rleft(left)
|
||||
{}
|
||||
|
||||
template<typename t_type_right>
|
||||
bool operator()(const t_type_right& right)const
|
||||
{
|
||||
return compare_varian_by_types(m_rleft, right);
|
||||
}
|
||||
};
|
||||
|
||||
struct left_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
const txin_v& m_rright;
|
||||
|
||||
left_visitor(const txin_v& right) : m_rright(right)
|
||||
{}
|
||||
template<typename t_type_left>
|
||||
bool operator()(const t_type_left& left)const
|
||||
{
|
||||
return boost::apply_visitor(right_visitor<t_type_left>(left), m_rright);
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------
|
||||
bool less_txin_v(const txin_v& left, const txin_v& right)
|
||||
{
|
||||
//txin_gen, txin_to_key, txin_multisig, txin_htlc, txin_zc_input
|
||||
if (left.type() != right.type())
|
||||
{
|
||||
//predefined type hierarchy based on it's tags defined in currency_basic.h, call compare_varian_by_types via 2-level visitor
|
||||
return boost::apply_visitor(left_visitor(right), left);
|
||||
}
|
||||
//compare
|
||||
return true;//(left < right);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename variant_container_t>
|
||||
bool check_allowed_types_in_variant_container(const variant_container_t& container, const std::unordered_set<std::type_index>& allowed_types, bool elements_must_be_unique = true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -275,14 +275,27 @@ namespace currency
|
|||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc))
|
||||
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc) || in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
|
||||
if (!ki.insert(get_to_key_input_from_txin_v(in).k_image).second)
|
||||
if (!ki.insert(get_key_image_txin_v(in)).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool validate_inputs_sorting(const transaction& tx)
|
||||
{
|
||||
size_t i = 0;
|
||||
for(; i+1 < tx.vin.size(); i++)
|
||||
{
|
||||
//same less_txin_v() function should be used for sorting inputs during transacction creation
|
||||
if (less_txin_v(tx.vin[i+1], tx.vin[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -153,6 +153,7 @@ namespace currency
|
|||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil);
|
||||
bool validate_inputs_sorting(const transaction& tx);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue