encrypted payment ids are now 64 bit, instead of 256 bit
Pros: - smaller on the blockchain - shorter integrated addresses Cons: - less sparseness - less ability to embed actual information The boolean argument to encrypt payment ids is now gone from the RPC calls, since the decision is made based on the length of the payment id passed.
This commit is contained in:
parent
e40cfc4e29
commit
a2d7a5fb49
@ -45,9 +45,13 @@ namespace crypto {
|
||||
POD_CLASS hash {
|
||||
char data[HASH_SIZE];
|
||||
};
|
||||
POD_CLASS hash8 {
|
||||
char data[8];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(hash) == HASH_SIZE, "Invalid structure size");
|
||||
static_assert(sizeof(hash8) == 8, "Invalid structure size");
|
||||
|
||||
/*
|
||||
Cryptonight hash functions
|
||||
@ -74,3 +78,4 @@ namespace crypto {
|
||||
}
|
||||
|
||||
CRYPTO_MAKE_HASHABLE(hash)
|
||||
CRYPTO_MAKE_COMPARABLE(hash8)
|
||||
|
@ -120,7 +120,7 @@ DISABLE_VS_WARNINGS(4244 4345)
|
||||
return get_account_address_as_str(testnet, m_keys.m_account_address);
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
std::string account_base::get_public_integrated_address_str(const crypto::hash &payment_id, bool testnet) const
|
||||
std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const
|
||||
{
|
||||
//TODO: change this code into base 58
|
||||
return get_account_integrated_address_as_str(testnet, m_keys.m_account_address, payment_id);
|
||||
|
@ -61,7 +61,7 @@ namespace cryptonote
|
||||
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
|
||||
const account_keys& get_keys() const;
|
||||
std::string get_public_address_str(bool testnet) const;
|
||||
std::string get_public_integrated_address_str(const crypto::hash &payment_id, bool testnet) const;
|
||||
std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const;
|
||||
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
void set_createtime(uint64_t val) { m_creation_timestamp = val; }
|
||||
|
@ -57,6 +57,7 @@ namespace cryptonote
|
||||
{
|
||||
|
||||
const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash);
|
||||
const static crypto::hash8 null_hash8 = AUTO_VAL_INIT(null_hash8);
|
||||
const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey);
|
||||
|
||||
typedef std::vector<crypto::signature> ring_signature;
|
||||
|
@ -46,7 +46,7 @@ namespace cryptonote {
|
||||
|
||||
struct integrated_address {
|
||||
account_public_address adr;
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(adr)
|
||||
@ -150,7 +150,7 @@ namespace cryptonote {
|
||||
std::string get_account_integrated_address_as_str(
|
||||
bool testnet
|
||||
, account_public_address const & adr
|
||||
, crypto::hash const & payment_id
|
||||
, crypto::hash8 const & payment_id
|
||||
)
|
||||
{
|
||||
uint64_t integrated_address_prefix = testnet ?
|
||||
@ -176,7 +176,7 @@ namespace cryptonote {
|
||||
bool get_account_integrated_address_from_str(
|
||||
account_public_address& adr
|
||||
, bool& has_payment_id
|
||||
, crypto::hash& payment_id
|
||||
, crypto::hash8& payment_id
|
||||
, bool testnet
|
||||
, std::string const & str
|
||||
)
|
||||
@ -278,7 +278,7 @@ namespace cryptonote {
|
||||
)
|
||||
{
|
||||
bool has_payment_id;
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
return get_account_integrated_address_from_str(adr, has_payment_id, payment_id, testnet, str);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace cryptonote {
|
||||
{
|
||||
uint8_t m_ver;
|
||||
account_public_address m_address;
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
uint8_t check_sum;
|
||||
};
|
||||
#pragma pack (pop)
|
||||
@ -83,13 +83,13 @@ namespace cryptonote {
|
||||
std::string get_account_integrated_address_as_str(
|
||||
bool testnet
|
||||
, const account_public_address& adr
|
||||
, const crypto::hash& payment_id
|
||||
, const crypto::hash8& payment_id
|
||||
);
|
||||
|
||||
bool get_account_integrated_address_from_str(
|
||||
account_public_address& adr
|
||||
, bool& has_payment_id
|
||||
, crypto::hash& payment_id
|
||||
, crypto::hash8& payment_id
|
||||
, bool testnet
|
||||
, const std::string& str
|
||||
);
|
||||
@ -110,6 +110,10 @@ template <class T>
|
||||
std::ostream &print256(std::ostream &o, const T &v) {
|
||||
return o << "<" << epee::string_tools::pod_to_hex(v) << ">";
|
||||
}
|
||||
template <class T>
|
||||
std::ostream &print64(std::ostream &o, const T &v) {
|
||||
return o << "<" << epee::string_tools::pod_to_hex(v) << ">";
|
||||
}
|
||||
|
||||
bool parse_hash256(const std::string str_hash, crypto::hash& hash);
|
||||
|
||||
@ -120,4 +124,5 @@ namespace crypto {
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::hash8 &v) { return print64(o, v); }
|
||||
}
|
||||
|
@ -334,26 +334,43 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id, bool encrypted)
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id)
|
||||
{
|
||||
extra_nonce.clear();
|
||||
extra_nonce.push_back(encrypted ? TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID : TX_EXTRA_NONCE_PAYMENT_ID);
|
||||
extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID);
|
||||
const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id);
|
||||
std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id, bool &encrypted)
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id)
|
||||
{
|
||||
extra_nonce.clear();
|
||||
extra_nonce.push_back(TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID);
|
||||
const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id);
|
||||
std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id)
|
||||
{
|
||||
if(sizeof(crypto::hash) + 1 != extra_nonce.size())
|
||||
return false;
|
||||
if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0] && TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID != extra_nonce[0])
|
||||
if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0])
|
||||
return false;
|
||||
payment_id = *reinterpret_cast<const crypto::hash*>(extra_nonce.data() + 1);
|
||||
encrypted = TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID == extra_nonce[0];
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations)
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id)
|
||||
{
|
||||
if(sizeof(crypto::hash8) + 1 != extra_nonce.size())
|
||||
return false;
|
||||
if (TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID != extra_nonce[0])
|
||||
return false;
|
||||
payment_id = *reinterpret_cast<const crypto::hash8*>(extra_nonce.data() + 1);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys)
|
||||
{
|
||||
if (destinations.empty())
|
||||
return null_pkey;
|
||||
@ -367,7 +384,7 @@ namespace cryptonote
|
||||
return destinations[0].addr.m_view_public_key;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool encrypt_payment_id(crypto::hash &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
|
||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
|
||||
{
|
||||
crypto::key_derivation derivation;
|
||||
crypto::hash hash;
|
||||
@ -380,12 +397,12 @@ namespace cryptonote
|
||||
data[32] = ENCRYPTED_PAYMENT_ID_TAIL;
|
||||
cn_fast_hash(data, 33, hash);
|
||||
|
||||
for (size_t b = 0; b < 32; ++b)
|
||||
for (size_t b = 0; b < 8; ++b)
|
||||
payment_id.data[b] ^= hash.data[b];
|
||||
|
||||
return true;
|
||||
}
|
||||
bool decrypt_payment_id(crypto::hash &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
|
||||
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
|
||||
{
|
||||
// Encryption and decryption are the same operation (xor with a key)
|
||||
return encrypt_payment_id(payment_id, public_key, secret_key);
|
||||
@ -411,13 +428,12 @@ namespace cryptonote
|
||||
tx_extra_nonce extra_nonce;
|
||||
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
|
||||
{
|
||||
crypto::hash payment_id = null_hash;
|
||||
bool encrypted;
|
||||
if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id, encrypted) && encrypted)
|
||||
crypto::hash8 payment_id = null_hash8;
|
||||
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
|
||||
{
|
||||
LOG_PRINT_L2("Encrypting payment id " << payment_id);
|
||||
crypto::key_derivation derivation;
|
||||
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations);
|
||||
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys);
|
||||
if (view_key_pub == null_pkey)
|
||||
{
|
||||
LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids");
|
||||
@ -431,7 +447,7 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
std::string extra_nonce;
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id, true);
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
|
||||
remove_extra_nonce_tx_extra(tx.extra);
|
||||
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
|
||||
{
|
||||
|
@ -45,8 +45,8 @@ namespace cryptonote
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 1);
|
||||
bool encrypt_payment_id(crypto::hash &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
bool decrypt_payment_id(crypto::hash &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||
|
||||
struct tx_source_entry
|
||||
{
|
||||
@ -88,8 +88,10 @@ namespace cryptonote
|
||||
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key);
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce);
|
||||
bool remove_extra_nonce_tx_extra(std::vector<uint8_t>& tx_extra);
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id, bool encrypted);
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id, bool &encrypted);
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id);
|
||||
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id);
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
|
||||
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id);
|
||||
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
|
@ -79,12 +79,14 @@ bool do_serialize(Archive<true> &ar, std::vector<crypto::signature> &v)
|
||||
|
||||
BLOB_SERIALIZER(crypto::chacha8_iv);
|
||||
BLOB_SERIALIZER(crypto::hash);
|
||||
BLOB_SERIALIZER(crypto::hash8);
|
||||
BLOB_SERIALIZER(crypto::public_key);
|
||||
BLOB_SERIALIZER(crypto::secret_key);
|
||||
BLOB_SERIALIZER(crypto::key_derivation);
|
||||
BLOB_SERIALIZER(crypto::key_image);
|
||||
BLOB_SERIALIZER(crypto::signature);
|
||||
VARIANT_TAG(debug_archive, crypto::hash, "hash");
|
||||
VARIANT_TAG(debug_archive, crypto::hash8, "hash8");
|
||||
VARIANT_TAG(debug_archive, crypto::public_key, "public_key");
|
||||
VARIANT_TAG(debug_archive, crypto::secret_key, "secret_key");
|
||||
VARIANT_TAG(debug_archive, crypto::key_derivation, "key_derivation");
|
||||
|
@ -601,7 +601,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
// parse address
|
||||
cryptonote::account_public_address address;
|
||||
bool has_payment_id;
|
||||
crypto::hash new_payment_id;
|
||||
crypto::hash8 new_payment_id;
|
||||
if(!get_account_integrated_address_from_str(address, has_payment_id, new_payment_id, testnet, parts[0]))
|
||||
{
|
||||
fail_msg_writer() << tr("Failed to parse address");
|
||||
@ -1288,36 +1288,45 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector<std::str
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
bool payment_id_seen = false;
|
||||
bool encrypt_payment_id = false;
|
||||
if (1 == local_args.size() % 2)
|
||||
{
|
||||
std::string payment_id_str = local_args.back();
|
||||
local_args.pop_back();
|
||||
|
||||
crypto::hash payment_id;
|
||||
bool r = tools::wallet2::parse_payment_id(payment_id_str, payment_id);
|
||||
bool r = tools::wallet2::parse_long_payment_id(payment_id_str, payment_id);
|
||||
if(r)
|
||||
{
|
||||
std::string extra_nonce;
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id, false);
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
}
|
||||
else
|
||||
{
|
||||
crypto::hash8 payment_id8;
|
||||
r = tools::wallet2::parse_short_payment_id(payment_id_str, payment_id8);
|
||||
if(r)
|
||||
{
|
||||
std::string extra_nonce;
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
}
|
||||
}
|
||||
|
||||
if(!r)
|
||||
{
|
||||
fail_msg_writer() << tr("payment id has invalid format, expected 64-character string: ") << payment_id_str;
|
||||
fail_msg_writer() << tr("payment id has invalid format, expected 16 or 64 character string: ") << payment_id_str;
|
||||
return true;
|
||||
}
|
||||
payment_id_seen = true;
|
||||
}
|
||||
|
||||
vector<cryptonote::tx_destination_entry> dsts;
|
||||
crypto::hash payment_id = null_hash;
|
||||
for (size_t i = 0; i < local_args.size(); i += 2)
|
||||
{
|
||||
cryptonote::tx_destination_entry de;
|
||||
bool has_payment_id;
|
||||
crypto::hash new_payment_id;
|
||||
crypto::hash8 new_payment_id;
|
||||
if(!get_account_integrated_address_from_str(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[i]))
|
||||
{
|
||||
// if treating as an address fails, try as url
|
||||
@ -1377,29 +1386,22 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector<std::str
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (has_payment_id)
|
||||
encrypt_payment_id = true;
|
||||
}
|
||||
|
||||
if (has_payment_id) {
|
||||
if (payment_id_seen && payment_id != new_payment_id) {
|
||||
if (has_payment_id)
|
||||
{
|
||||
if (payment_id_seen)
|
||||
{
|
||||
fail_msg_writer() << tr("A single transaction cannot use more than one payment id: ") << local_args[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!payment_id_seen)
|
||||
std::string extra_nonce;
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, new_payment_id);
|
||||
bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
if(!r)
|
||||
{
|
||||
std::string extra_nonce;
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, new_payment_id, encrypt_payment_id);
|
||||
bool r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
if(!r)
|
||||
{
|
||||
fail_msg_writer() << tr("Failed to set up payment id, though it was decoded correctly");
|
||||
return true;
|
||||
}
|
||||
payment_id = new_payment_id;
|
||||
fail_msg_writer() << tr("Failed to set up payment id, though it was decoded correctly");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1702,7 +1704,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::print_integrated_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
{
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
if (args.size() > 1)
|
||||
{
|
||||
fail_msg_writer() << tr("integrated_address only takes one or zero arguments");
|
||||
@ -1710,19 +1712,19 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
|
||||
}
|
||||
if (args.size() == 0)
|
||||
{
|
||||
crypto::generate_random_bytes(32, payment_id.data);
|
||||
crypto::generate_random_bytes(8, payment_id.data);
|
||||
success_msg_writer() << tr("Random payment ID: ") << payment_id;
|
||||
success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet());
|
||||
return true;
|
||||
}
|
||||
if(tools::wallet2::parse_payment_id(args.back(), payment_id))
|
||||
if(tools::wallet2::parse_short_payment_id(args.back(), payment_id))
|
||||
{
|
||||
success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->testnet());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
bool has_payment_id;
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
account_public_address addr;
|
||||
if(get_account_integrated_address_from_str(addr, has_payment_id, payment_id, m_wallet->testnet(), args.back()))
|
||||
{
|
||||
|
@ -237,20 +237,24 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_
|
||||
crypto::hash payment_id = null_hash;
|
||||
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
|
||||
{
|
||||
bool encrypted;
|
||||
if(get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id, encrypted) && encrypted)
|
||||
crypto::hash8 payment_id8 = null_hash8;
|
||||
if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
|
||||
{
|
||||
// We got a payment ID to go with this tx
|
||||
LOG_PRINT_L2("Found encrypted payment ID: " << payment_id);
|
||||
LOG_PRINT_L2("Found encrypted payment ID: " << payment_id8);
|
||||
if (tx_pub_key != null_pkey)
|
||||
{
|
||||
if (!decrypt_payment_id(payment_id, tx_pub_key, m_account.get_keys().m_view_secret_key))
|
||||
if (!decrypt_payment_id(payment_id8, tx_pub_key, m_account.get_keys().m_view_secret_key))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to decrypt payment ID: " << payment_id);
|
||||
LOG_PRINT_L0("Failed to decrypt payment ID: " << payment_id8);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L2("Decrypted payment ID: " << payment_id);
|
||||
LOG_PRINT_L2("Decrypted payment ID: " << payment_id8);
|
||||
// put the 64 bit decrypted payment id in the first 8 bytes
|
||||
memcpy(payment_id.data, payment_id8.data, 8);
|
||||
// rest is already 0, but guard against code changes above
|
||||
memset(payment_id.data + 8, 0, 24);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -258,6 +262,10 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_
|
||||
LOG_PRINT_L1("No public key found in tx, unable to decrypt payment id");
|
||||
}
|
||||
}
|
||||
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
|
||||
{
|
||||
LOG_PRINT_L2("Found unencrypted payment ID: " << payment_id);
|
||||
}
|
||||
}
|
||||
uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0;
|
||||
if (0 < received)
|
||||
@ -783,7 +791,7 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path)
|
||||
return !file_path.empty();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
|
||||
bool wallet2::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
|
||||
{
|
||||
cryptonote::blobdata payment_id_data;
|
||||
if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
|
||||
@ -796,6 +804,33 @@ bool wallet2::parse_payment_id(const std::string& payment_id_str, crypto::hash&
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id)
|
||||
{
|
||||
cryptonote::blobdata payment_id_data;
|
||||
if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
|
||||
return false;
|
||||
|
||||
if(sizeof(crypto::hash8) != payment_id_data.size())
|
||||
return false;
|
||||
|
||||
payment_id = *reinterpret_cast<const crypto::hash8*>(payment_id_data.data());
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
|
||||
{
|
||||
if (parse_long_payment_id(payment_id_str, payment_id))
|
||||
return true;
|
||||
crypto::hash8 payment_id8;
|
||||
if (parse_short_payment_id(payment_id_str, payment_id8))
|
||||
{
|
||||
memcpy(payment_id.data, payment_id8.data, 8);
|
||||
memset(payment_id.data + 8, 0, 24);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_file_names(const std::string& file_path)
|
||||
{
|
||||
do_prepare_file_names(file_path, m_keys_file, m_wallet_file);
|
||||
|
@ -266,6 +266,8 @@ namespace tools
|
||||
*/
|
||||
static bool wallet_valid_path_format(const std::string& file_path);
|
||||
|
||||
static bool parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id);
|
||||
static bool parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id);
|
||||
static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id);
|
||||
|
||||
static std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec_valid);
|
||||
|
@ -117,14 +117,15 @@ namespace tools
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, std::string payment_id, bool encrypt_payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er)
|
||||
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, std::string payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er)
|
||||
{
|
||||
crypto::hash integrated_payment_id = cryptonote::null_hash;
|
||||
crypto::hash8 integrated_payment_id = cryptonote::null_hash8;
|
||||
std::string extra_nonce;
|
||||
for (auto it = destinations.begin(); it != destinations.end(); it++)
|
||||
{
|
||||
cryptonote::tx_destination_entry de;
|
||||
bool has_payment_id;
|
||||
crypto::hash new_payment_id;
|
||||
crypto::hash8 new_payment_id;
|
||||
if(!get_account_integrated_address_from_str(de.addr, has_payment_id, new_payment_id, m_wallet.testnet(), it->address))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
@ -136,17 +137,15 @@ namespace tools
|
||||
|
||||
if (has_payment_id)
|
||||
{
|
||||
if (!payment_id.empty() || integrated_payment_id != cryptonote::null_hash)
|
||||
if (!payment_id.empty() || integrated_payment_id != cryptonote::null_hash8)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
er.message = "A single payment id is allowed per transaction";
|
||||
return false;
|
||||
}
|
||||
integrated_payment_id = new_payment_id;
|
||||
cryptonote::set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, integrated_payment_id);
|
||||
}
|
||||
|
||||
// integrated addresses imply encrypted payment id
|
||||
encrypt_payment_id = true;
|
||||
}
|
||||
|
||||
if (!payment_id.empty())
|
||||
@ -155,17 +154,23 @@ namespace tools
|
||||
/* Just to clarify */
|
||||
const std::string& payment_id_str = payment_id;
|
||||
|
||||
crypto::hash payment_id;
|
||||
crypto::hash long_payment_id;
|
||||
crypto::hash8 short_payment_id;
|
||||
|
||||
/* Parse payment ID */
|
||||
if (!wallet2::parse_payment_id(payment_id_str, payment_id)) {
|
||||
if (wallet2::parse_long_payment_id(payment_id_str, long_payment_id)) {
|
||||
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, long_payment_id);
|
||||
}
|
||||
/* or short payment ID */
|
||||
else if (!wallet2::parse_short_payment_id(payment_id_str, short_payment_id)) {
|
||||
cryptonote::set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, short_payment_id);
|
||||
}
|
||||
else {
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64-character string";
|
||||
er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 16 or 64 character string";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string extra_nonce;
|
||||
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id, encrypt_payment_id);
|
||||
|
||||
/* Append Payment ID data into extra */
|
||||
if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
@ -192,7 +197,7 @@ namespace tools
|
||||
}
|
||||
|
||||
// validate the transfer requested and populate dsts & extra
|
||||
if (!validate_transfer(req.destinations, req.payment_id, req.encrypt_payment_id, dsts, extra, er))
|
||||
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -250,7 +255,7 @@ namespace tools
|
||||
}
|
||||
|
||||
// validate the transfer requested and populate dsts & extra; RPC_TRANSFER::request and RPC_TRANSFER_SPLIT::request are identical types.
|
||||
if (!validate_transfer(req.destinations, req.payment_id, req.encrypt_payment_id, dsts, extra, er))
|
||||
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -342,14 +347,14 @@ namespace tools
|
||||
{
|
||||
try
|
||||
{
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
if (req.payment_id.empty())
|
||||
{
|
||||
crypto::generate_random_bytes(32, payment_id.data);
|
||||
crypto::generate_random_bytes(8, payment_id.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tools::wallet2::parse_payment_id(req.payment_id,payment_id))
|
||||
if (!tools::wallet2::parse_short_payment_id(req.payment_id,payment_id))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
er.message = "Invalid payment ID";
|
||||
@ -374,7 +379,7 @@ namespace tools
|
||||
try
|
||||
{
|
||||
cryptonote::account_public_address address;
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id;
|
||||
bool has_payment_id;
|
||||
|
||||
if(!get_account_integrated_address_from_str(address, has_payment_id, payment_id, m_wallet.testnet(), req.integrated_address))
|
||||
@ -488,6 +493,7 @@ namespace tools
|
||||
for (auto & payment_id_str : req.payment_ids)
|
||||
{
|
||||
crypto::hash payment_id;
|
||||
crypto::hash8 payment_id8;
|
||||
cryptonote::blobdata payment_id_blob;
|
||||
|
||||
// TODO - should the whole thing fail because of one bad id?
|
||||
@ -499,15 +505,23 @@ namespace tools
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sizeof(payment_id) != payment_id_blob.size())
|
||||
if(sizeof(payment_id) == payment_id_blob.size())
|
||||
{
|
||||
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_blob.data());
|
||||
}
|
||||
else if(sizeof(payment_id8) == payment_id_blob.size())
|
||||
{
|
||||
payment_id8 = *reinterpret_cast<const crypto::hash8*>(payment_id_blob.data());
|
||||
memcpy(payment_id.data, payment_id8.data, 8);
|
||||
memset(payment_id.data + 8, 0, 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||
er.message = "Payment ID has invalid size: " + payment_id_str;
|
||||
return false;
|
||||
}
|
||||
|
||||
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_blob.data());
|
||||
|
||||
std::list<wallet2::payment_details> payment_list;
|
||||
m_wallet.get_payments(payment_id, payment_list, req.min_block_height);
|
||||
|
||||
|
@ -79,7 +79,7 @@ namespace tools
|
||||
//json_rpc
|
||||
bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er);
|
||||
bool on_getaddress(const wallet_rpc::COMMAND_RPC_GET_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er);
|
||||
bool validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, const std::string payment_id, bool encrypt_payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
|
||||
bool validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, const std::string payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
|
||||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er);
|
||||
bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er);
|
||||
|
@ -97,7 +97,6 @@ namespace wallet_rpc
|
||||
uint64_t mixin;
|
||||
uint64_t unlock_time;
|
||||
std::string payment_id;
|
||||
bool encrypt_payment_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(destinations)
|
||||
@ -105,7 +104,6 @@ namespace wallet_rpc
|
||||
KV_SERIALIZE(mixin)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(encrypt_payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
@ -129,7 +127,6 @@ namespace wallet_rpc
|
||||
uint64_t unlock_time;
|
||||
std::string payment_id;
|
||||
bool new_algorithm;
|
||||
bool encrypt_payment_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(destinations)
|
||||
@ -138,7 +135,6 @@ namespace wallet_rpc
|
||||
KV_SERIALIZE(unlock_time)
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(new_algorithm)
|
||||
KV_SERIALIZE(encrypt_payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user