From f2375f0156083e4708734566a21f978c4c1900a0 Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 1 Feb 2023 21:58:26 +0100 Subject: [PATCH] confidential assets: work in progress --- src/common/crypto_serialization.h | 19 ++++++ src/crypto/clsag.cpp | 18 ++++- src/crypto/clsag.h | 39 ++++++++++- src/currency_core/blockchain_storage.cpp | 13 ++-- src/currency_core/blockchain_storage.h | 6 +- src/currency_core/crypto_config.h | 3 +- src/currency_core/currency_basic.h | 87 +++++++++++++----------- 7 files changed, 135 insertions(+), 50 deletions(-) diff --git a/src/common/crypto_serialization.h b/src/common/crypto_serialization.h index 89b05d8f..80dfb6df 100644 --- a/src/common/crypto_serialization.h +++ b/src/common/crypto_serialization.h @@ -94,6 +94,25 @@ namespace crypto END_BOOST_SERIALIZATION() }; + struct CLSAG_GGX_signature_serialized : public CLSAG_GGX_signature + { + BEGIN_SERIALIZE_OBJECT() + FIELD(c) + FIELD((std::vector&)(r_g)) + FIELD((std::vector&)(r_x)) + FIELD(K1) + FIELD(K2) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(c) + BOOST_SERIALIZE((std::vector&)(r_g)) + BOOST_SERIALIZE((std::vector&)(r_x)) + BOOST_SERIALIZE(K1) + BOOST_SERIALIZE(K2) + END_BOOST_SERIALIZATION() + }; + struct CLSAG_GGXG_signature_serialized : public CLSAG_GGXG_signature { BEGIN_SERIALIZE_OBJECT() diff --git a/src/crypto/clsag.cpp b/src/crypto/clsag.cpp index bcc369e1..c4e1198f 100644 --- a/src/crypto/clsag.cpp +++ b/src/crypto/clsag.cpp @@ -171,7 +171,23 @@ namespace crypto return c_prev == sig.c; } - + + //--------------------------------------------------------------- + + + bool generate_CLSAG_GGX(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_asset_id, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, uint64_t secret_index, CLSAG_GGX_signature& sig) + { + return false; + } + + bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig) + { + return false; + } + + //--------------------------------------------------------------- diff --git a/src/crypto/clsag.h b/src/crypto/clsag.h index 8a4400e5..9b7f2156 100644 --- a/src/crypto/clsag.h +++ b/src/crypto/clsag.h @@ -47,7 +47,44 @@ namespace crypto bool verify_CLSAG_GG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const key_image& ki, const CLSAG_GG_signature& sig); - + + // + // 3-CLSAG + // + + + // 3-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX') + struct CLSAG_GGX_signature + { + scalar_t c; + scalar_vec_t r_g; // for G-components (layers 0, 1), size = size of the ring + scalar_vec_t r_x; // for X-component (layer 2), size = size of the ring + public_key K1; // auxiliary key image for layer 1 (G) + public_key K2; // auxiliary key image for layer 2 (X) + }; + + struct CLSAG_GGX_input_ref_t : public CLSAG_GG_input_ref_t + { + CLSAG_GGX_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& blinded_asset_id) + : CLSAG_GG_input_ref_t(stealth_address, amount_commitment) + , blinded_asset_id(blinded_asset_id) + {} + + const public_key& blinded_asset_id; // T, premultiplied by 1/8 + }; + + // pseudo_out_amount_commitment -- not premultiplied by 1/8 + // pseudo_out_asset_id -- not premultiplied by 1/8 + bool generate_CLSAG_GGX(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_asset_id, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, uint64_t secret_index, CLSAG_GGX_signature& sig); + + // pseudo_out_amount_commitment -- premultiplied by 1/8 + // pseudo_out_asset_id -- premultiplied by 1/8 + // may throw an exception TODO @#@# make sure it's okay + bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig); + + // // 4-CLSAG // diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 57fc8ea4..823e4c05 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -3528,10 +3528,10 @@ bool blockchain_storage::unprocess_blockchain_tx_extra(const transaction& tx) if (ei.m_asset_operation.operation_type != ASSET_DESCRIPTOR_OPERATION_UNDEFINED) { - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; if (ei.m_asset_operation.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - asset_id = get_asset_id_from_descriptor(ei.m_asset_operation.descriptor); + calculate_asset_id(ei.m_asset_operation.descriptor, nullptr, &asset_id); } else { @@ -3565,7 +3565,7 @@ uint64_t blockchain_storage::get_aliases_count() const return m_db_aliases.size(); } //------------------------------------------------------------------ -bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const +bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& result) const { CRITICAL_REGION_LOCAL(m_read_lock); auto as_ptr = m_db_assets.find(asset_id); @@ -3573,7 +3573,7 @@ bool blockchain_storage::get_asset_info(const crypto::hash& asset_id, asset_desc { if (as_ptr->size()) { - info = as_ptr->back().descriptor; + result = as_ptr->back().descriptor; return true; } } @@ -3768,7 +3768,7 @@ bool blockchain_storage::put_alias_info(const transaction & tx, extra_alias_entr return true; } //------------------------------------------------------------------ -bool blockchain_storage::pop_asset_info(const crypto::hash& asset_id) +bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id) { CRITICAL_REGION_LOCAL(m_read_lock); @@ -3791,7 +3791,8 @@ bool blockchain_storage::put_asset_info(const transaction & tx, asset_descriptor CRITICAL_REGION_LOCAL(m_read_lock); if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER) { - crypto::hash asset_id = get_asset_id_from_descriptor(ado.descriptor); + crypto::public_key asset_id{}; + calculate_asset_id(ado.descriptor, nullptr, &asset_id); auto asset_history_ptr = m_db_assets.find(asset_id); CHECK_AND_ASSERT_MES(!asset_history_ptr, false, "Asset id already existing"); assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history); diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 7537919d..fc68d95a 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -288,7 +288,7 @@ namespace currency uint64_t get_aliases_count()const; uint64_t get_block_h_older_then(uint64_t timestamp) const; bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const; - bool get_asset_info(const crypto::hash& asset_id, asset_descriptor_base& info)const; + bool get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& info)const; uint64_t get_assets_count() const; bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const; bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height)const; @@ -492,7 +492,7 @@ namespace currency typedef tools::db::cached_key_value_accessor solo_options_container; typedef tools::db::basic_key_value_accessor per_block_gindex_increments_container; // height => [(amount, gindex_increment), ...] - typedef tools::db::cached_key_value_accessor, true, false> assets_container; + typedef tools::db::cached_key_value_accessor, true, false> assets_container; //----------------------------------------- @@ -654,7 +654,7 @@ namespace currency bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp); bool pop_alias_info(const extra_alias_entry& ai); bool put_alias_info(const transaction& tx, extra_alias_entry& ai); - bool pop_asset_info(const crypto::hash& asset_id); + bool pop_asset_info(const crypto::public_key& asset_id); bool put_asset_info(const transaction & tx, asset_descriptor_operation & ado); void fill_addr_to_alias_dict(); //bool resync_spent_tx_flags(); diff --git a/src/currency_core/crypto_config.h b/src/currency_core/crypto_config.h index 087c1cfd..f97a9bad 100644 --- a/src/currency_core/crypto_config.h +++ b/src/currency_core/crypto_config.h @@ -8,7 +8,8 @@ // #define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______" -#define CRYPTO_HDS_OUT_BLINDING_MASK "ZANO_HDS_OUT_BLINDING_MASK_____" +#define CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK "ZANO_HDS_OUT_AMOUNT_BLIND_MASK_" +#define CRYPTO_HDS_OUT_ASSET_BLINDING_MASK "ZANO_HDS_OUT_ASSET_BLIND_MASK__" #define CRYPTO_HDS_OUT_CONCEALING_POINT "ZANO_HDS_OUT_CONCEALING_POINT__" #define CRYPTO_HDS_CLSAG_GG_LAYER_0 "ZANO_HDS_CLSAG_GG_LAYER_ZERO___" diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index d79c5122..f725c626 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -56,6 +56,7 @@ namespace currency const static crypto::hash gdefault_genesis = epee::string_tools::hex_to_pod("CC608F59F8080E2FBFE3C8C80EB6E6A953D47CF2D6AEBD345BADA3A1CAB99852"); const static crypto::hash ffff_hash = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + const static crypto::public_key ffff_pkey = epee::string_tools::hex_to_pod("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER; const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER; @@ -214,22 +215,8 @@ namespace currency uint32_t n_extras; }; - //!!!!this is temporary struct!!! - //needed only to hold asset_id of input/output while zarcanum extension being developed - struct open_asset_id - { - crypto::hash asset_id; - BEGIN_SERIALIZE_OBJECT() - FIELD(asset_id) // referring_input - END_SERIALIZE() - BEGIN_BOOST_SERIALIZATION() - BOOST_SERIALIZE(asset_id) - END_BOOST_SERIALIZATION() - }; - - - typedef boost::variant txin_etc_details_v; + typedef boost::variant txin_etc_details_v; struct referring_input @@ -394,8 +381,6 @@ namespace currency END_BOOST_SERIALIZATION() }; - typedef boost::variant txout_etc_details_v; - struct tx_out_zarcanum { tx_out_zarcanum() {} @@ -407,27 +392,26 @@ namespace currency crypto::public_key stealth_address; crypto::public_key concealing_point; // group element Q, see also Zarcanum paper, premultiplied by 1/8 crypto::public_key amount_commitment; // premultiplied by 1/8 - uint64_t encrypted_amount; - uint8_t mix_attr; - std::vector etc_details; - //crypto::public_key token_masked_generator; + crypto::public_key blinded_asset_id; // group element T, premultiplied by 1/8 + uint64_t encrypted_amount = 0; + uint8_t mix_attr = 0; BEGIN_SERIALIZE_OBJECT() FIELD(stealth_address) FIELD(concealing_point) FIELD(amount_commitment) + FIELD(blinded_asset_id) FIELD(encrypted_amount) FIELD(mix_attr) - FIELD(etc_details) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(stealth_address) BOOST_SERIALIZE(concealing_point) BOOST_SERIALIZE(amount_commitment) + BOOST_SERIALIZE(blinded_asset_id) BOOST_SERIALIZE(encrypted_amount) BOOST_SERIALIZE(mix_attr) - BOOST_SERIALIZE(etc_details) END_BOOST_SERIALIZATION() }; @@ -444,21 +428,45 @@ namespace currency END_BOOST_SERIALIZATION() }; - // non-consoditated txs must have one of this objects in the attachments (outputs_count == vout.size()) - // consolidated -- one pre consolidated part (sum(outputs_count) == vout.size()) + // each output has another amount commitment using generators U and G for range proof aggregation + struct zc_out_range_proof_aggregation_item + { + crypto::public_key amount_commitment_for_range_proof; // U = e_j * U + y'_j * G + crypto::scalar_t y0; // linear proof scalars + crypto::scalar_t y1; + + BEGIN_SERIALIZE_OBJECT() + FIELD(amount_commitment_for_range_proof) + FIELD(y0) + FIELD(y1) + END_SERIALIZE() + + BEGIN_BOOST_SERIALIZATION() + BOOST_SERIALIZE(amount_commitment_for_range_proof) + BOOST_SERIALIZE(y0) + BOOST_SERIALIZE(y1) + END_BOOST_SERIALIZATION() + }; + + // non-consoditated txs must have one of this objects in the attachments (aggregation_items.size() == vout.size()) + // consolidated -- one pre consolidated part (sum(aggregation_items.size()) == vout.size()) struct zc_outs_range_proof { crypto::bpp_signature_serialized bpp; - uint8_t outputs_count = 0; // how many outputs are included in the proof + //std::vector aggregation_items; // size = outputs count, per each output + crypto::vector_aggregation_proof aggregation_proof; + //uint8_t outputs_count = 0; // how many outputs are included in the proof BEGIN_SERIALIZE_OBJECT() FIELD(bpp) - FIELD(outputs_count) + FIELD(aggregation_proof) + //FIELD(outputs_count) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(bpp) - BOOST_SERIALIZE(outputs_count) + BOOST_SERIALIZE(aggregation_proof) + //BOOST_SERIALIZE(outputs_count) END_BOOST_SERIALIZATION() }; @@ -466,19 +474,23 @@ namespace currency struct ZC_sig { crypto::public_key pseudo_out_amount_commitment = null_pkey; // premultiplied by 1/8 - crypto::CLSAG_GG_signature_serialized clsags_gg; + crypto::public_key pseudo_out_asset_id = null_pkey; // premultiplied by 1/8 + crypto::CLSAG_GGX_signature_serialized clsags_ggx; BEGIN_SERIALIZE_OBJECT() FIELD(pseudo_out_amount_commitment) - FIELD(clsags_gg) + FIELD(pseudo_out_asset_id) + FIELD(clsags_ggx) END_SERIALIZE() BEGIN_BOOST_SERIALIZATION() BOOST_SERIALIZE(pseudo_out_amount_commitment) - BOOST_SERIALIZE(clsags_gg) + BOOST_SERIALIZE(pseudo_out_asset_id) + BOOST_SERIALIZE(clsags_ggx) END_BOOST_SERIALIZATION() }; + // only for txs with no ZC inputs (cancels out G component of outputs' amount commitments, asset tags assumed to be H_0 (native coin), non-blinded) struct zc_balance_proof { crypto::signature s = null_sig; @@ -777,7 +789,7 @@ namespace currency struct asset_descriptor_with_id: public asset_descriptor_base { - crypto::hash asset_id = currency::null_hash; + crypto::public_key asset_id = currency::null_pkey; /* BEGIN_VERSIONED_SERIALIZE() @@ -797,6 +809,7 @@ namespace currency #define ASSET_DESCRIPTOR_OPERATION_REGISTER 1 #define ASSET_DESCRIPTOR_OPERATION_EMMIT 2 #define ASSET_DESCRIPTOR_OPERATION_UPDATE 3 +#define ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN 4 struct asset_descriptor_operation @@ -804,7 +817,7 @@ namespace currency uint8_t operation_type = ASSET_DESCRIPTOR_OPERATION_UNDEFINED; std::vector proof; asset_descriptor_base descriptor; - std::vector asset_id; //questionable regarding form of optional fields + std::vector asset_id; //questionable regarding form of optional fields // premultiplied by 1/8 BEGIN_VERSIONED_SERIALIZE() @@ -1215,12 +1228,10 @@ SET_VARIANT_TAGS(currency::NLSAG_sig, 42, "NLSAG_sig"); SET_VARIANT_TAGS(currency::ZC_sig, 43, "ZC_sig"); SET_VARIANT_TAGS(currency::void_sig, 44, "void_sig"); SET_VARIANT_TAGS(currency::zarcanum_sig, 45, "zarcanum_sig"); -SET_VARIANT_TAGS(currency::zc_outs_range_proof, 46, "zc_outs_range_proof"); -SET_VARIANT_TAGS(currency::zc_balance_proof, 47, "zc_balance_proof"); +SET_VARIANT_TAGS(currency::zc_outs_range_proof, 47, "zc_outs_range_proof"); +SET_VARIANT_TAGS(currency::zc_balance_proof, 48, "zc_balance_proof"); -SET_VARIANT_TAGS(currency::open_asset_id, 48, "asset_id"); - -SET_VARIANT_TAGS(currency::asset_descriptor_operation, 48, "asset_descriptor_base"); +SET_VARIANT_TAGS(currency::asset_descriptor_operation, 49, "asset_descriptor_base");