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:
moneromooo-monero 2015-08-09 10:09:39 +01:00
parent e40cfc4e29
commit a2d7a5fb49
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
15 changed files with 169 additions and 89 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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; }

View File

@ -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;

View File

@ -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);
}

View File

@ -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); }
}

View File

@ -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))
{

View File

@ -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);

View File

@ -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");

View File

@ -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()))
{

View File

@ -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);

View 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);

View File

@ -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);

View File

@ -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);

View File

@ -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()
};