Merge pull request #17 from salvium/add-sal1-treasury-mint

sal1 treasury mint
This commit is contained in:
akildemir
2025-05-06 12:01:47 +03:00
committed by GitHub
11 changed files with 277 additions and 18 deletions
+78 -3
View File
@@ -86,6 +86,9 @@
#define PREMINE_AMOUNT_UPFRONT ((uint64_t)650000000000000ull) // 3.4% of MONEY_SUPPLY #define PREMINE_AMOUNT_UPFRONT ((uint64_t)650000000000000ull) // 3.4% of MONEY_SUPPLY
#define PREMINE_AMOUNT_MONTHLY ((uint64_t)65000000000000ull) // 8.6%/24 of MONEY_SUPPLY #define PREMINE_AMOUNT_MONTHLY ((uint64_t)65000000000000ull) // 8.6%/24 of MONEY_SUPPLY
#define TREASURY_SAL1_MINT_AMOUNT ((uint64_t)65000000000000ull) // 650K
#define TREASURY_SAL1_MINT_COUNT 16 // 16 times
#define DIFFICULTY_TARGET_V2 120 // seconds #define DIFFICULTY_TARGET_V2 120 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork #define DIFFICULTY_TARGET_V1 60 // seconds - before first fork
#define DIFFICULTY_WINDOW_V2 70 // blocks #define DIFFICULTY_WINDOW_V2 70 // blocks
@@ -238,6 +241,7 @@
#define HF_VERSION_AUDIT1_PAUSE 7 #define HF_VERSION_AUDIT1_PAUSE 7
#define HF_VERSION_AUDIT2 8 #define HF_VERSION_AUDIT2 8
#define HF_VERSION_AUDIT2_PAUSE 9 #define HF_VERSION_AUDIT2_PAUSE 9
#define HF_VERSION_TREASURY_SAL1_MINT 10
#define HF_VERSION_REQUIRE_VIEW_TAGS 255 #define HF_VERSION_REQUIRE_VIEW_TAGS 255
#define HF_VERSION_ENABLE_CONVERT 255 #define HF_VERSION_ENABLE_CONVERT 255
@@ -301,9 +305,30 @@ namespace config
}; };
const uint64_t STAKE_LOCK_PERIOD = 30*24*30; const uint64_t STAKE_LOCK_PERIOD = 30*24*30;
const uint64_t TREASURY_SAL1_MINT_PERIOD = 30*24*30; // 1 month of blocks
std::string const TREASURY_ADDRESS = "SaLvdZR6w1A21sf2Wh6jYEh1wzY4GSbT7RX6FjyPsnLsffWLrzFQeXUXJcmBLRWDzZC2YXeYe5t7qKsnrg9FpmxmEcxPHsEYfqA"; std::string const TREASURY_ADDRESS = "SaLvdZR6w1A21sf2Wh6jYEh1wzY4GSbT7RX6FjyPsnLsffWLrzFQeXUXJcmBLRWDzZC2YXeYe5t7qKsnrg9FpmxmEcxPHsEYfqA";
// treasury payout {tx-key, output-key} pairs
const std::vector<std::pair<std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_KEYS = {
{"a1bdd1da651fbbb845232816e1aa2d4ff29b790f10bbd4f574a012f1199e15a4", "b0733ab6f251b16458efa9ebb3fb99bd54d43173b5768fe9ffc42e0fe46ae3a8"},
{"47996eccbcc078b06d0f6ece37bf3a700c2bd60adfdd898b22096f16a9ad315c", "fd6bcceb4799ee067d59b97a6f66a0f9a70f134220259d3b4d6a2278ba4aca4c"},
{"a3e6754a849b80c21a77e6065fefdae29eeeabf17c407453356244a00545bdb8", "3d395454df1452d715d27190e022b20395871c99af578f7251c3f9752e0274a6"},
{"0d5e97a910e0f9c606ad9c711b6595aaed142d857cde2efa519112b9a29240d5", "56c29e28bdcf4f20b4b45906b93ae7c4bf9ee82e18cd45543cb69a14ce5efb88"},
{"495fa363de88915aa8b74818c4b80715a882a688b4f7127ab7cd3b6885f3567a", "d42dfe0da5579c82e8255eba8c0a17170023f14a6a5030da6abf9f10abb52cbb"},
{"85ea10ec40390e4f406446fb519e974d89536154045c6df28bb3b538b254e20d", "0ce2b7dd3a8ce8b596889dac8081a62f98fd70f1f043944ab4ac592c3c59e77b"},
{"40f201b38a319dda81e7201e57fea7924067a4a332ed71b8e51ec29ac2d67310", "8289aa6963b98d1034e94eae55d8be6b33d0a88f14f174ebcbaec70837986c7c"},
{"c5a648cc7846341357b7b4653a58f9eb4800d88b5de587bceec7a5c28f98d05a", "3f308a203845d88e5e728fcebcdcea1f90e2f424d461617993c672a6138ad2d8"},
{"4c51d6550b8eeb6cc8f0d395cc83a5f90ec2a4d86501b3f68da48d618ccf5711", "53f0bd8cebeefb3a88fffa5d7f6ad43d4712608ded561732467ca499df940454"},
{"ce2f5d82118fed03d5e269e285fc16189a6cd34f38999e5c055a5dea5fce61bc", "f7fc6948b194d9bd6f2df6ecb83f04e6c8d1a2556a63fedb310a4631fe1bfc42"},
{"6248028fd77fb02b5c6ea72dea10b417891a2da7aaf9565aed382e063b4981a3", "63986e1177499bdb23cd49afb519ec18f38cb1b0c386220b376d8ffdc2e37890"},
{"6adcb695aa5d6d01133c68900f29e501e9549816e827ea0c164bbc78f3534dd6", "6a440ccb18f5e703e8000de3865ac40d4c18f081270d32eef377dc831f28d8d0"},
{"b97a4d2259480f34f20e41c489ab5c2e5ae9ee84d8672a7eff8012f2260e121e", "e6eb9147ff40e22209d321d0f1bfbfe20acf5ceb6b9d0bfb13688ad28aa1232e"},
{"4fd214602a36902f22d16927244c456e8cc5a406a9570131f138a028214ffdf0", "34060b8bd96009b9b298280ebd84fa9587fa8c9df6fb5ad0270fb6cd2098885c"},
{"9d60178ec6d6599d7a31298f2559fb9c3111f2c70494b3a1638db877ea55b808", "7985ed03856a929663e954738d0938713407717835f760c7ca4d54844a128c91"},
{"cd65718eab234bf419332e53bd2f48e2ade70af48c5e126ab5080321e1493dfc", "581cb4cca7a0a029ee2cac51dfc00a0c3a657d2eaf67ed3c6ae7bacc11b4f007"},
};
// Hash domain separators // Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus"; const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus";
@@ -381,6 +406,7 @@ namespace config
}; };
const uint64_t STAKE_LOCK_PERIOD = 20; const uint64_t STAKE_LOCK_PERIOD = 20;
const uint64_t TREASURY_SAL1_MINT_PERIOD = 20;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}}; std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}};
@@ -390,6 +416,26 @@ namespace config
"-----END PUBLIC KEY-----\n"; "-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "SaLvTyLFta9BiAXeUfFkKvViBkFt4ay5nEUBpWyDKewYggtsoxBbtCUVqaBjtcCDyY1euun8Giv7LLEgvztuurLo5a6Km1zskZn36"; std::string const TREASURY_ADDRESS = "SaLvTyLFta9BiAXeUfFkKvViBkFt4ay5nEUBpWyDKewYggtsoxBbtCUVqaBjtcCDyY1euun8Giv7LLEgvztuurLo5a6Km1zskZn36";
// treasury payout {tx-key, output-key} pairs
const std::vector<std::pair<std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_KEYS = {
{"a1bdd1da651fbbb845232816e1aa2d4ff29b790f10bbd4f574a012f1199e15a4", "b0733ab6f251b16458efa9ebb3fb99bd54d43173b5768fe9ffc42e0fe46ae3a8"},
{"47996eccbcc078b06d0f6ece37bf3a700c2bd60adfdd898b22096f16a9ad315c", "fd6bcceb4799ee067d59b97a6f66a0f9a70f134220259d3b4d6a2278ba4aca4c"},
{"a3e6754a849b80c21a77e6065fefdae29eeeabf17c407453356244a00545bdb8", "3d395454df1452d715d27190e022b20395871c99af578f7251c3f9752e0274a6"},
{"0d5e97a910e0f9c606ad9c711b6595aaed142d857cde2efa519112b9a29240d5", "56c29e28bdcf4f20b4b45906b93ae7c4bf9ee82e18cd45543cb69a14ce5efb88"},
{"495fa363de88915aa8b74818c4b80715a882a688b4f7127ab7cd3b6885f3567a", "d42dfe0da5579c82e8255eba8c0a17170023f14a6a5030da6abf9f10abb52cbb"},
{"85ea10ec40390e4f406446fb519e974d89536154045c6df28bb3b538b254e20d", "0ce2b7dd3a8ce8b596889dac8081a62f98fd70f1f043944ab4ac592c3c59e77b"},
{"40f201b38a319dda81e7201e57fea7924067a4a332ed71b8e51ec29ac2d67310", "8289aa6963b98d1034e94eae55d8be6b33d0a88f14f174ebcbaec70837986c7c"},
{"c5a648cc7846341357b7b4653a58f9eb4800d88b5de587bceec7a5c28f98d05a", "3f308a203845d88e5e728fcebcdcea1f90e2f424d461617993c672a6138ad2d8"},
{"4c51d6550b8eeb6cc8f0d395cc83a5f90ec2a4d86501b3f68da48d618ccf5711", "53f0bd8cebeefb3a88fffa5d7f6ad43d4712608ded561732467ca499df940454"},
{"ce2f5d82118fed03d5e269e285fc16189a6cd34f38999e5c055a5dea5fce61bc", "f7fc6948b194d9bd6f2df6ecb83f04e6c8d1a2556a63fedb310a4631fe1bfc42"},
{"6248028fd77fb02b5c6ea72dea10b417891a2da7aaf9565aed382e063b4981a3", "63986e1177499bdb23cd49afb519ec18f38cb1b0c386220b376d8ffdc2e37890"},
{"6adcb695aa5d6d01133c68900f29e501e9549816e827ea0c164bbc78f3534dd6", "6a440ccb18f5e703e8000de3865ac40d4c18f081270d32eef377dc831f28d8d0"},
{"b97a4d2259480f34f20e41c489ab5c2e5ae9ee84d8672a7eff8012f2260e121e", "e6eb9147ff40e22209d321d0f1bfbfe20acf5ceb6b9d0bfb13688ad28aa1232e"},
{"4fd214602a36902f22d16927244c456e8cc5a406a9570131f138a028214ffdf0", "34060b8bd96009b9b298280ebd84fa9587fa8c9df6fb5ad0270fb6cd2098885c"},
{"9d60178ec6d6599d7a31298f2559fb9c3111f2c70494b3a1638db877ea55b808", "7985ed03856a929663e954738d0938713407717835f760c7ca4d54844a128c91"},
{"cd65718eab234bf419332e53bd2f48e2ade70af48c5e126ab5080321e1493dfc", "581cb4cca7a0a029ee2cac51dfc00a0c3a657d2eaf67ed3c6ae7bacc11b4f007"},
};
} }
namespace stagenet namespace stagenet
@@ -409,6 +455,7 @@ namespace config
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> AUDIT_HARD_FORKS = { {HF_VERSION_AUDIT1, {30, {"SAL", "SAL1"}}} }; const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> AUDIT_HARD_FORKS = { {HF_VERSION_AUDIT1, {30, {"SAL", "SAL1"}}} };
const uint64_t STAKE_LOCK_PERIOD = 20; const uint64_t STAKE_LOCK_PERIOD = 20;
const uint64_t TREASURY_SAL1_MINT_PERIOD = 20;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}}; std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}};
@@ -418,6 +465,26 @@ namespace config
"-----END PUBLIC KEY-----\n"; "-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A"; std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
// treasury payout {tx-key, output-key} pairs
const std::vector<std::pair<std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_KEYS = {
{"a1bdd1da651fbbb845232816e1aa2d4ff29b790f10bbd4f574a012f1199e15a4", "b0733ab6f251b16458efa9ebb3fb99bd54d43173b5768fe9ffc42e0fe46ae3a8"},
{"47996eccbcc078b06d0f6ece37bf3a700c2bd60adfdd898b22096f16a9ad315c", "fd6bcceb4799ee067d59b97a6f66a0f9a70f134220259d3b4d6a2278ba4aca4c"},
{"a3e6754a849b80c21a77e6065fefdae29eeeabf17c407453356244a00545bdb8", "3d395454df1452d715d27190e022b20395871c99af578f7251c3f9752e0274a6"},
{"0d5e97a910e0f9c606ad9c711b6595aaed142d857cde2efa519112b9a29240d5", "56c29e28bdcf4f20b4b45906b93ae7c4bf9ee82e18cd45543cb69a14ce5efb88"},
{"495fa363de88915aa8b74818c4b80715a882a688b4f7127ab7cd3b6885f3567a", "d42dfe0da5579c82e8255eba8c0a17170023f14a6a5030da6abf9f10abb52cbb"},
{"85ea10ec40390e4f406446fb519e974d89536154045c6df28bb3b538b254e20d", "0ce2b7dd3a8ce8b596889dac8081a62f98fd70f1f043944ab4ac592c3c59e77b"},
{"40f201b38a319dda81e7201e57fea7924067a4a332ed71b8e51ec29ac2d67310", "8289aa6963b98d1034e94eae55d8be6b33d0a88f14f174ebcbaec70837986c7c"},
{"c5a648cc7846341357b7b4653a58f9eb4800d88b5de587bceec7a5c28f98d05a", "3f308a203845d88e5e728fcebcdcea1f90e2f424d461617993c672a6138ad2d8"},
{"4c51d6550b8eeb6cc8f0d395cc83a5f90ec2a4d86501b3f68da48d618ccf5711", "53f0bd8cebeefb3a88fffa5d7f6ad43d4712608ded561732467ca499df940454"},
{"ce2f5d82118fed03d5e269e285fc16189a6cd34f38999e5c055a5dea5fce61bc", "f7fc6948b194d9bd6f2df6ecb83f04e6c8d1a2556a63fedb310a4631fe1bfc42"},
{"6248028fd77fb02b5c6ea72dea10b417891a2da7aaf9565aed382e063b4981a3", "63986e1177499bdb23cd49afb519ec18f38cb1b0c386220b376d8ffdc2e37890"},
{"6adcb695aa5d6d01133c68900f29e501e9549816e827ea0c164bbc78f3534dd6", "6a440ccb18f5e703e8000de3865ac40d4c18f081270d32eef377dc831f28d8d0"},
{"b97a4d2259480f34f20e41c489ab5c2e5ae9ee84d8672a7eff8012f2260e121e", "e6eb9147ff40e22209d321d0f1bfbfe20acf5ceb6b9d0bfb13688ad28aa1232e"},
{"4fd214602a36902f22d16927244c456e8cc5a406a9570131f138a028214ffdf0", "34060b8bd96009b9b298280ebd84fa9587fa8c9df6fb5ad0270fb6cd2098885c"},
{"9d60178ec6d6599d7a31298f2559fb9c3111f2c70494b3a1638db877ea55b808", "7985ed03856a929663e954738d0938713407717835f760c7ca4d54844a128c91"},
{"cd65718eab234bf419332e53bd2f48e2ade70af48c5e126ab5080321e1493dfc", "581cb4cca7a0a029ee2cac51dfc00a0c3a657d2eaf67ed3c6ae7bacc11b4f007"},
};
} }
} }
@@ -445,8 +512,10 @@ namespace cryptonote
std::array<std::string, 3> const ORACLE_URLS; std::array<std::string, 3> const ORACLE_URLS;
std::string const ORACLE_PUBLIC_KEY; std::string const ORACLE_PUBLIC_KEY;
uint64_t const STAKE_LOCK_PERIOD; uint64_t const STAKE_LOCK_PERIOD;
uint64_t TREASURY_SAL1_MINT_PERIOD;
std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> const AUDIT_HARD_FORKS; std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> const AUDIT_HARD_FORKS;
std::string TREASURY_ADDRESS; std::string TREASURY_ADDRESS;
std::vector<std::pair<std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_KEYS;
}; };
inline const config_t& get_config(network_type nettype) inline const config_t& get_config(network_type nettype)
{ {
@@ -463,8 +532,10 @@ namespace cryptonote
::config::ORACLE_URLS, ::config::ORACLE_URLS,
::config::ORACLE_PUBLIC_KEY, ::config::ORACLE_PUBLIC_KEY,
::config::STAKE_LOCK_PERIOD, ::config::STAKE_LOCK_PERIOD,
::config::TREASURY_SAL1_MINT_PERIOD,
::config::AUDIT_HARD_FORKS, ::config::AUDIT_HARD_FORKS,
::config::TREASURY_ADDRESS ::config::TREASURY_ADDRESS,
::config::TREASURY_SAL1_MINT_OUTPUT_KEYS
}; };
static const config_t testnet = { static const config_t testnet = {
::config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, ::config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -479,8 +550,10 @@ namespace cryptonote
::config::testnet::ORACLE_URLS, ::config::testnet::ORACLE_URLS,
::config::testnet::ORACLE_PUBLIC_KEY, ::config::testnet::ORACLE_PUBLIC_KEY,
::config::testnet::STAKE_LOCK_PERIOD, ::config::testnet::STAKE_LOCK_PERIOD,
::config::testnet::TREASURY_SAL1_MINT_PERIOD,
::config::testnet::AUDIT_HARD_FORKS, ::config::testnet::AUDIT_HARD_FORKS,
::config::testnet::TREASURY_ADDRESS ::config::testnet::TREASURY_ADDRESS,
::config::testnet::TREASURY_SAL1_MINT_OUTPUT_KEYS
}; };
static const config_t stagenet = { static const config_t stagenet = {
::config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, ::config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -495,8 +568,10 @@ namespace cryptonote
::config::stagenet::ORACLE_URLS, ::config::stagenet::ORACLE_URLS,
::config::stagenet::ORACLE_PUBLIC_KEY, ::config::stagenet::ORACLE_PUBLIC_KEY,
::config::stagenet::STAKE_LOCK_PERIOD, ::config::stagenet::STAKE_LOCK_PERIOD,
::config::stagenet::TREASURY_SAL1_MINT_PERIOD,
::config::stagenet::AUDIT_HARD_FORKS, ::config::stagenet::AUDIT_HARD_FORKS,
::config::stagenet::TREASURY_ADDRESS ::config::stagenet::TREASURY_ADDRESS,
::config::stagenet::TREASURY_SAL1_MINT_OUTPUT_KEYS
}; };
switch (nettype) switch (nettype)
{ {
+65 -4
View File
@@ -1416,14 +1416,74 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh
return true; return true;
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
std::tuple<bool, size_t> Blockchain::validate_treasury_payout(const transaction& tx, const uint64_t payout_index, uint8_t hf_version) const {
// find the treasury output
const auto treasury_output_keys = get_config(m_nettype).TREASURY_SAL1_MINT_OUTPUT_KEYS;
const auto expected_output_key = treasury_output_keys[payout_index].second;
const auto &output = std::find_if(tx.vout.begin(), tx.vout.end(), [&expected_output_key](const tx_out &o) {
std::string output_key;
if (o.target.type() == typeid(txout_to_key)) {
output_key = epee::string_tools::pod_to_hex(boost::get<txout_to_key>(o.target).key);
} else if (o.target.type() == typeid(txout_to_tagged_key)) {
output_key = epee::string_tools::pod_to_hex(boost::get<txout_to_tagged_key>(o.target).key);
} else {
return false;
}
return output_key == expected_output_key;
});
if (output == tx.vout.end()) {
MERROR_VER("Miner transaction does not contain treasury output");
return {false, 0};
}
if (output->amount != TREASURY_SAL1_MINT_AMOUNT) {
MERROR_VER("Miner transaction contains treasury output with invalid amount");
return {false, 0};
}
if (output->target.type() != typeid(txout_to_key)) {
MERROR_VER("Miner transaction contains treasury output with invalid target type");
return {false, 0};
}
if (boost::get<txout_to_key>(output->target).unlock_time != CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW) {
MERROR_VER("Miner transaction contains treasury output with invalid target key");
return {false, 0};
}
return {true, output - tx.vout.begin()};
}
//------------------------------------------------------------------
// This function validates the miner transaction reward // This function validates the miner transaction reward
bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_block_weight, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins, bool &partial_block_reward, uint8_t version) bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_block_weight, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins, bool &partial_block_reward, uint8_t version)
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
// validate treasury payout
size_t treasury_index_in_tx_outputs;
auto [treasury_payout_exist, treasury_payout_index] = check_treasury_payout(m_nettype, boost::get<txin_gen>(b.miner_tx.vin[0]).height, m_hardfork->get_hardforks(), version);
if (treasury_payout_exist) {
// check the treasury payout
auto [valid, index_in_tx_outputs] = validate_treasury_payout(b.miner_tx, treasury_payout_index, version);
if (!valid) {
MERROR_VER("Miner transaction treasury output was invalid");
return false;
}
treasury_index_in_tx_outputs = index_in_tx_outputs;
}
//validate reward //validate reward
uint64_t money_in_use = 0; uint64_t money_in_use = 0;
for (auto& o: b.miner_tx.vout) for(size_t i = 0; i < b.miner_tx.vout.size(); i++)
money_in_use += o.amount; {
// skip the treasury output
if (treasury_payout_exist && (i == treasury_index_in_tx_outputs)) {
continue;
}
money_in_use += b.miner_tx.vout[i].amount;
}
partial_block_reward = false; partial_block_reward = false;
switch (version) { switch (version) {
@@ -1436,6 +1496,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
case HF_VERSION_AUDIT1_PAUSE: case HF_VERSION_AUDIT1_PAUSE:
case HF_VERSION_AUDIT2: case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE: case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_TREASURY_SAL1_MINT:
if (b.miner_tx.amount_burnt > 0) { if (b.miner_tx.amount_burnt > 0) {
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt"); CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
money_in_use += b.miner_tx.amount_burnt; money_in_use += b.miner_tx.amount_burnt;
@@ -2002,7 +2063,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight //make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
uint8_t hf_version = b.major_version; uint8_t hf_version = b.major_version;
size_t max_outs = hf_version >= 4 ? 1 : 11; size_t max_outs = hf_version >= 4 ? 1 : 11;
bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version); bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance"); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx); size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE) #if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
@@ -2011,7 +2072,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
#endif #endif
for (size_t try_count = 0; try_count != 10; ++try_count) for (size_t try_count = 0; try_count != 10; ++try_count)
{ {
r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version); r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, m_nettype, m_hardfork->get_hardforks(), ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance"); CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
size_t coinbase_weight = get_transaction_weight(b.miner_tx); size_t coinbase_weight = get_transaction_weight(b.miner_tx);
+10
View File
@@ -1492,6 +1492,16 @@ namespace cryptonote
*/ */
difficulty_type get_next_difficulty_for_alternative_chain(const std::list<block_extended_info>& alt_chain, block_extended_info& bei) const; difficulty_type get_next_difficulty_for_alternative_chain(const std::list<block_extended_info>& alt_chain, block_extended_info& bei) const;
/**
* @brief validates the treasury payout for a block
* @param tx transaction to validate
* @param payout_index the index of the payout to check
* @param hf_version the consensus rules to apply
*
* @return bool indicating payout valid, and the index of the output within miner transaction outputs.
*/
std::tuple<bool, size_t> validate_treasury_payout(const transaction& tx, const uint64_t payout_index, uint8_t hf_version) const;
/** /**
* @brief sanity checks a miner transaction before validating an entire block * @brief sanity checks a miner transaction before validating an entire block
* *
+55 -4
View File
@@ -335,6 +335,34 @@ namespace cryptonote
} }
*/ */
//--------------------------------------------------------------- //---------------------------------------------------------------
std::tuple<bool, uint64_t> check_treasury_payout(
network_type nettype,
uint64_t height,
const std::vector<hardfork_t>& hardforks,
const uint8_t hf_version
) {
if (hf_version >= HF_VERSION_TREASURY_SAL1_MINT) {
// find the hardfork height
const auto& hf = std::find_if(hardforks.begin(), hardforks.end(), [](const hardfork_t& hf) {
return hf.version == HF_VERSION_TREASURY_SAL1_MINT;
});
// since we are at least at the hard fork HF_VERSION_TREASURY_SAL1_MINT, we assume height >= hf->height
const auto diff = height - hf->height;
const auto mint_period = get_config(nettype).TREASURY_SAL1_MINT_PERIOD;
// pay per period
if (diff % mint_period == 0) {
const auto payout_index = diff / mint_period;
if (payout_index < TREASURY_SAL1_MINT_COUNT) {
return {true, payout_index};
}
}
}
return {false, 0};
}
//---------------------------------------------------------------
bool construct_protocol_tx( bool construct_protocol_tx(
const size_t height, const size_t height,
transaction& tx, transaction& tx,
@@ -389,12 +417,15 @@ namespace cryptonote
return true; return true;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) { bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype, const std::vector<hardfork_t>& hardforks, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
// Clear the TX contents // Clear the TX contents
tx.set_null(); tx.set_null();
tx.type = cryptonote::transaction_type::MINER; tx.type = cryptonote::transaction_type::MINER;
// check for treasury payouts
auto[treasury_payout_exist, treasury_payout_index] = check_treasury_payout(nettype, height, hardforks, hard_fork_version);
keypair txkey = keypair::generate(hw::get_device("default")); keypair txkey = keypair::generate(hw::get_device("default"));
add_tx_pub_key_to_extra(tx, txkey.pub); add_tx_pub_key_to_extra(tx, txkey.pub);
if(!extra_nonce.empty()) if(!extra_nonce.empty())
@@ -451,6 +482,7 @@ namespace cryptonote
case HF_VERSION_AUDIT1_PAUSE: case HF_VERSION_AUDIT1_PAUSE:
case HF_VERSION_AUDIT2: case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE: case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_TREASURY_SAL1_MINT:
// SRCG: subtract 20% that will be rewarded to staking users // SRCG: subtract 20% that will be rewarded to staking users
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero"); CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
tx.amount_burnt = amount / 5; tx.amount_burnt = amount / 5;
@@ -464,7 +496,7 @@ namespace cryptonote
std::string asset_type = "SAL"; std::string asset_type = "SAL";
if (hard_fork_version >= HF_VERSION_SALVIUM_ONE_PROOFS) if (hard_fork_version >= HF_VERSION_SALVIUM_ONE_PROOFS)
asset_type = "SAL1"; asset_type = "SAL1";
cryptonote::set_tx_out(amount, asset_type, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, use_view_tags, view_tag, out); cryptonote::set_tx_out(amount, asset_type, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, !treasury_payout_exist, view_tag, out);
tx.vout.push_back(out); tx.vout.push_back(out);
} else { } else {
@@ -477,10 +509,29 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward); CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward);
// add the treasury payout if needed
if (treasury_payout_exist) {
std::vector<crypto::public_key> additional_tx_public_keys = {txkey.pub};
const auto output_keys = get_config(nettype).TREASURY_SAL1_MINT_OUTPUT_KEYS;
const auto keys = output_keys[treasury_payout_index];
crypto::public_key tx_key;
CHECK_AND_ASSERT_MES(epee::string_tools::hex_to_pod(keys.first, tx_key), false, "fail to deserialize treasury tx key");
crypto::public_key output_key;
CHECK_AND_ASSERT_MES(epee::string_tools::hex_to_pod(keys.second, output_key), false, "fail to deserialize treasury output key");
// Create the TX output for this payout
tx_out out;
cryptonote::set_tx_out(TREASURY_SAL1_MINT_AMOUNT, "SAL1", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, output_key, false, crypto::view_tag{}, out);
tx.vout.push_back(out);
// add tx pub key to tx extra
additional_tx_public_keys.push_back(tx_key);
add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys);
}
tx.version = 2; tx.version = 2;
tx.vin.push_back(in); tx.vin.push_back(in);
tx.invalidate_hashes(); tx.invalidate_hashes();
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee) //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
+5 -1
View File
@@ -37,6 +37,8 @@
#include "oracle/pricing_record.h" #include "oracle/pricing_record.h"
#include "cryptonote_protocol/enums.h" #include "cryptonote_protocol/enums.h"
#include "hardforks/hardforks.h"
namespace cryptonote namespace cryptonote
{ {
/* /*
@@ -72,7 +74,9 @@ namespace cryptonote
//--------------------------------------------------------------- //---------------------------------------------------------------
bool construct_protocol_tx(const size_t height, transaction& tx, std::vector<protocol_data_entry>& protocol_data, const uint8_t hf_version); bool construct_protocol_tx(const size_t height, transaction& tx, std::vector<protocol_data_entry>& protocol_data, const uint8_t hf_version);
//--------------------------------------------------------------- //---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1); bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype = network_type::FAKECHAIN, const std::vector<hardfork_t>& hardforks = {}, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
//---------------------------------------------------------------
std::tuple<bool, uint64_t> check_treasury_payout(network_type nettype, uint64_t height, const std::vector<hardfork_t>& hardforks, const uint8_t hf_version);
struct tx_source_entry struct tx_source_entry
{ {
+1 -1
View File
@@ -149,7 +149,7 @@ void print_genesis_tx_hex(const cryptonote::network_type nettype) {
//Prepare genesis_tx //Prepare genesis_tx
cryptonote::transaction tx_genesis; cryptonote::transaction tx_genesis;
cryptonote::construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().m_account_address, tx_genesis, blobdata(), 999, 1); cryptonote::construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().m_account_address, tx_genesis, (network_type)nettype, {}, blobdata(), 999, 1);
std::cout << "Object:" << std::endl; std::cout << "Object:" << std::endl;
std::cout << obj_to_json_str(tx_genesis) << std::endl << std::endl; std::cout << obj_to_json_str(tx_genesis) << std::endl << std::endl;
+3
View File
@@ -89,6 +89,9 @@ const hardfork_t testnet_hard_forks[] = {
// version 9 (audit 1 complete, whitelist controlling payouts) starts from block 1000 // version 9 (audit 1 complete, whitelist controlling payouts) starts from block 1000
{ 9, 1000, 0, 1739280000 }, { 9, 1000, 0, 1739280000 },
// version 10 treasury mint starts from block 1100
{10, 1100, 0, 1739780005 },
}; };
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]); const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1); const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
+2 -2
View File
@@ -272,7 +272,7 @@ bool test_generator::construct_block(cryptonote::block& blk, uint64_t height, co
size_t target_block_weight = txs_weight + get_transaction_weight(blk.miner_tx); size_t target_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
while (true) while (true)
{ {
if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, target_block_weight, total_fee, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), 10, hf_ver ? hf_ver.get() : 1)) if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, target_block_weight, total_fee, miner_acc.get_keys().m_account_address, blk.miner_tx, network_type::FAKECHAIN, {}, blobdata(), 10, hf_ver ? hf_ver.get() : 1))
return false; return false;
size_t actual_block_weight = txs_weight + get_transaction_weight(blk.miner_tx); size_t actual_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
@@ -375,7 +375,7 @@ bool test_generator::construct_block_manually(block& blk, const block& prev_bloc
{ {
size_t current_block_weight = txs_weight + get_transaction_weight(blk.miner_tx); size_t current_block_weight = txs_weight + get_transaction_weight(blk.miner_tx);
// TODO: This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE // TODO: This will work, until size of constructed block is less then CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE
if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, current_block_weight, fees, miner_acc.get_keys().m_account_address, blk.miner_tx, blobdata(), max_outs, hf_version)) if (!construct_miner_tx(height, misc_utils::median(block_weights), already_generated_coins, current_block_weight, fees, miner_acc.get_keys().m_account_address, blk.miner_tx, cryptonote::network_type::FAKECHAIN, {}, blobdata(), max_outs, hf_version))
return false; return false;
} }
+1 -1
View File
@@ -192,7 +192,7 @@ bool test_block_creation()
bool r = get_account_address_from_str(info, MAINNET, "0099be99c70ef10fd534c43c88e9d13d1c8853213df7e362afbec0e4ee6fec4948d0c190b58f4b356cd7feaf8d9d0a76e7c7e5a9a0a497a6b1faf7a765882dd08ac2"); bool r = get_account_address_from_str(info, MAINNET, "0099be99c70ef10fd534c43c88e9d13d1c8853213df7e362afbec0e4ee6fec4948d0c190b58f4b356cd7feaf8d9d0a76e7c7e5a9a0a497a6b1faf7a765882dd08ac2");
CHECK_AND_ASSERT_MES(r, false, "failed to import"); CHECK_AND_ASSERT_MES(r, false, "failed to import");
block b; block b;
r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, info.address, b.miner_tx, blobdata(), 11); r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, info.address, b.miner_tx, cryptonote::network_type::FAKECHAIN, {}, blobdata(), 11);
return r; return r;
} }
+55
View File
@@ -30,6 +30,16 @@
#include "cryptonote_basic/account.h" #include "cryptonote_basic/account.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/subaddress_index.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "string_tools.h"
using namespace cryptonote;
TEST(account, encrypt_keys) TEST(account, encrypt_keys)
{ {
cryptonote::keypair recovery_key = cryptonote::keypair::generate(hw::get_device("default")); cryptonote::keypair recovery_key = cryptonote::keypair::generate(hw::get_device("default"));
@@ -69,3 +79,48 @@ TEST(account, encrypt_keys)
ASSERT_EQ(account.get_keys().m_spend_secret_key, keys.m_spend_secret_key); ASSERT_EQ(account.get_keys().m_spend_secret_key, keys.m_spend_secret_key);
ASSERT_EQ(account.get_keys().m_view_secret_key, keys.m_view_secret_key); ASSERT_EQ(account.get_keys().m_view_secret_key, keys.m_view_secret_key);
} }
TEST(account, derive_output_key)
{
const std::string secret_view = "";
const std::string addr = "";
address_parse_info address_info;
bool ok = get_account_address_from_str(address_info, network_type::MAINNET, addr);
ASSERT_TRUE(ok);
std::unordered_map<crypto::public_key, subaddress_index> subaddresses = {{
{address_info.address.m_spend_public_key, {0, 0}},
}};
// derive keys
std::vector<std::pair<crypto::public_key, crypto::public_key>> txkeys;
for (size_t i = 0; i < 16; i++) {
// tx key
keypair txkey = keypair::generate(hw::get_device("default"));
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
ok = crypto::generate_key_derivation(address_info.address.m_view_public_key, txkey.sec, derivation);
ASSERT_TRUE(ok);
ok = crypto::derive_public_key(derivation, 0, address_info.address.m_spend_public_key, out_eph_public_key);
ASSERT_TRUE(ok);
txkeys.push_back({txkey.pub, out_eph_public_key});
}
// validate we can receive them
crypto::secret_key secret_view_key;
epee::string_tools::hex_to_pod(secret_view, secret_view_key);
size_t i = 0;
for (const auto& txkey : txkeys) {
crypto::key_derivation derivation;
hw::device *hw = &hw::get_device("default");
ASSERT_TRUE(hw->generate_key_derivation(txkey.first, secret_view_key, derivation));
ASSERT_TRUE(is_out_to_acc_precomp(subaddresses, txkey.second, derivation, {}, 0, *hw, boost::none));
i++;
}
}
+2 -2
View File
@@ -141,7 +141,7 @@ TEST(parse_and_validate_tx_extra, is_valid_tx_extra_parsed)
cryptonote::account_base acc; cryptonote::account_base acc;
acc.generate(); acc.generate();
cryptonote::blobdata b = "dsdsdfsdfsf"; cryptonote::blobdata b = "dsdsdfsdfsf";
ASSERT_TRUE(cryptonote::construct_miner_tx(0, 0, 10000000000000, 1000, TEST_FEE, acc.get_keys().m_account_address, tx, b, 1)); ASSERT_TRUE(cryptonote::construct_miner_tx(0, 0, 10000000000000, 1000, TEST_FEE, acc.get_keys().m_account_address, tx, cryptonote::network_type::FAKECHAIN, {}, b, 1));
crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(tx); crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(tx);
ASSERT_NE(tx_pub_key, crypto::null_pkey); ASSERT_NE(tx_pub_key, crypto::null_pkey);
} }
@@ -151,7 +151,7 @@ TEST(parse_and_validate_tx_extra, fails_on_big_extra_nonce)
cryptonote::account_base acc; cryptonote::account_base acc;
acc.generate(); acc.generate();
cryptonote::blobdata b(TX_EXTRA_NONCE_MAX_COUNT + 1, 0); cryptonote::blobdata b(TX_EXTRA_NONCE_MAX_COUNT + 1, 0);
ASSERT_FALSE(cryptonote::construct_miner_tx(0, 0, 10000000000000, 1000, TEST_FEE, acc.get_keys().m_account_address, tx, b, 1)); ASSERT_FALSE(cryptonote::construct_miner_tx(0, 0, 10000000000000, 1000, TEST_FEE, acc.get_keys().m_account_address, tx, cryptonote::network_type::FAKECHAIN, {}, b, 1));
} }
TEST(parse_and_validate_tx_extra, fails_on_wrong_size_in_extra_nonce) TEST(parse_and_validate_tx_extra, fails_on_wrong_size_in_extra_nonce)
{ {