Skip to content

Commit

Permalink
Merge pull request #238 from bubafistah/swap
Browse files Browse the repository at this point in the history
More swap wip
  • Loading branch information
bubafistah authored Sep 21, 2022
2 parents 2cde206 + a845f2f commit b3f28db
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 37 deletions.
17 changes: 16 additions & 1 deletion src/cryptonote_basic/cryptonote_basic_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using namespace epee;
#include "crypto/hash.h"
#include "common/int-util.h"
#include "common/dns_utils.h"
#include "cryptonote_core/swap_address.h"

#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "cn"
Expand Down Expand Up @@ -177,6 +178,10 @@ namespace cryptonote {
uint64_t address_prefix = testnet ?
config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX;

if(adr.is_swap_addr) {
address_prefix = SWAP_PUBLIC_ADDRESS_BASE58_PREFIX;
}

return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr));
}
//-----------------------------------------------------------------------
Expand Down Expand Up @@ -219,6 +224,11 @@ namespace cryptonote {
uint64_t integrated_address_prefix = testnet ?
config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;

uint64_t swap_address_prefix = SWAP_PUBLIC_ADDRESS_BASE58_PREFIX;
uint64_t integrated_swap_address_prefix = SWAP_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX;

adr.is_swap_addr = false;

if (2 * sizeof(public_address_outer_blob) != str.size())
{
blobdata data;
Expand All @@ -237,7 +247,12 @@ namespace cryptonote {
{
has_payment_id = false;
}
else {
else if (swap_address_prefix == prefix || integrated_swap_address_prefix == prefix) {
// Identify addr as swap addr
adr.is_swap_addr = true;
}
else
{
LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix << " or " << integrated_address_prefix);
return false;
}
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_basic/cryptonote_format_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ namespace cryptonote
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
bool get_payment_id_from_swap_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
bool get_swap_data_from_tx(const transaction& tx, const crypto::secret_key& sk, account_public_address& addr);
bool get_swapdata_encrypted_buff_from_extra_nonce(const std::string& extra_nonce, std::string& encrypted_buff);
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 is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index);
Expand Down
146 changes: 110 additions & 36 deletions src/cryptonote_core/cryptonote_tx_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,48 +169,54 @@ namespace cryptonote
keypair txkey = keypair::generate();
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
add_tx_pub_key_to_extra(tx, txkey.pub);

tx_key = txkey.sec;

// if we have a stealth payment id, find it and encrypt it with the tx key now
std::vector<tx_extra_field> tx_extra_fields;
if (parse_tx_extra(tx.extra, tx_extra_fields))
{
tx_extra_nonce extra_nonce;
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
if (is_swap_tx(tx, destinations)) {
encrypt_user_data_with_tx_secret_key(txkey.sec, tx.extra);
} else {
// Only encrypt payment id if this is not swap tx.
// if we have a stealth payment id, find it and encrypt it with the tx key now
std::vector<tx_extra_field> tx_extra_fields;
if (parse_tx_extra(tx.extra, tx_extra_fields))
{
crypto::hash8 payment_id = null_hash8;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
tx_extra_nonce extra_nonce;
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
{
LOG_PRINT_L2("Encrypting payment id " << payment_id);
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");
return false;
}

if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec))
{
LOG_ERROR("Failed to encrypt payment id");
return false;
}

std::string extra_nonce;
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
crypto::hash8 payment_id = null_hash8;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{
LOG_ERROR("Failed to add encrypted payment id to tx extra");
return false;
LOG_PRINT_L2("Encrypting payment id " << payment_id);
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");
return false;
}

if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec))
{
LOG_ERROR("Failed to encrypt payment id");
return false;
}

std::string extra_nonce;
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{
LOG_ERROR("Failed to add encrypted payment id to tx extra");
return false;
}
LOG_PRINT_L1("Encrypted payment ID: " << payment_id);
}
LOG_PRINT_L1("Encrypted payment ID: " << payment_id);
}
}
}
else
{
LOG_ERROR("Failed to parse tx extra");
return false;
else
{
LOG_ERROR("Failed to parse tx extra");
return false;
}
}

struct input_generation_context_data
Expand Down Expand Up @@ -289,10 +295,20 @@ namespace cryptonote

tx_out out;
out.amount = dst_entr.amount;
txout_to_key tk;
tk.key = out_eph_public_key;

txout_to_key tk = AUTO_VAL_INIT(tk);

if (dst_entr.addr.is_swap_addr) {
// Zero key for swap txs
// TODO Should probably do all address math only when neccessary
} else {
tk.key = out_eph_public_key;
}


out.target = tk;
tx.vout.push_back(out);

