added unit tests for protocol_tx and check_output_types; bumped version to v0.9.6-rc1
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Salvium Zero v0.9.5
|
# Salvium Zero v0.9.6
|
||||||
|
|
||||||
Copyright (c) 2023-2024, Salvium
|
Copyright (c) 2023-2024, Salvium
|
||||||
Portions Copyright (c) 2014-2023, The Monero Project
|
Portions Copyright (c) 2014-2023, The Monero Project
|
||||||
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd salvium
|
cd salvium
|
||||||
git checkout v0.9.5
|
git checkout v0.9.6
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/salvium/salvium
|
git clone https://github.com/salvium/salvium
|
||||||
cd salvium
|
cd salvium
|
||||||
git checkout v0.9.5
|
git checkout v0.9.6
|
||||||
```
|
```
|
||||||
|
|
||||||
* Build:
|
* Build:
|
||||||
@@ -370,10 +370,10 @@ application.
|
|||||||
cd salvium
|
cd salvium
|
||||||
```
|
```
|
||||||
|
|
||||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.5'. If you don't care about the version and just want binaries from master, skip this step:
|
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.6'. If you don't care about the version and just want binaries from master, skip this step:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git checkout v0.9.5
|
git checkout v0.9.6
|
||||||
```
|
```
|
||||||
|
|
||||||
* If you are on a 64-bit system, run:
|
* If you are on a 64-bit system, run:
|
||||||
|
|||||||
@@ -1482,16 +1482,12 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
|||||||
|
|
||||||
// if nothing is created by this TX - check no money is included
|
// if nothing is created by this TX - check no money is included
|
||||||
CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 1, false, "coinbase protocol transaction in the block has no inputs");
|
CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 1, false, "coinbase protocol transaction in the block has no inputs");
|
||||||
size_t vout_size = b.protocol_tx.vout.size();
|
|
||||||
if (vout_size == 0) {
|
|
||||||
LOG_PRINT_L2("coinbase protocol transaction in the block has no outputs");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can we have matured STAKE transactions yet?
|
// Can we have matured STAKE transactions yet?
|
||||||
uint64_t stake_lock_period = get_config(m_nettype).STAKE_LOCK_PERIOD;
|
uint64_t stake_lock_period = get_config(m_nettype).STAKE_LOCK_PERIOD;
|
||||||
if (height <= stake_lock_period) {
|
if (height <= stake_lock_period) {
|
||||||
return false;
|
CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == 0, false, "protocol transaction in the block has outputs");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the staking data for the block that matured this time
|
// Get the staking data for the block that matured this time
|
||||||
@@ -1543,28 +1539,9 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
|||||||
// Check we have the correct number of entries
|
// Check we have the correct number of entries
|
||||||
CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == yield_payouts.size() + audit_payouts.size(), false, "Invalid number of outputs in protocol_tx - aborting");
|
CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == yield_payouts.size() + audit_payouts.size(), false, "Invalid number of outputs in protocol_tx - aborting");
|
||||||
|
|
||||||
// go through each vout and validate
|
|
||||||
//std::set<crypto::public_key> used_keys;
|
|
||||||
|
|
||||||
// Merge the yield and audit payouts into an iterable vector
|
// Merge the yield and audit payouts into an iterable vector
|
||||||
std::vector<std::pair<yield_tx_info, uint64_t>> payouts{yield_payouts};
|
std::vector<std::pair<yield_tx_info, uint64_t>> payouts{yield_payouts};
|
||||||
payouts.insert(payouts.end(), audit_payouts.begin(), audit_payouts.end());
|
payouts.insert(payouts.end(), audit_payouts.begin(), audit_payouts.end());
|
||||||
/*
|
|
||||||
if (hf_version >= HF_VERSION_AUDIT2) {
|
|
||||||
std::sort(payouts.begin(), payouts.end(), [](const auto& lhs, const auto& rhs) {
|
|
||||||
// If block heights are different (only possible with mixed AUDIT+STAKE) sort by them first
|
|
||||||
if (lhs.first.block_height < rhs.first.block_height) return true;
|
|
||||||
if (lhs.first.block_height > rhs.first.block_height) return false;
|
|
||||||
|
|
||||||
// If output keys are different, sort by them second
|
|
||||||
if (lhs.first.return_address < rhs.first.return_address) return true;
|
|
||||||
if (lhs.first.return_address > rhs.first.return_address) return false;
|
|
||||||
|
|
||||||
// If block heights _and_ output keys are same, sort by amount third
|
|
||||||
return lhs.second < rhs.second;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
size_t output_idx = 0;
|
size_t output_idx = 0;
|
||||||
for (auto it = payouts.begin(); it != payouts.end(); it++, output_idx++) {
|
for (auto it = payouts.begin(); it != payouts.end(); it++, output_idx++) {
|
||||||
@@ -1575,8 +1552,9 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
|||||||
CHECK_AND_ASSERT_MES(out_key == it->first.return_address, false, "Incorrect output key detected in protocol_tx");
|
CHECK_AND_ASSERT_MES(out_key == it->first.return_address, false, "Incorrect output key detected in protocol_tx");
|
||||||
|
|
||||||
// Verify the output amount
|
// Verify the output amount
|
||||||
CHECK_AND_ASSERT_MES(b.protocol_tx.vout[output_idx].amount == it->second, false, "Incorrect output amount detected in protocol_tx");
|
uint64_t expected_amount = it->second;
|
||||||
|
CHECK_AND_ASSERT_MES(b.protocol_tx.vout[output_idx].amount == expected_amount, false, "Incorrect output amount detected in protocol_tx. expected_amount: " << expected_amount);
|
||||||
|
|
||||||
// Verify the output asset type
|
// Verify the output asset type
|
||||||
std::string out_asset_type;
|
std::string out_asset_type;
|
||||||
cryptonote::get_output_asset_type(b.protocol_tx.vout[output_idx], out_asset_type);
|
cryptonote::get_output_asset_type(b.protocol_tx.vout[output_idx], out_asset_type);
|
||||||
@@ -4526,6 +4504,7 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
|
|||||||
}
|
}
|
||||||
yield_block_info ybi = m_yield_block_info_cache[idx];
|
yield_block_info ybi = m_yield_block_info_cache[idx];
|
||||||
if (ybi.slippage_total_this_block == 0) continue;
|
if (ybi.slippage_total_this_block == 0) continue;
|
||||||
|
if (ybi.locked_coins_tally == 0) continue;
|
||||||
|
|
||||||
boost::multiprecision::int128_t slippage_128 = ybi.slippage_total_this_block;
|
boost::multiprecision::int128_t slippage_128 = ybi.slippage_total_this_block;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
|
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
|
||||||
#define DEF_SALVIUM_VERSION "0.9.5a"
|
#define DEF_SALVIUM_VERSION "0.9.6-rc1"
|
||||||
#define DEF_MONERO_VERSION_TAG "release"
|
#define DEF_MONERO_VERSION_TAG "release"
|
||||||
#define DEF_MONERO_VERSION "0.18.3.3"
|
#define DEF_MONERO_VERSION "0.18.3.4"
|
||||||
#define DEF_MONERO_RELEASE_NAME "Zero"
|
#define DEF_MONERO_RELEASE_NAME "Zero"
|
||||||
#define DEF_MONERO_VERSION_FULL DEF_SALVIUM_VERSION "-" DEF_SALVIUM_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
|
#define DEF_MONERO_VERSION_FULL DEF_SALVIUM_VERSION "-" DEF_SALVIUM_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
|
||||||
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
|
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ set(unit_tests_sources
|
|||||||
expect.cpp
|
expect.cpp
|
||||||
fee.cpp
|
fee.cpp
|
||||||
json_serialization.cpp
|
json_serialization.cpp
|
||||||
get_tx_asset_types.cpp
|
check_output_types.cpp
|
||||||
|
protocol_tx.cpp
|
||||||
get_xtype_from_string.cpp
|
get_xtype_from_string.cpp
|
||||||
hashchain.cpp
|
hashchain.cpp
|
||||||
hmac_keccak.cpp
|
hmac_keccak.cpp
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// Copyright (c) 2025, Salvium (author: akil)
|
||||||
|
// Portions copyright (c) 2019-2021, Haven Protocol
|
||||||
|
// Portions copyright (c) 2016-2019, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
|
||||||
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
TEST(check_output_types, check_all)
|
||||||
|
{
|
||||||
|
transaction tx;
|
||||||
|
tx.version = 2;
|
||||||
|
uint8_t hf_version = 1;
|
||||||
|
|
||||||
|
// should only allow for single output for audit and stake txs
|
||||||
|
tx.type = transaction_type::AUDIT;
|
||||||
|
txout_to_key out; out.asset_type = "SAL";
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.pop_back();
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
tx.type = transaction_type::STAKE;
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.pop_back();
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
// should only allow txout_to_key or txout_to_tagged_key output types
|
||||||
|
txout_to_script tx_out_script;
|
||||||
|
tx.vout.push_back(tx_out {0, tx_out_script});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
txout_to_scripthash tx_out_scripthash;
|
||||||
|
tx.vout.push_back(tx_out {0, tx_out_scripthash});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
// should force all outputs to be of the same type
|
||||||
|
out.asset_type = "SAL";
|
||||||
|
txout_to_tagged_key out2; out2.asset_type = "SAL";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
tx.vout.push_back(tx_out {0, out2});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
// should only allow SAL outputs before version 6
|
||||||
|
out.asset_type = "SAL1";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
out.asset_type = "SAL";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
// after version 6, AUDIT txs still should only have SAL outputs
|
||||||
|
hf_version = 6;
|
||||||
|
tx.type = transaction_type::AUDIT;
|
||||||
|
|
||||||
|
out.asset_type = "SAL1";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
out.asset_type = "SAL";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
// after version 6, non-AUDIT txs should only allow SAL1 outputs
|
||||||
|
tx.type = transaction_type::PROTOCOL;
|
||||||
|
|
||||||
|
out.asset_type = "SAL";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
out.asset_type = "SAL1";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
tx.type = transaction_type::TRANSFER;
|
||||||
|
out.asset_type = "SAL";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_FALSE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
|
||||||
|
out.asset_type = "SAL1";
|
||||||
|
tx.vout.push_back(tx_out {0, out});
|
||||||
|
EXPECT_TRUE(check_output_types(tx, hf_version));
|
||||||
|
tx.vout.clear();
|
||||||
|
}
|
||||||
@@ -1,665 +0,0 @@
|
|||||||
// Copyright (c) 2019-2021, Haven Protocol
|
|
||||||
// Portions copyright (c) 2016-2019, The Monero Project
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
// materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
// used to endorse or promote products derived from this software without specific
|
|
||||||
// prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "cryptonote_core/cryptonote_tx_utils.cpp"
|
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
|
||||||
#include "vector"
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Regular transfers tests. Same asset type in input and output. Should be successful.
|
|
||||||
TEST(get_tx_asset_types, successful_on_1_input_type_1_output_type_FULM)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_to_key fulm_key;
|
|
||||||
tx.vin.push_back(fulm_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_to_key out_fulm;
|
|
||||||
out.target = out_fulm;
|
|
||||||
out1.target = out_fulm;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "FULM");
|
|
||||||
EXPECT_EQ(dest, "FULM");
|
|
||||||
}
|
|
||||||
TEST(get_tx_asset_types, successful_on_1_input_type_1_output_type_FUSD)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_to_key offshore_key;
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_offshore out_fusd;
|
|
||||||
out.target = out_fusd;
|
|
||||||
out1.target = out_fusd;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "FUSD");
|
|
||||||
EXPECT_EQ(dest, "FUSD");
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass on correct conversions
|
|
||||||
TEST(get_tx_asset_types, successful_offshore)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_to_key fulm_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_fulm;
|
|
||||||
cryptonote::txout_offshore out_fusd;
|
|
||||||
|
|
||||||
tx.vin.push_back(fulm_key);
|
|
||||||
tx.vin.push_back(fulm_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_fulm;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_fusd;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "FULM");
|
|
||||||
EXPECT_EQ(dest, "FUSD");
|
|
||||||
}
|
|
||||||
TEST(get_tx_asset_types, successful_onshore)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_onshore fusd_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_fulm;
|
|
||||||
cryptonote::txout_offshore out_fusd;
|
|
||||||
|
|
||||||
tx.vin.push_back(fusd_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_fulm;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_fusd;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
cryptonote::tx_out out2;
|
|
||||||
out2.target = out_fulm;
|
|
||||||
tx.vout.push_back(out2);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "FUSD");
|
|
||||||
EXPECT_EQ(dest, "FULM");
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - 3 or more
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_3_or_more)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - 1. XHV, 2. not XUSD
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_XHV_not_XUSD)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "XBTC";
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - 1. XUSD, 2. not XHV
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_XUSD_not_XHV)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "XBTC";
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(onshore_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - ins) 1. XHV 2. XUSD outs) only XHV
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_only_XHV_out)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - ins) 1. XHV 2. XUSD outs) only XUSD
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_only_XUSD_out)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - ins) 1. XHV 2. XUSD outs) 1. not XHV 2. not XUSD
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_out_not_XHV_not_XUSD)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
out_xasset.asset_type = "XEUR";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xasset;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - ins) 1. XHV 2. XUSD outs) 1. XHV 2. not XUSD
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_out_XHV_not_XUSD)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
out_xasset.asset_type = "XEUR";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_xasset;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on multiple input types - ins) 1. XHV 2. XUSD outs) 1. not XHV 2. XUSD
|
|
||||||
TEST(get_tx_asset_types, fail_on_multiple_input_types_out_XUSD_not_XHV)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
out_xasset.asset_type = "XEUR";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xasset;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass on multiple input types - ins) 1. XHV 2. XUSD outs) 1. XHV 2. XUSD
|
|
||||||
TEST(get_tx_asset_types, pass_on_multiple_input_types_onshore)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_offshore offshore_key;
|
|
||||||
cryptonote::txin_onshore onshore_key;
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(offshore_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on single input types with more than 2 output types
|
|
||||||
TEST(get_tx_asset_types, fail_single_input_and_more_than_2output_types)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_offshore out_offshore;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
out_xasset.asset_type = "XAU";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_offshore;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
cryptonote::tx_out out2;
|
|
||||||
out2.target = out_xasset;
|
|
||||||
tx.vout.push_back(out2);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on single input types & single output types & they are not equal
|
|
||||||
TEST(get_tx_asset_types, fail_single_input_single_output_types_are_not_equal)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "XAG";
|
|
||||||
out_xasset1.asset_type = "XAG";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xasset;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on single input types & 2 output types & none of the outputs matches inputs
|
|
||||||
TEST(get_tx_asset_types, none_of_output_mathces_input)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "XAG";
|
|
||||||
out_xasset1.asset_type = "XBTC";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xasset;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass on single input types & 2 output types & 1 of the outputs matches inputs, other ddesn't but not allowed. xhv -> xasset
|
|
||||||
// This case will expected to be caught by get_tx_type()
|
|
||||||
TEST(get_tx_asset_types, succesfuul_on_logical_input_output_but_not_allowed)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
cryptonote::txin_to_key xhv_key;
|
|
||||||
|
|
||||||
cryptonote::txout_to_key out_xhv;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset1.asset_type = "XBTC";
|
|
||||||
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
tx.vin.push_back(xhv_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
out.target = out_xhv;
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "XHV");
|
|
||||||
EXPECT_EQ(dest, "XBTC");
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass on 2 different xasset but source and dest are different. This case will expectedd to be catch by get_tx_type()
|
|
||||||
TEST(get_tx_asset_types, successful_on_logical_input_output_but_not_allowed_xassets)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "XBTC";
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "XBTC";
|
|
||||||
out_xasset1.asset_type = "XJPY";
|
|
||||||
out.target = out_xasset;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_TRUE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
|
|
||||||
EXPECT_EQ(source, "XBTC");
|
|
||||||
EXPECT_EQ(dest, "XJPY");
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on 2 different xasset
|
|
||||||
TEST(get_tx_asset_types, fail_on_2_different_xasset)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "XBTC";
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "XJPY";
|
|
||||||
out_xasset1.asset_type = "XJPY";
|
|
||||||
out.target = out_xasset;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on unknown asset types
|
|
||||||
TEST(get_tx_asset_types, fail_on_2_unknown_asset_types)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "xabc";
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "xabc";
|
|
||||||
out_xasset1.asset_type = "xabc";
|
|
||||||
out.target = out_xasset;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on unknown asset types
|
|
||||||
TEST(get_tx_asset_types, fail_on_2_unknown_asset_types_and_multiple_outs)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "xabc";
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "xabc";
|
|
||||||
out_xasset1.asset_type = "xbdc";
|
|
||||||
out.target = out_xasset;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// fail on unknown asset types
|
|
||||||
TEST(get_tx_asset_types, fail_on_1_unknown_asset_type)
|
|
||||||
{
|
|
||||||
cryptonote::transaction tx;
|
|
||||||
tx.version = 7;
|
|
||||||
|
|
||||||
cryptonote::txin_xasset xasset_key;
|
|
||||||
xasset_key.asset_type = "XBTC";
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
tx.vin.push_back(xasset_key);
|
|
||||||
|
|
||||||
cryptonote::tx_out out;
|
|
||||||
cryptonote::tx_out out1;
|
|
||||||
cryptonote::txout_xasset out_xasset;
|
|
||||||
cryptonote::txout_xasset out_xasset1;
|
|
||||||
out_xasset.asset_type = "XBTC";
|
|
||||||
out_xasset1.asset_type = "xbdc";
|
|
||||||
out.target = out_xasset;
|
|
||||||
out1.target = out_xasset1;
|
|
||||||
|
|
||||||
tx.vout.push_back(out);
|
|
||||||
tx.vout.push_back(out1);
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
std::string dest;
|
|
||||||
EXPECT_FALSE(get_tx_asset_types(tx, tx.hash, source, dest, false));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -0,0 +1,492 @@
|
|||||||
|
// Copyright (c) 2025, Salvium (author: akil)
|
||||||
|
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#define IN_UNIT_TESTS
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "cryptonote_core/blockchain.h"
|
||||||
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
|
#include "blockchain_db/testdb.h"
|
||||||
|
|
||||||
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
const uint64_t AMOUNT_BURNT = 1000000000000; // 1 SAL
|
||||||
|
const uint64_t STAKE_REWARD = 10000000000000; // 10 SAL
|
||||||
|
const uint64_t STAKE_PAYOUT = 216001000000000000; // 216k SAL
|
||||||
|
const uint64_t STAKE_LOCK_PERIOD = get_config(network_type::FAKECHAIN).STAKE_LOCK_PERIOD;
|
||||||
|
const auto AUDIT_HARD_FORKS = get_config(network_type::FAKECHAIN).AUDIT_HARD_FORKS;
|
||||||
|
|
||||||
|
class TestDB: public BaseTestDB {
|
||||||
|
public:
|
||||||
|
TestDB() { m_open = true; }
|
||||||
|
|
||||||
|
virtual uint64_t height() const override { return blocks.size(); }
|
||||||
|
virtual void add_block(const block& blk
|
||||||
|
, size_t block_weight
|
||||||
|
, uint64_t long_term_block_weight
|
||||||
|
, const difficulty_type& cumulative_difficulty
|
||||||
|
, const uint64_t& coins_generated
|
||||||
|
, uint64_t num_rct_outs
|
||||||
|
, oracle::asset_type_counts& cum_rct_by_asset_type
|
||||||
|
, const crypto::hash& blk_hash
|
||||||
|
, uint64_t slippage_total
|
||||||
|
, uint64_t yield_total
|
||||||
|
, uint64_t audit_total
|
||||||
|
, const network_type nettype
|
||||||
|
, yield_block_info& ybi
|
||||||
|
, audit_block_info& abi
|
||||||
|
) override {
|
||||||
|
uint64_t height = this->height();
|
||||||
|
yield_block_info ybi_prev = { 0, 0, 0, 0, 100 };
|
||||||
|
yield_block_info ybi_matured = { 0, 0, 0, 0, 100 };
|
||||||
|
if (height >= 1) {
|
||||||
|
ybi_prev = yield_info.at(height - 1);
|
||||||
|
}
|
||||||
|
if (height > STAKE_LOCK_PERIOD) {
|
||||||
|
ybi_matured = yield_info.at(height - STAKE_LOCK_PERIOD - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ybi.block_height = height;
|
||||||
|
ybi.locked_coins_this_block = yield_total;
|
||||||
|
ybi.slippage_total_this_block = slippage_total;
|
||||||
|
ybi.locked_coins_tally = yield_total + ybi_prev.locked_coins_tally - ybi_matured.locked_coins_this_block;
|
||||||
|
|
||||||
|
abi.locked_coins_this_block = audit_total;
|
||||||
|
abi.locked_coins_tally = audit_total;
|
||||||
|
abi.block_height = ybi.block_height;
|
||||||
|
|
||||||
|
yield_info[ybi.block_height] = ybi;
|
||||||
|
audit_info[abi.block_height] = abi;
|
||||||
|
blocks.push_back(blk);
|
||||||
|
}
|
||||||
|
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash, const bool miner_tx) override {
|
||||||
|
if (tx.first.type == transaction_type::STAKE || tx.first.type == transaction_type::AUDIT) {
|
||||||
|
yield_tx_info yti;
|
||||||
|
yti.tx_hash = tx_hash;
|
||||||
|
yti.block_height = (uint64_t)this->height();
|
||||||
|
yti.locked_coins = tx.first.amount_burnt;
|
||||||
|
yti.return_address = tx.first.return_address_list[0];
|
||||||
|
if (tx.first.type == transaction_type::STAKE) {
|
||||||
|
yield_txs[yti.block_height].push_back(yti);
|
||||||
|
} else if (tx.first.type == transaction_type::AUDIT) {
|
||||||
|
audit_txs[yti.block_height].push_back(yti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const override {
|
||||||
|
if (yield_info.count(height) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ybi = yield_info.at(height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual int get_audit_block_info(const uint64_t height, audit_block_info& abi) const override {
|
||||||
|
if (audit_info.count(height) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
abi = audit_info.at(height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const override {
|
||||||
|
if (yield_txs.count(height) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
yti_container = yield_txs.at(height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual int get_audit_tx_info(const uint64_t height, std::vector<yield_tx_info>& ati_container) const override {
|
||||||
|
if (audit_txs.count(height) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ati_container = audit_txs.at(height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const override {
|
||||||
|
crypto::hash hash = crypto::null_hash;
|
||||||
|
*(uint64_t*)&hash = height;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override {
|
||||||
|
uint64_t h = height();
|
||||||
|
crypto::hash top = crypto::null_hash;
|
||||||
|
if (h)
|
||||||
|
*(uint64_t*)&top = h - 1;
|
||||||
|
if (block_height)
|
||||||
|
*block_height = h - 1;
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<block> blocks;
|
||||||
|
std::map<uint64_t, yield_block_info> yield_info;
|
||||||
|
std::map<uint64_t, audit_block_info> audit_info;
|
||||||
|
std::map<uint64_t, std::vector<yield_tx_info>> yield_txs;
|
||||||
|
std::map<uint64_t, std::vector<yield_tx_info>> audit_txs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
transaction get_audit_tx() {
|
||||||
|
transaction audit_tx;
|
||||||
|
audit_tx.type = transaction_type::AUDIT;
|
||||||
|
|
||||||
|
std::string str = "audit-return-address-32-bytes32";
|
||||||
|
rct::key audit_return_address;
|
||||||
|
memcpy(audit_return_address.bytes, str.data(), sizeof(audit_return_address.bytes));
|
||||||
|
|
||||||
|
audit_tx.return_address_list.push_back(rct::rct2pk(audit_return_address));
|
||||||
|
audit_tx.amount_burnt = AMOUNT_BURNT;
|
||||||
|
audit_tx.version = 2;
|
||||||
|
|
||||||
|
return audit_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction get_stake_tx() {
|
||||||
|
transaction stake_tx;
|
||||||
|
stake_tx.type = transaction_type::STAKE;
|
||||||
|
|
||||||
|
std::string str = "stake-return-address-32-bytes32";
|
||||||
|
rct::key stake_return_address;
|
||||||
|
memcpy(stake_return_address.bytes, str.data(), sizeof(stake_return_address.bytes));
|
||||||
|
|
||||||
|
stake_tx.return_address_list.push_back(rct::rct2pk(stake_return_address));
|
||||||
|
stake_tx.amount_burnt = AMOUNT_BURNT;
|
||||||
|
stake_tx.version = 2;
|
||||||
|
|
||||||
|
return stake_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_block(Blockchain *bc, uint8_t num_audit_txs, uint8_t num_stake_txs) {
|
||||||
|
block b;
|
||||||
|
b.miner_tx.amount_burnt = STAKE_REWARD;
|
||||||
|
|
||||||
|
// add txs
|
||||||
|
std::vector<std::pair<transaction, blobdata>> audit_txs;
|
||||||
|
std::vector<std::pair<transaction, blobdata>> stake_txs;
|
||||||
|
for (int i = 0; i < num_audit_txs; i++) {
|
||||||
|
audit_txs.push_back(std::make_pair(get_audit_tx(), ""));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_stake_txs; i++) {
|
||||||
|
stake_txs.push_back(std::make_pair(get_stake_tx(), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge & add txs to the block
|
||||||
|
std::vector<std::pair<transaction, blobdata>> txs;
|
||||||
|
txs.insert(txs.end(), audit_txs.begin(), audit_txs.end());
|
||||||
|
txs.insert(txs.end(), stake_txs.begin(), stake_txs.end());
|
||||||
|
for (auto tx : txs) {
|
||||||
|
b.tx_hashes.push_back(tx.first.hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the block
|
||||||
|
yield_block_info ybi;
|
||||||
|
audit_block_info abi;
|
||||||
|
bc->get_db().add_block(
|
||||||
|
std::make_pair(b, ""),
|
||||||
|
0, 0, 1, 0,
|
||||||
|
txs,
|
||||||
|
network_type::FAKECHAIN, ybi, abi
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t progress_chain(Blockchain *bc, uint64_t num_blocks) {
|
||||||
|
for (int i = 0; i < num_blocks; i++) {
|
||||||
|
add_block(bc, 0, 0);
|
||||||
|
}
|
||||||
|
return bc->get_db().height();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(protocol_tx, validate)
|
||||||
|
{
|
||||||
|
const std::pair<uint8_t, uint64_t> hard_forks[3] = {
|
||||||
|
std::make_pair(1, 1),
|
||||||
|
std::make_pair(5, 1 * STAKE_LOCK_PERIOD),
|
||||||
|
std::make_pair(6, 2 * STAKE_LOCK_PERIOD),
|
||||||
|
};
|
||||||
|
const test_options test_options = {
|
||||||
|
hard_forks,
|
||||||
|
1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockchainAndPool bap;
|
||||||
|
Blockchain *bc = &bap.blockchain;
|
||||||
|
bool r = bc->init(new TestDB(), network_type::FAKECHAIN, true, &test_options, 0, NULL);
|
||||||
|
ASSERT_TRUE(r);
|
||||||
|
block b;
|
||||||
|
b.miner_tx.amount_burnt = STAKE_REWARD;
|
||||||
|
|
||||||
|
// ******** Special cases for genesis block(height is 0) ********
|
||||||
|
|
||||||
|
uint64_t height = bc->get_db().height() - 1;
|
||||||
|
uint8_t hf_version = bc->get_ideal_hard_fork_version(height);
|
||||||
|
|
||||||
|
// should have version 1
|
||||||
|
b.protocol_tx.version = 2;
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.version = 1;
|
||||||
|
|
||||||
|
// shouldn't have any inputs
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.clear();
|
||||||
|
|
||||||
|
// shouldn't have any outputs
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {0, txout_target_v{txout_to_key{}}});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// should now pass
|
||||||
|
EXPECT_TRUE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// ******** Normal cases ********
|
||||||
|
height = progress_chain(bc, 1);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// should only have 1 input
|
||||||
|
b.protocol_tx.vin.clear();
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.pop_back();
|
||||||
|
|
||||||
|
// should now pass with no output
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
EXPECT_TRUE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// height should be at least STAKE_LOCK_PERIOD if there is at least 1 output
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {10000, txout_target_v{txout_to_key{}}});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// reach to stake period height
|
||||||
|
height = progress_chain(bc, STAKE_LOCK_PERIOD);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// should fail if can't find a ybi & abi entry for the block
|
||||||
|
// (this will always pass since you can't add a block without ybi & abi entry)
|
||||||
|
|
||||||
|
// should fail if protocol tx outputs(1) > audit txs(0) + yield txs(0)
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {10000, txout_target_v{txout_to_key{}}});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// there shouldn't be outputs for audit txs in hf_version 5
|
||||||
|
EXPECT_EQ((int)bc->get_ideal_hard_fork_version(height), 5);
|
||||||
|
add_block(bc, 1, 1);
|
||||||
|
|
||||||
|
// progress chain until the audit payout
|
||||||
|
height = progress_chain(bc, AUDIT_HARD_FORKS.at(6).first);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// make outputs for audit tx
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {AMOUNT_BURNT, txout_target_v{txout_to_key{
|
||||||
|
get_audit_tx().return_address_list[0],
|
||||||
|
"SAL",
|
||||||
|
CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW
|
||||||
|
}}});
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// progress chain until the stake payout
|
||||||
|
height = progress_chain(bc, STAKE_LOCK_PERIOD - AUDIT_HARD_FORKS.at(6).first);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// make sure its paid out with correct asset type & amount
|
||||||
|
b.protocol_tx.vout.push_back(
|
||||||
|
tx_out {
|
||||||
|
STAKE_PAYOUT - 1, // wrong amount
|
||||||
|
txout_target_v{txout_to_key{
|
||||||
|
get_stake_tx().return_address_list[0],
|
||||||
|
"SAL1", // wrong asset type
|
||||||
|
CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW - 1 // wrong unlock window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix amount
|
||||||
|
b.protocol_tx.vout[0].amount = STAKE_PAYOUT;
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix asset type
|
||||||
|
boost::get<txout_to_key>(b.protocol_tx.vout[0].target).asset_type = "SAL";
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix unlock window
|
||||||
|
boost::get<txout_to_key>(b.protocol_tx.vout[0].target).unlock_time = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||||
|
EXPECT_TRUE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// audit txs should now be paid out in hf_version 6
|
||||||
|
EXPECT_EQ((int)bc->get_ideal_hard_fork_version(height), 6);
|
||||||
|
add_block(bc, 1, 0);
|
||||||
|
|
||||||
|
// progress chain until the payout
|
||||||
|
height = progress_chain(bc, AUDIT_HARD_FORKS.at(6).first);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// validate we get paid out with correct asset type & amount
|
||||||
|
b.protocol_tx.vout.push_back(
|
||||||
|
tx_out {
|
||||||
|
AMOUNT_BURNT - 1, // wrong amount
|
||||||
|
txout_target_v{txout_to_key{
|
||||||
|
get_audit_tx().return_address_list[0],
|
||||||
|
"SAL", // wrong asset type
|
||||||
|
CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW - 1 // wrong unlock window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix amount
|
||||||
|
b.protocol_tx.vout[0].amount = AMOUNT_BURNT;
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix asset type
|
||||||
|
boost::get<txout_to_key>(b.protocol_tx.vout[0].target).asset_type = "SAL1";
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// fix unlock window
|
||||||
|
boost::get<txout_to_key>(b.protocol_tx.vout[0].target).unlock_time = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||||
|
EXPECT_TRUE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// add a stake tx
|
||||||
|
add_block(bc, 0, 1);
|
||||||
|
|
||||||
|
// progress chain to add audit tx so that they both mature at the same time
|
||||||
|
height = progress_chain(bc, STAKE_LOCK_PERIOD - AUDIT_HARD_FORKS.at(6).first - 1);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// add an audit tx
|
||||||
|
add_block(bc, 1, 0);
|
||||||
|
|
||||||
|
// progress chain to mature height
|
||||||
|
height = progress_chain(bc, AUDIT_HARD_FORKS.at(6).first);
|
||||||
|
hf_version = bc->get_current_hard_fork_version();
|
||||||
|
|
||||||
|
// fail since protocol tx outputs(0) < audit txs(1) + yield txs(1)
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// audit tx output
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {AMOUNT_BURNT, txout_target_v{txout_to_key{
|
||||||
|
get_audit_tx().return_address_list[0],
|
||||||
|
"SAL1",
|
||||||
|
CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW
|
||||||
|
}}});
|
||||||
|
// fail since protocol tx outputs(1) < audit txs(1) + yield txs(1)
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// stake tx output
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {STAKE_PAYOUT, txout_target_v{txout_to_key{
|
||||||
|
get_stake_tx().return_address_list[0],
|
||||||
|
"SAL1",
|
||||||
|
CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW
|
||||||
|
}}});
|
||||||
|
// fail since protocol tx outputs[0] != stake_tx
|
||||||
|
EXPECT_FALSE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// swap the outputs
|
||||||
|
std::swap(b.protocol_tx.vout[0], b.protocol_tx.vout[1]);
|
||||||
|
EXPECT_TRUE(bc->validate_protocol_transaction(b, height, hf_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(protocol_tx, prevalidate)
|
||||||
|
{
|
||||||
|
tx_memory_pool* tx_pool = nullptr;
|
||||||
|
Blockchain blockchain(*tx_pool);
|
||||||
|
block b;
|
||||||
|
|
||||||
|
// ******** Special cases for genesis block(height is 0) ********
|
||||||
|
uint64_t height = 0;
|
||||||
|
uint8_t hf_version = 1;
|
||||||
|
|
||||||
|
// should have version 1
|
||||||
|
b.protocol_tx.version = 2;
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.version = 1;
|
||||||
|
|
||||||
|
// shouldn't have any inputs
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.clear();
|
||||||
|
|
||||||
|
// shouldn't have any outputs
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {0, txout_target_v{txout_to_key{}}});
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
|
||||||
|
// should now pass
|
||||||
|
EXPECT_TRUE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
|
||||||
|
// ******** Normal cases ********
|
||||||
|
height = 1;
|
||||||
|
hf_version = 1;
|
||||||
|
|
||||||
|
// should have version > 1
|
||||||
|
b.protocol_tx.version = 1;
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.version = 2;
|
||||||
|
|
||||||
|
// should have only 1 input
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.clear();
|
||||||
|
|
||||||
|
// should have only input type txin_gen
|
||||||
|
b.protocol_tx.vin.push_back(txin_to_key {0, "SAL", {}, crypto::key_image{}});
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vin.clear();
|
||||||
|
b.protocol_tx.vin.push_back(txin_gen{height});
|
||||||
|
|
||||||
|
// should have rct type NULL
|
||||||
|
b.protocol_tx.rct_signatures.type = rct::RCTTypeSalviumOne;
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.rct_signatures.type = rct::RCTTypeNull;
|
||||||
|
|
||||||
|
// txin_gen height must match block height
|
||||||
|
boost::get<txin_gen>(b.protocol_tx.vin[0]).height = height + 1;
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
boost::get<txin_gen>(b.protocol_tx.vin[0]).height = height;
|
||||||
|
|
||||||
|
// output amounts can't overflow
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {UINT64_MAX, txout_target_v{txout_to_key{}}});
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {1, txout_target_v{txout_to_key{}}});
|
||||||
|
EXPECT_FALSE(blockchain.prevalidate_protocol_transaction(b, height, hf_version));
|
||||||
|
b.protocol_tx.vout.clear();
|
||||||
|
b.protocol_tx.vout.push_back(tx_out {UINT64_MAX, txout_target_v{txout_to_key{}}});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user