Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Haven 4.2 #78

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4295101
temp change, must be revenrted
Sep 8, 2024
9490aaa
adding anonymity pool
Sep 8, 2024
53e7e7c
additional anonymity pool checks
Sep 9, 2024
016cd4f
anonymity pool not applicable before HF24
Sep 9, 2024
b030600
additional anon pool checks, error messages
Sep 9, 2024
8810408
add new RCT type for the supply Audit
Sep 10, 2024
fa458b4
tx validation checks
Sep 10, 2024
3ff2fa8
added amount proof sketch
Sep 10, 2024
7c43818
commenting
Sep 10, 2024
a2c0621
amount proof verification
Sep 11, 2024
d4c02dc
fixed comments
Sep 11, 2024
070648f
added amount proof to the tx signing process
Sep 12, 2024
8979a3d
amount proof signing
Sep 12, 2024
9033d98
added version bp_version=8 for supply audit txs
Sep 12, 2024
fcaa5df
supply update after audit - part 1
Sep 12, 2024
ea39f28
rpc command for supply recalculation after audit
Sep 13, 2024
214f25c
added to-do for wallet2
Sep 14, 2024
832b1e0
wallet adaptations for supply audit
Sep 14, 2024
6e29b4d
rct distribution by range of blocks
Sep 14, 2024
dcab58f
anon pool offset
Sep 14, 2024
8f14160
decoy pickup now takes into account anon pools
Sep 15, 2024
28dd2c8
bug fixes
Sep 15, 2024
88b3bfb
bugfixing
Sep 15, 2024
3785695
bug fix proof
Sep 15, 2024
9afe86d
fix pre clsag hash, empty pr
Sep 16, 2024
348672e
fix amount proof serialization
Sep 16, 2024
470c56b
fixes to tx validation and wallet
Sep 16, 2024
ca8d300
fix update of supply
Sep 17, 2024
31357ff
remove debug message
Sep 17, 2024
5ba6b4f
adjust supply calculation by adding transfer fees
Sep 17, 2024
dd7e188
revert previous change
Sep 17, 2024
5133e24
wallet improvements, formatting
Sep 17, 2024
64111aa
wallet commands to freeze/thaw all old/new outputs
Sep 17, 2024
b423ff0
fixes thaw/freeze old/new outputs
Sep 17, 2024
2342c60
vbs removal
Sep 18, 2024
c97c279
verification checks hardening
Sep 18, 2024
6521e0c
lock old outputs after the end of the supply audit
Sep 18, 2024
3f4ee2f
bug fix - db level lock of old outputs
Sep 18, 2024
46da4d0
add parameter for old output lock block post audit
Sep 18, 2024
c7ea37c
formatting
Sep 18, 2024
2d56eb3
additional security checks design
Sep 20, 2024
4228478
typo fix
Sep 20, 2024
33755e1
added comments
Sep 20, 2024
1127592
additional proof of value checks, bugfixing
Sep 21, 2024
f025495
error messages, removing TO-DO tags
Sep 21, 2024
7cdd573
Merge branch 'haven-protocol-org:master' into Haven-4.2
Tay8NWWFKpz9JT4NXU0w Sep 23, 2024
9d73c96
wallet commands implementation
Sep 23, 2024
d0361ed
bug fix collateral check
Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,5 @@ nbproject
__pycache__/
*.pyc
*.log
compile_commands.json
.cache/
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ all: release-all

depends:
cd contrib/depends && $(MAKE) HOST=$(target) && cd ../.. && mkdir -p build/$(target)/release
cd build/$(target)/release && cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
cd build/$(target)/release && cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ../../.. && $(MAKE)

cmake-debug:
mkdir -p $(builddir)/debug
Expand Down
3 changes: 2 additions & 1 deletion src/blockchain_db/blockchain_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <boost/range/adaptor/reversed.hpp>

