mirror of
https://github.com/monero-project/monero.git
synced 2025-05-02 17:04:51 -04:00
Merge pull request #4308
9907ea06
cryptonote: sort tx_extra fields (moneromooo-monero)
This commit is contained in:
commit
1c91963dcd
5 changed files with 177 additions and 1 deletions
|
@ -47,7 +47,6 @@
|
|||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "misc_language.h"
|
||||
#include "tx_extra.h"
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "device/device.hpp"
|
||||
|
||||
|
|
|
@ -445,6 +445,91 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<typename T>
|
||||
static bool pick(binary_archive<true> &ar, std::vector<tx_extra_field> &fields, uint8_t tag)
|
||||
{
|
||||
std::vector<tx_extra_field>::iterator it;
|
||||
while ((it = std::find_if(fields.begin(), fields.end(), [](const tx_extra_field &f) { return f.type() == typeid(T); })) != fields.end())
|
||||
{
|
||||
bool r = ::do_serialize(ar, tag);
|
||||
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field");
|
||||
r = ::do_serialize(ar, boost::get<T>(*it));
|
||||
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field");
|
||||
fields.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool sort_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<uint8_t> &sorted_tx_extra, bool allow_partial)
|
||||
{
|
||||
std::vector<tx_extra_field> tx_extra_fields;
|
||||
|
||||
if(tx_extra.empty())
|
||||
{
|
||||
sorted_tx_extra.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
|
||||
std::istringstream iss(extra_str);
|
||||
binary_archive<false> ar(iss);
|
||||
|
||||
bool eof = false;
|
||||
size_t processed = 0;
|
||||
while (!eof)
|
||||
{
|
||||
tx_extra_field field;
|
||||
bool r = ::do_serialize(ar, field);
|
||||
if (!r)
|
||||
{
|
||||
MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
|
||||
if (!allow_partial)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
tx_extra_fields.push_back(field);
|
||||
processed = iss.tellg();
|
||||
|
||||
std::ios_base::iostate state = iss.rdstate();
|
||||
eof = (EOF == iss.peek());
|
||||
iss.clear(state);
|
||||
}
|
||||
if (!::serialization::check_stream_state(ar))
|
||||
{
|
||||
MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
|
||||
if (!allow_partial)
|
||||
return false;
|
||||
}
|
||||
MTRACE("Sorted " << processed << "/" << tx_extra.size());
|
||||
|
||||
std::ostringstream oss;
|
||||
binary_archive<true> nar(oss);
|
||||
|
||||
// sort by:
|
||||
if (!pick<tx_extra_pub_key>(nar, tx_extra_fields, TX_EXTRA_TAG_PUBKEY)) return false;
|
||||
if (!pick<tx_extra_additional_pub_keys>(nar, tx_extra_fields, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS)) return false;
|
||||
if (!pick<tx_extra_nonce>(nar, tx_extra_fields, TX_EXTRA_NONCE)) return false;
|
||||
if (!pick<tx_extra_merge_mining_tag>(nar, tx_extra_fields, TX_EXTRA_MERGE_MINING_TAG)) return false;
|
||||
if (!pick<tx_extra_mysterious_minergate>(nar, tx_extra_fields, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG)) return false;
|
||||
if (!pick<tx_extra_padding>(nar, tx_extra_fields, TX_EXTRA_TAG_PADDING)) return false;
|
||||
|
||||
// if not empty, someone added a new type and did not add a case above
|
||||
if (!tx_extra_fields.empty())
|
||||
{
|
||||
MERROR("tx_extra_fields not empty after sorting, someone forgot to add a case above");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string oss_str = oss.str();
|
||||
if (allow_partial && processed < tx_extra.size())
|
||||
{
|
||||
MDEBUG("Appending unparsed data");
|
||||
oss_str += std::string((const char*)tx_extra.data() + processed, tx_extra.size() - processed);
|
||||
}
|
||||
sorted_tx_extra = std::vector<uint8_t>(oss_str.begin(), oss_str.end());
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index)
|
||||
{
|
||||
std::vector<tx_extra_field> tx_extra_fields;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
#include "blobdatatype.h"
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "tx_extra.h"
|
||||
#include "account.h"
|
||||
#include "subaddress_index.h"
|
||||
#include "include_base_utils.h"
|
||||
|
@ -65,6 +66,7 @@ namespace cryptonote
|
|||
}
|
||||
|
||||
bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields);
|
||||
bool sort_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<uint8_t> &sorted_tx_extra, bool allow_partial = false);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index = 0);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index = 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue