diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 2362621de..8ef31df81 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -215,16 +215,19 @@ namespace cryptonote static constexpr size_t POS_KEY_INDEX = 0; static constexpr size_t POS_PROXY_KEY_INDEX = 1; static constexpr size_t WALLET_PROXY_KEY_INDEX = 2; + uint64_t auth_sample_height = 0; // block height for auth sample generation std::vector keys; BEGIN_SERIALIZE_OBJECT() FIELD(payment_id) + FIELD(auth_sample_height) FIELD(keys) END_SERIALIZE() bool operator== (const rta_header &other) const { return this->payment_id == other.payment_id - && this->keys == other.keys; + && this->keys == other.keys + && this->auth_sample_height == other.auth_sample_height; } }; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 2c6d01985..a5b228178 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -407,7 +407,7 @@ namespace cryptonote blocks_per_sync, sync_mode, fast_sync); r = m_blockchain_storage.init(db, m_testnet, test_options); - + m_mempool.set_stake_transaction_processor(&m_graft_stake_transaction_processor); r = m_mempool.init(); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 26ee1c164..75dc66a0c 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -46,6 +46,7 @@ #include "common/perf_timer.h" #include "crypto/hash.h" #include "stake_transaction_processor.h" +#include "graft_rta_config.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "txpool" @@ -1073,10 +1074,16 @@ namespace cryptonote { bool result = true; + if (rta_hdr.keys.size() == 0) { + MERROR("Failed to validate rta tx, missing auth sample keys for tx: " << txid ); + return false; + } +#if 0 // don't validate signatures for rta mining if (rta_hdr.keys.size() != rta_signs.size()) { MERROR("Failed to validate rta tx: " << txid << ", keys.size() != signatures.size()"); return false; } + for (const auto &rta_sign : rta_signs) { // check if key index is in range if (rta_sign.key_index >= rta_hdr.keys.size()) { @@ -1085,11 +1092,6 @@ namespace cryptonote break; } - result &= validate_supernode(m_blockchain.get_current_blockchain_height(), rta_hdr.keys[rta_sign.key_index]); - if (!result) { - MERROR("Failed to validate rta tx: " << epee::string_tools::pod_to_hex(txid) << ", key: " << rta_hdr.keys[rta_sign.key_index] << " doesn't belong to a valid supernode"); - break; - } result &= crypto::check_signature(txid, rta_hdr.keys[rta_sign.key_index], rta_sign.signature); if (!result) { @@ -1097,13 +1099,21 @@ namespace cryptonote break; } } +#endif + for (const crypto::public_key &key : rta_hdr.keys) { + result &= validate_supernode(rta_hdr.auth_sample_height, key); + if (!result) { + MERROR("Failed to validate rta tx: " << epee::string_tools::pod_to_hex(txid) << ", key: " << key << " doesn't belong to a valid supernode"); + break; + } + } + return result; } bool tx_memory_pool::validate_supernode(uint64_t height, const public_key &id) const { - // TODO: add pointer/reference to the StakeTransactionProcessor to this class and - // check if key belongs to a valid supernode - return true; + supernode_stake * stake = const_cast(m_stp->find_supernode_stake(height, epee::string_tools::pod_to_hex(id))); + return stake ? stake->amount >= config::graft::TIER1_STAKE_AMOUNT : false; }; } diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 47f54277c..7b06e2bc5 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -331,6 +331,11 @@ namespace cryptonote size_t validate(uint8_t version); + void set_stake_transaction_processor(StakeTransactionProcessor * arg) + { + m_stp = arg; + } + #define CURRENT_MEMPOOL_ARCHIVE_VER 11 #define CURRENT_MEMPOOL_TX_DETAILS_ARCHIVE_VER 12 @@ -460,7 +465,7 @@ namespace cryptonote bool validate_rta_tx(const crypto::hash &txid, const std::vector &rta_signs, const cryptonote::rta_header &rta_hdr) const; - bool validate_supernode(uint64_t heigh, const crypto::public_key &id) const; + bool validate_supernode(uint64_t height, const crypto::public_key &id) const; //TODO: confirm the below comments and investigate whether or not this // is the desired behavior @@ -508,6 +513,7 @@ namespace cryptonote std::unordered_set m_timed_out_transactions; Blockchain& m_blockchain; //!< reference to the Blockchain object + StakeTransactionProcessor * m_stp = nullptr; }; } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a6cd6baba..88f438c8f 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -558,6 +558,8 @@ namespace tools cryptonote::rta_header rta_header; rta_header.payment_id = req.graft_payment_id; + rta_header.auth_sample_height = req.auth_sample_height; + for (const std::string &key_str : req.supernode_keys) { crypto::public_key key; if (!epee::string_tools::hex_to_pod(key_str, key)) { @@ -583,6 +585,9 @@ namespace tools return false; } + if (!req.do_not_relay) + m_wallet->commit_tx(ptx_vector); + // populate response with tx hash res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx)); if (req.get_tx_key) @@ -591,9 +596,12 @@ namespace tools } res.fee = ptx_vector.back().fee; - cryptonote::blobdata blob; - tx_to_blob(ptx_vector.back().tx, blob); - res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob); + if (req.get_tx_hex) + { + cryptonote::blobdata blob; + tx_to_blob(ptx_vector.back().tx, blob); + res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob); + } // return encrypted tx key std::string encrypted_key_blob; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index b19fc07fe..c0bd73b32 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -210,7 +210,7 @@ namespace wallet_rpc { std::list supernode_keys; std::string graft_payment_id; - + uint64_t auth_sample_height; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(destinations) KV_SERIALIZE(priority) @@ -220,6 +220,7 @@ namespace wallet_rpc KV_SERIALIZE(get_tx_key) KV_SERIALIZE(supernode_keys) KV_SERIALIZE(graft_payment_id) + KV_SERIALIZE(auth_sample_height) KV_SERIALIZE_OPT(do_not_relay, false) KV_SERIALIZE_OPT(get_tx_hex, false) END_KV_SERIALIZE_MAP() diff --git a/tests/supernode_tests/graft_wallet_tests.cpp b/tests/supernode_tests/graft_wallet_tests.cpp index 56128839d..20fc7c9d2 100644 --- a/tests/supernode_tests/graft_wallet_tests.cpp +++ b/tests/supernode_tests/graft_wallet_tests.cpp @@ -391,6 +391,7 @@ TEST_F(RtaRpcTest, TransfersRtaTransaction) req.id = epee::serialization::storage_entry(0); req.params.graft_payment_id = "test-test-test"; + req.params.auth_sample_height = 243285; req.params.priority = 0; req.params.mixin = 7; req.params.get_tx_key = 1; @@ -436,8 +437,9 @@ TEST_F(RtaRpcTest, TransfersRtaTransaction) bool r = net_utils::invoke_http_json("/json_rpc", req, res, http_client_wallet); ASSERT_TRUE(r); + ASSERT_FALSE(res.result.tx_hash.empty()); - +#if 0 cryptonote::transaction tx; std::string tx_blob; ASSERT_TRUE(string_tools::parse_hexstr_to_binbuff(res.result.tx_blob, tx_blob)); @@ -487,4 +489,6 @@ TEST_F(RtaRpcTest, TransfersRtaTransaction) r = net_utils::invoke_http_json("/sendrawtransaction", tx_req, tx_resp, http_client_daemon); ASSERT_TRUE(r); ASSERT_FALSE(tx_resp.rta_validation_failed); +#endif + }