|
|
|
@ -878,6 +878,11 @@ namespace cryptonote
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res)
|
|
|
|
|
{
|
|
|
|
|
cn_fast_hash(blob.data(), blob.size(), res);
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
void get_blob_hash(const blobdata& blob, crypto::hash& res)
|
|
|
|
|
{
|
|
|
|
|
cn_fast_hash(blob.data(), blob.size(), res);
|
|
|
|
@ -946,6 +951,13 @@ namespace cryptonote
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
crypto::hash get_blob_hash(const epee::span<const char>& blob)
|
|
|
|
|
{
|
|
|
|
|
crypto::hash h = null_hash;
|
|
|
|
|
get_blob_hash(blob, h);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
crypto::hash get_transaction_hash(const transaction& t)
|
|
|
|
|
{
|
|
|
|
|
crypto::hash h = null_hash;
|
|
|
|
@ -958,26 +970,35 @@ namespace cryptonote
|
|
|
|
|
return get_transaction_hash(t, res, NULL);
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
bool calculate_transaction_prunable_hash(const transaction& t, crypto::hash& res)
|
|
|
|
|
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res)
|
|
|
|
|
{
|
|
|
|
|
if (t.version == 1)
|
|
|
|
|
return false;
|
|
|
|
|
transaction &tt = const_cast<transaction&>(t);
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
binary_archive<true> ba(ss);
|
|
|
|
|
const size_t inputs = t.vin.size();
|
|
|
|
|
const size_t outputs = t.vout.size();
|
|
|
|
|
const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
|
|
|
|
|
bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
|
|
|
|
|
cryptonote::get_blob_hash(ss.str(), res);
|
|
|
|
|
const unsigned int unprunable_size = t.unprunable_size;
|
|
|
|
|
if (blob && unprunable_size)
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_MES(unprunable_size <= blob->size(), false, "Inconsistent transaction unprunable and blob sizes");
|
|
|
|
|
cryptonote::get_blob_hash(epee::span<const char>(blob->data() + unprunable_size, blob->size() - unprunable_size), res);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
transaction &tt = const_cast<transaction&>(t);
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
binary_archive<true> ba(ss);
|
|
|
|
|
const size_t inputs = t.vin.size();
|
|
|
|
|
const size_t outputs = t.vout.size();
|
|
|
|
|
const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
|
|
|
|
|
bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
|
|
|
|
|
cryptonote::get_blob_hash(ss.str(), res);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
crypto::hash get_transaction_prunable_hash(const transaction& t)
|
|
|
|
|
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blobdata)
|
|
|
|
|
{
|
|
|
|
|
crypto::hash res;
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, res), "Failed to calculate tx prunable hash");
|
|
|
|
|
CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, blobdata, res), "Failed to calculate tx prunable hash");
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
@ -1030,16 +1051,13 @@ namespace cryptonote
|
|
|
|
|
|
|
|
|
|
transaction &tt = const_cast<transaction&>(t);
|
|
|
|
|
|
|
|
|
|
const blobdata blob = tx_to_blob(t);
|
|
|
|
|
const unsigned int unprunable_size = t.unprunable_size;
|
|
|
|
|
const unsigned int prefix_size = t.prefix_size;
|
|
|
|
|
|
|
|
|
|
// base rct
|
|
|
|
|
{
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
binary_archive<true> ba(ss);
|
|
|
|
|
const size_t inputs = t.vin.size();
|
|
|
|
|
const size_t outputs = t.vout.size();
|
|
|
|
|
bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs);
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base");
|
|
|
|
|
cryptonote::get_blob_hash(ss.str(), hashes[1]);
|
|
|
|
|
}
|
|
|
|
|
CHECK_AND_ASSERT_MES(prefix_size <= unprunable_size && unprunable_size <= blob.size(), false, "Inconsistent transaction prefix, unprunable and blob sizes");
|
|
|
|
|
cryptonote::get_blob_hash(epee::span<const char>(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]);
|
|
|
|
|
|
|
|
|
|
// prunable rct
|
|
|
|
|
if (t.rct_signatures.type == rct::RCTTypeNull)
|
|
|
|
@ -1048,7 +1066,7 @@ namespace cryptonote
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, hashes[2]), false, "Failed to get tx prunable hash");
|
|
|
|
|
CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blob, hashes[2]), false, "Failed to get tx prunable hash");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the tx hash is the hash of the 3 hashes
|
|
|
|
|