output_index++;
summary_outs_money += dst_entr.amount;
}
Expand Down Expand Up @@ -496,4 +512,62 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
bool is_swap_tx(const transaction& tx, const std::vector<tx_destination_entry>& destinations)
{
// a tx is a swap tx if it has at least one swap destination address (null_pkey output) AND swap info in extra.userdata
bool has_swap_destinations = false;

if (!destinations.empty())
{
for (auto& d : destinations)
{
if (d.addr.is_swap_addr)
{
has_swap_destinations = true;
break;
}
}
}
else
{
// use tx outputs if destinations was not provided
for (auto& o : tx.vout)
{
if (o.target.type() == typeid(txout_to_key) && boost::get<txout_to_key>(o.target).key == null_pkey)
{
has_swap_destinations = true;
break;
}
}
}

if (!has_swap_destinations)
return false; // No swap destinations

std::vector<cryptonote::tx_extra_field> extra_fields;

if (cryptonote::parse_tx_extra(tx.extra, extra_fields)) {
cryptonote::tx_extra_nonce extra_nonce;
if (find_tx_extra_field_by_type(extra_fields, extra_nonce)) {
std::string buff;
if(!cryptonote::get_swapdata_encrypted_buff_from_extra_nonce(extra_nonce.nonce, buff)) {
return false; // No swap data
}
} else {
return false; // No extra nonce
}
} else {
return false; // No extra
}

// there is a swap data, consider it as a swap tx
return true;
}
//---------------------------------------------------------------
bool is_swap_tx(const transaction& tx)
{
static std::vector<tx_destination_entry> empty_destinations;
return is_swap_tx(tx, empty_destinations);
}
//---------------------------------------------------------------
}
2 changes: 2 additions & 0 deletions src/cryptonote_core/cryptonote_tx_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ namespace cryptonote
, uint32_t nonce
);

bool is_swap_tx(const transaction& tx, const std::vector<tx_destination_entry>& destinations);
bool is_swap_tx(const transaction& tx);
}

BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0)
Expand Down
47 changes: 47 additions & 0 deletions tests/unit_tests/swap_test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "gtest/gtest.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "crypto/random.h"
#include "cryptonote_core/swap_address.h"

Expand All @@ -17,6 +18,46 @@ TEST(swap_address, swap_addr_extra_userdata_entry_from_addr)
ASSERT_TRUE(entry.is_checksum_valid());
}

TEST(swap_address, swap_parse_addr_from_str)
{
cryptonote::account_public_address new_chain_addr = AUTO_VAL_INIT(new_chain_addr);
cryptonote::account_public_address old_chain_addr = AUTO_VAL_INIT(old_chain_addr);
cryptonote::account_public_address invalid_addr = AUTO_VAL_INIT(invalid_addr);

std::string new_chain_addr_str = "iTxtQTLo1H8aGripS8mzG6c1Y3WcoSzzBFb4o7o2xUJmfJgLxxscutm9s9EMYXYnaaUN1E1XpMUHREcFbqAeSBzk61pYu2Tjhs";
std::string old_chain_addr_str = "iz5vDmtTSk7cyKdHr6Jv7vVSpx3thD6wGdXuyETg81KBfSVsZKeBewQUBF25uAtbJ3j9sHJzVHKfSNPu9aYbBnSv239GjxfER";
std::string invalid_addr_str = "n05vDmtTSk7cyKdHr6Jv7vVSpx3thD6wGdXuyETg81KBfSVsZKeBewQUBF25uAtbJ3j9sHJzVHKfSNPu9aYbBnSv239GjxfER";

bool has_payment_id;
crypto::hash8 payment_id;

ASSERT_TRUE(
cryptonote::get_account_integrated_address_from_str(new_chain_addr,
has_payment_id,
payment_id,
false,
new_chain_addr_str)
);
ASSERT_TRUE(new_chain_addr.is_swap_addr);

ASSERT_TRUE(
cryptonote::get_account_integrated_address_from_str(old_chain_addr,
has_payment_id,
payment_id,
false,
old_chain_addr_str)
);
ASSERT_FALSE(old_chain_addr.is_swap_addr);

ASSERT_FALSE(
cryptonote::get_account_integrated_address_from_str(invalid_addr,
has_payment_id,
payment_id,
false,
invalid_addr_str)
);
}

TEST(swap_tx, fill_tx_extra)
{
cryptonote::transaction tx = AUTO_VAL_INIT(tx);
Expand Down Expand Up @@ -55,4 +96,10 @@ TEST(swap_tx, fill_tx_extra)

ASSERT_EQ(swap_addr.m_spend_public_key, swap_addr2.m_spend_public_key);
ASSERT_EQ(swap_addr.m_view_public_key, swap_addr2.m_view_public_key);

vector<cryptonote::tx_destination_entry> fake_dest = {
cryptonote::tx_destination_entry(80085, swap_addr)
};

ASSERT_TRUE(cryptonote::is_swap_tx(tx, fake_dest));
}

0 comments on commit b3f28db

Please sign in to comment.