#include "ringct/rctTypes.h"
#include "string_tools.h"
#include "blockchain_db.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
Expand Down Expand Up @@ -260,7 +261,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
}
else
{
if (tx.rct_signatures.type == rct::RCTTypeHaven2 || tx.rct_signatures.type == rct::RCTTypeHaven3 || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus) {
if (tx.rct_signatures.type == rct::RCTTypeHaven2 || tx.rct_signatures.type == rct::RCTTypeHaven3 || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeSupplyAudit) {
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, unlock_time, tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
} else {
std::string output_asset_type;
Expand Down
7 changes: 7 additions & 0 deletions src/blockchain_db/blockchain_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,13 @@ class BlockchainDB
*/
virtual std::vector<std::pair<std::string, std::string>> get_circulating_supply() const = 0;

/**
* @brief Recalculate supply after the audit
*
* @param decryption_secretkey Decryption key for amount_encrypted
*/
virtual void recalculate_supply_after_audit(const rct::key & decryption_secretkey) = 0;


/**
* <!--
Expand Down
133 changes: 133 additions & 0 deletions src/blockchain_db/lmdb/db_lmdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <memory> // std::unique_ptr
#include <cstring> // memcpy

#include "cryptonote_config.h"
#include "string_tools.h"
#include "file_io_utils.h"
#include "common/util.h"
Expand Down Expand Up @@ -989,6 +990,7 @@ read_circulating_supply_data(MDB_cursor *cur_circ_supply_tally, MDB_val idx)
void write_circulating_supply_data(MDB_cursor *cur_circ_supply_tally, MDB_val idx, boost::multiprecision::int128_t tally)
{
// packing the Boost 128-bit signed integer into 2 uint64's + a sign bit
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
circ_supply_tally cst;

// From the Boost docs, bitwise operations on negative values "Yields the value, but not the bit pattern, that would result from
Expand Down Expand Up @@ -3299,6 +3301,123 @@ std::vector<std::pair<std::string, std::string>> BlockchainLMDB::get_circulating
return circulating_supply;
}

//! This function updates the circulating total supply, but it does not update the individual transaction supply.
//! It is meant as a temporary measure, due to the limitation of not being able to publish the private decryption key.
//! It will be redesigned in the next Haven release
void BlockchainLMDB::recalculate_supply_after_audit(const rct::key & decryption_secretkey)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);


check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;

block_wtxn_start();
int result = 0;

CURSOR(block_info)
CURSOR(blocks)
CURSOR(circ_supply)
CURSOR(circ_supply_tally)

const uint64_t bc_height = height();
const uint64_t start_height=1700000;
uint64_t height = start_height;

//Initialize new total supply at 0
std::map<uint64_t, boost::multiprecision::int128_t> total_new_supply;
uint64_t asset_id=0;
for (auto asset_type: offshore::ASSET_TYPES){
if (asset_type!="XCAD" && asset_type != "XNOK" && asset_type != "XNZD") //TO-DO##
total_new_supply.insert(std::pair<uint64_t, boost::multiprecision::int128_t>(asset_id, 0));
asset_id++;
}

uint64_t coinbase_at_start_of_audit = 0;
const bool after_audit_start = get_hard_fork_version(bc_height - 1) >= HF_VERSION_SUPPLY_AUDIT;
bool audit_blocked_reached = false;

//TO-DO## split this in chunks, so that not all blocks are fetched at the same time, killing the daemon
std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > > blocks;

while(height < bc_height && after_audit_start) {
block b = get_block_from_height(height);
if (!audit_blocked_reached)
audit_blocked_reached=(get_hard_fork_version(height) == HF_VERSION_SUPPLY_AUDIT);
if(audit_blocked_reached){
if (coinbase_at_start_of_audit == 0) //All coins minted by mining prior to the audit will have to undergo audit, so have to be removed from the coinbase supply
coinbase_at_start_of_audit=get_block_already_generated_coins(height-1);

for (auto &tx_hash: b.tx_hashes){
cryptonote::blobdata tx_blob;
if(!get_pruned_tx_blob(tx_hash, tx_blob))
throw1(TX_DNE("Cant get transaction from DB"));


circ_supply cs;
transaction tx;
MDB_val_set(val_h, tx_hash);
if (!parse_and_validate_tx_base_from_blob(tx_blob, tx))
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));


if (mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &val_h, MDB_GET_BOTH))
throw1(TX_DNE("Attempting to remove transaction that isn't in the db"));
txindex *tip = (txindex *)val_h.mv_data;
MDB_val_set(val_tx_id, tip->data.tx_id);
bool is_miner_tx = (tx.vin[0].type() == typeid(cryptonote::txin_gen));
// get tx assets
std::string strSource;
std::string strDest;
if (!get_tx_asset_types(tx, tx_hash, strSource, strDest, is_miner_tx)) {
throw0(DB_ERROR("Failed to add tx circulating supply to db transaction: get_tx_asset_types fails."));
}

if(tx.rct_signatures.type==rct::RCTTypeSupplyAudit){
rct::xmr_amount amount_decrypted=tx.rct_signatures.amount_encrypted;
rct::xmr_amount encryption_key=0;

rct::key decryption_pubkey=tx.rct_signatures.decryption_pubkey;

const rct::key rS = scalarmultKey(decryption_pubkey,decryption_secretkey);
for (int i = 8; i < 16; i++){ //Use bytes 8 to 16 for the encryption
encryption_key*=256; //Shift 1 bytes
encryption_key+=rS.bytes[i]; //Add current byte
}
amount_decrypted ^= encryption_key; //XOR using the encryption key

MDEBUG("height,amount_decrypted,tx: " << height<<","<<amount_decrypted<<","<<tx_hash);
uint64_t dest_currency_type = std::find(offshore::ASSET_TYPES.begin(), offshore::ASSET_TYPES.end(), strDest) - offshore::ASSET_TYPES.begin();
total_new_supply[dest_currency_type] += amount_decrypted; //Sum of outgoing amounts
} else { //check if we already have a transaction record
MDB_val v;
result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, &v, MDB_SET);
if (result==0){
const circ_supply &cs = *(const circ_supply*)v.mv_data;
boost::multiprecision::int128_t burnt = cs.amount_burnt;
total_new_supply[cs.source_currency_type] -= burnt;
boost::multiprecision::int128_t minted = cs.amount_minted;
total_new_supply[cs.dest_currency_type] += minted;
} else if(result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("Failed to enumerate circ_supply table: ", result).c_str()));
}

}
}
height++;
}
//remove old coinbase amount
uint64_t dest_currency_type = std::find(offshore::ASSET_TYPES.begin(), offshore::ASSET_TYPES.end(), "XHV") - offshore::ASSET_TYPES.begin();
total_new_supply[dest_currency_type]-=coinbase_at_start_of_audit;

if (after_audit_start) //write supply back to the DB only if the current height is above the start of the audit
for (auto &tally: total_new_supply) {
MDB_val_copy<uint64_t> currency_type(tally.first);
write_circulating_supply_data(m_cur_circ_supply_tally, currency_type, tally.second);
}
block_wtxn_stop();
}

uint64_t BlockchainLMDB::num_outputs() const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
Expand Down Expand Up @@ -3516,6 +3635,7 @@ bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t coun
return true;
}

//TO-DO## Potentially not working as expected?
bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_block_count, size_t max_block_count, size_t max_tx_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
Expand Down Expand Up @@ -3786,6 +3906,12 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint6
if (include_commitmemt)
ret.commitment = rct::zeroCommit(amount);
}

const uint64_t m_height = height(); //After the supply audit ends, old outputs should be locked. This is an extra safety measure.
const uint8_t hf_version=get_hard_fork_version(m_height);
if(get_hard_fork_version(ret.height-1)<HF_VERSION_SUPPLY_AUDIT && hf_version >= HF_VERSION_SUPPLY_AUDIT_END){
ret.unlock_time=OLD_OUTPUT_LOCK_BLOCK_AFTER_AUDIT;
}
TXN_POSTFIX_RDONLY();
return ret;
}
Expand Down Expand Up @@ -4551,6 +4677,8 @@ void BlockchainLMDB::get_output_key(const epee::span<const uint64_t> &amounts, c

RCURSOR(output_amounts);

const uint64_t m_height = height();
const uint8_t hf_version=get_hard_fork_version(m_height-1);
for (size_t i = 0; i < offsets.size(); ++i)
{
const uint64_t amount = amounts.size() == 1 ? amounts[0] : amounts[i];
Expand Down Expand Up @@ -4583,6 +4711,11 @@ void BlockchainLMDB::get_output_key(const epee::span<const uint64_t> &amounts, c
memcpy(&data, &okp->data, sizeof(pre_rct_output_data_t));
data.commitment = rct::zeroCommit(amount);
}
//After the supply audit ends, old outputs should be locked. This is an extra safety measure.
output_data_t &data = outputs.back();
if(get_hard_fork_version(data.height)<HF_VERSION_SUPPLY_AUDIT && hf_version >= HF_VERSION_SUPPLY_AUDIT_END){
data.unlock_time=OLD_OUTPUT_LOCK_BLOCK_AFTER_AUDIT;
}
}

TXN_POSTFIX_RDONLY();
Expand Down
2 changes: 2 additions & 0 deletions src/blockchain_db/lmdb/db_lmdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ class BlockchainLMDB : public BlockchainDB
virtual block get_top_block() const;

virtual std::vector<std::pair<std::string, std::string>> get_circulating_supply() const;

virtual void recalculate_supply_after_audit(const rct::key & decryption_secretkey);

virtual uint64_t height() const;

Expand Down
6 changes: 3 additions & 3 deletions src/cryptonote_basic/cryptonote_boost_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeCLSAGN && x.type != rct::RCTTypeHaven2 && x.type != rct::RCTTypeHaven3 && x.type != rct::RCTTypeBulletproofPlus)
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeCLSAGN && x.type != rct::RCTTypeHaven2 && x.type != rct::RCTTypeHaven3 && x.type != rct::RCTTypeBulletproofPlus&& x.type != rct::RCTTypeSupplyAudit)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
Expand Down Expand Up @@ -464,7 +464,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeCLSAGN && x.type != rct::RCTTypeHaven2 && x.type != rct::RCTTypeHaven3 && x.type != rct::RCTTypeBulletproofPlus)
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeCLSAGN && x.type != rct::RCTTypeHaven2 && x.type != rct::RCTTypeHaven3 && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeSupplyAudit)
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
Expand Down Expand Up @@ -521,7 +521,7 @@ namespace boost
a & x.p.MGs;
if (ver >= 1u)
a & x.p.CLSAGs;
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeCLSAGN || x.type == rct::RCTTypeHaven2 || x.type == rct::RCTTypeHaven3 || x.type == rct::RCTTypeBulletproofPlus)
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeCLSAGN || x.type == rct::RCTTypeHaven2 || x.type == rct::RCTTypeHaven3 || x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeSupplyAudit)
a & x.p.pseudoOuts;
}

Expand Down
8 changes: 5 additions & 3 deletions src/cryptonote_basic/cryptonote_format_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <atomic>
#include <boost/algorithm/string.hpp>
#include "ringct/rctTypes.h"
#include "wipeable_string.h"
#include "string_tools.h"
#include "string_tools_lexical.h"
Expand Down Expand Up @@ -104,7 +105,7 @@ namespace cryptonote
ge_p1p1_to_p3(&A2, &tmp3);
ge_p3_tobytes(&AB, &A2);
}

//TO-DO##
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
{
const rct::rctSig &rv = tx.rct_signatures;
Expand Down Expand Up @@ -485,7 +486,7 @@ namespace cryptonote
{
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeCLSAGN || tx.rct_signatures.type == rct::RCTTypeHaven2 || tx.rct_signatures.type == rct::RCTTypeHaven3 || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus,
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeCLSAGN || tx.rct_signatures.type == rct::RCTTypeHaven2 || tx.rct_signatures.type == rct::RCTTypeHaven3 || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeSupplyAudit,
std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight");
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_haven_key), std::numeric_limits<uint64_t>::max(), "invalid vin in get_pruned_transaction_weight");
Expand Down Expand Up @@ -1934,7 +1935,8 @@ namespace cryptonote
return get_tx_tree_hash(txs_ids);
}
//---------------------------------------------------------------
bool is_valid_decomposed_amount(uint64_t amount)
bool
is_valid_decomposed_amount(uint64_t amount)
{
const uint64_t *begin = valid_decomposed_outputs;
const uint64_t *end = valid_decomposed_outputs + sizeof(valid_decomposed_outputs) / sizeof(valid_decomposed_outputs[0]);
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_basic/verification_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace cryptonote
uint64_t m_collateral;
uint64_t m_slippage;
bool tx_pr_height_verified = false;
anonymity_pool m_tx_anon_pool = anonymity_pool::UNSET;
};

struct block_verification_context
Expand Down
9 changes: 9 additions & 0 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,14 @@
#define HF_VERSION_MAX_CONV_TRANSACTION_FEE 24
#define MAX_CONV_TRANSACTION_FEE ((uint64_t)10000000000000ull)

// Haven v4.2 definitions
#define HF_VERSION_SUPPLY_AUDIT 25
#define SUPPLY_AUDIT_BLOCK_HEIGHT ((uint64_t)1713000)
#define OLD_OUTPUT_LOCK_BLOCK_AFTER_AUDIT ((uint64_t)20000000) //After the supply audit ends, all old outputs will be locked to this block, to avoid spending them


#define HF_VERSION_SUPPLY_AUDIT_END 26
#define HF_VERSION_VBS_REMOVAL 27

#define STAGENET_VERSION 0x0e
#define TESTNET_VERSION 0x1b
Expand Down Expand Up @@ -342,6 +350,7 @@ namespace config
const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS_SEED[] = "multisig_tx_privkeys_seed";
const constexpr char HASH_KEY_MULTISIG_TX_PRIVKEYS[] = "multisig_tx_privkeys";
const constexpr char HASH_KEY_TXHASH_AND_MIXRING[] = "txhash_and_mixring";
const unsigned char HASH_KEY_AMOUNTPROOF[] = "AmountProof";

// Multisig
const uint32_t MULTISIG_MAX_SIGNERS{16};
Expand Down
Loading
Loading