From 5de3d11ccbac36b0fd487fc983c7695f6456a1a4 Mon Sep 17 00:00:00 2001 From: MoneroOcean Date: Mon, 6 Oct 2025 19:45:43 -0700 Subject: [PATCH] SAL v1 support --- src/carrot_core/core_types.h | 104 +++++++++++++ src/cryptonote_basic/cryptonote_basic.h | 69 ++++++++- src/cryptonote_basic/tx_extra.h | 16 +- src/cryptonote_config.h | 1 + src/ringct/rctTypes.h | 185 +++++++++++++++++++++--- src/serialization/crypto.h | 3 + 6 files changed, 348 insertions(+), 30 deletions(-) create mode 100644 src/carrot_core/core_types.h diff --git a/src/carrot_core/core_types.h b/src/carrot_core/core_types.h new file mode 100644 index 0000000..38163ef --- /dev/null +++ b/src/carrot_core/core_types.h @@ -0,0 +1,104 @@ +// Copyright (c) 2024, 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. + +//! @file Supporting types for Carrot (anchor, view tag, etc.). + +#pragma once + +//standard headers +#include +#include + +//forward declarations + +namespace carrot +{ + +constexpr std::size_t JANUS_ANCHOR_BYTES{16}; + +/// either encodes randomness the private key of, or an HMAC of, the ephemeral pubkey +struct janus_anchor_t final +{ + unsigned char bytes[JANUS_ANCHOR_BYTES]; +}; + +/// carrot janus anchor XORd with a user-defined secret +using encrypted_janus_anchor_t = janus_anchor_t; + +/// carrot enote types +enum class CarrotEnoteType : unsigned char +{ + PAYMENT = 0, + CHANGE = 1 +}; + +/// carrot encrypted amount +constexpr std::size_t ENCRYPTED_AMOUNT_BYTES{8}; +struct encrypted_amount_t final +{ + unsigned char bytes[ENCRYPTED_AMOUNT_BYTES]; +}; + +/// legacy payment ID +constexpr std::size_t PAYMENT_ID_BYTES{8}; +struct payment_id_t final +{ + unsigned char bytes[PAYMENT_ID_BYTES]; +}; +static constexpr payment_id_t null_payment_id{{0}}; + +/// legacy encrypted payment ID +struct encrypted_payment_id_t final +{ + unsigned char bytes[PAYMENT_ID_BYTES]; +}; + +/// carrot view tags +constexpr std::size_t VIEW_TAG_BYTES{3}; +struct view_tag_t final +{ + unsigned char bytes[VIEW_TAG_BYTES]; +}; + +static_assert(sizeof(view_tag_t) < 32, "uint8_t cannot index all view tag bits"); + +/// carrot input context +constexpr std::size_t INPUT_CONTEXT_BYTES{1 + 32}; +struct input_context_t final +{ + unsigned char bytes[INPUT_CONTEXT_BYTES]; +}; + +// SPARC encrypted return public key +constexpr std::size_t ENCRYPTED_RETURN_PUBKEY_BYTES{32}; +struct encrypted_return_pubkey_t final +{ + unsigned char bytes[ENCRYPTED_RETURN_PUBKEY_BYTES]; +}; + +} //namespace carrot diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 8cd9ea5..edd74a4 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -29,6 +29,7 @@ #include "offshore/pricing_record.h" #include "zephyr_oracle/pricing_record.h" #include "salvium_oracle/pricing_record.h" +#include "carrot_core/core_types.h" #include "arq_txtypes.h" @@ -216,6 +217,25 @@ namespace cryptonote END_SERIALIZE() }; + + struct txout_to_carrot_v1 + { + crypto::public_key key; // K_o + std::string asset_type; + carrot::view_tag_t view_tag; // vt + carrot::encrypted_janus_anchor_t encrypted_janus_anchor; // anchor_enc + + // Encrypted amount a_enc and amount commitment C_a are stored in rct::rctSigBase + // This allows for reuse of this output type between coinbase and non-coinbase txs + + BEGIN_SERIALIZE_OBJECT() + FIELD(key) + FIELD(asset_type) + FIELD(view_tag) + FIELD(encrypted_janus_anchor) + END_SERIALIZE() + }; + /* inputs */ struct txin_gen @@ -361,6 +381,7 @@ namespace cryptonote typedef boost::variant txout_target_v; typedef boost::variant txout_xhv_target_v; typedef boost::variant txout_salvium_target_v; + typedef boost::variant txout_carrot_target_v; typedef boost::variant txout_stablero_target_v; @@ -408,6 +429,23 @@ namespace cryptonote END_SERIALIZE() }; + class protocol_tx_data_t { + public: + uint8_t version; + crypto::public_key return_address; + crypto::public_key return_pubkey; + carrot::view_tag_t return_view_tag; + carrot::encrypted_janus_anchor_t return_anchor_enc; + + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(version) + FIELD(return_address) + FIELD(return_pubkey) + FIELD(return_view_tag) + FIELD(return_anchor_enc) + END_SERIALIZE() + }; + enum loki_version { @@ -465,6 +503,7 @@ namespace cryptonote //uint64_t amount_burnt; // Slippage limit uint64_t amount_slippage_limit; + protocol_tx_data_t protocol_tx_data; // @@ -740,15 +779,21 @@ namespace cryptonote FIELD(vout_salvium) FIELD(extra) VARINT_FIELD(sal_tx_type) - if (sal_tx_type != cryptonote::salvium_transaction_type::PROTOCOL) { + if (sal_tx_type != cryptonote::salvium_transaction_type::UNSET && sal_tx_type != cryptonote::salvium_transaction_type::PROTOCOL) { VARINT_FIELD(amount_burnt) if (sal_tx_type != cryptonote::salvium_transaction_type::MINER) { if (type == cryptonote::salvium_transaction_type::TRANSFER && version >= TRANSACTION_VERSION_N_OUTS) { FIELD(return_address_list) FIELD(return_address_change_mask) } else { - FIELD(return_address) - FIELD(return_pubkey) + if (type == cryptonote::salvium_transaction_type::STAKE && + version >= TRANSACTION_VERSION_CARROT) + { + FIELD(protocol_tx_data) + } else { + FIELD(return_address) + FIELD(return_pubkey) + } } FIELD(source_asset_type) FIELD(destination_asset_type) @@ -941,6 +986,10 @@ namespace cryptonote return_address_list.clear(); return_address_change_mask.clear(); return_pubkey = cryptonote::null_pkey; + protocol_tx_data.return_address = cryptonote::null_pkey; + protocol_tx_data.return_pubkey = cryptonote::null_pkey; + protocol_tx_data.return_view_tag = {}; + protocol_tx_data.return_anchor_enc = {}; source_asset_type.clear(); destination_asset_type.clear(); amount_slippage_limit = 0; @@ -1209,6 +1258,7 @@ namespace cryptonote { crypto::public_key m_spend_public_key; crypto::public_key m_view_public_key; + bool m_is_carrot; BEGIN_SERIALIZE_OBJECT() FIELD(m_spend_public_key) @@ -1219,6 +1269,18 @@ namespace cryptonote KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key) END_KV_SERIALIZE_MAP() + + bool operator==(const account_public_address& rhs) const + { + return m_spend_public_key == rhs.m_spend_public_key && + m_view_public_key == rhs.m_view_public_key && + m_is_carrot == rhs.m_is_carrot; + } + + bool operator!=(const account_public_address& rhs) const + { + return !(*this == rhs); + } }; struct integrated_address { @@ -1261,6 +1323,7 @@ VARIANT_TAG(binary_archive, cryptonote::txout_zephyr_tagged_key, 0x2); VARIANT_TAG(binary_archive, cryptonote::txout_to_tagged_key, 0x3); VARIANT_TAG(binary_archive, cryptonote::txout_salvium_tagged_key, 0x3); VARIANT_TAG(binary_archive, cryptonote::txout_offshore, 0x3); +VARIANT_TAG(binary_archive, cryptonote::txout_to_carrot_v1, 0x4); VARIANT_TAG(binary_archive, cryptonote::txout_xasset, 0x5); VARIANT_TAG(binary_archive, cryptonote::txout_haven_key, 0x6); VARIANT_TAG(binary_archive, cryptonote::txout_haven_tagged_key, 0x7); diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h index 36a9d25..3d638b0 100644 --- a/src/cryptonote_basic/tx_extra.h +++ b/src/cryptonote_basic/tx_extra.h @@ -1,21 +1,21 @@ // Copyright (c) 2014-2018, 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 @@ -25,7 +25,7 @@ // 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. -// +// // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #pragma once @@ -221,7 +221,7 @@ namespace cryptonote FIELD(data) END_SERIALIZE() }; - + struct tx_extra_service_node_winner { crypto::public_key m_service_node_key; diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 702f167..b43a74f 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -10,6 +10,7 @@ #define HF_VERSION_USE_COLLATERAL 20 #define HF_VERSION_ENABLE_N_OUTS 2 #define TRANSACTION_VERSION_N_OUTS 3 +#define TRANSACTION_VERSION_CARROT 4 // UNLOCK TIMES #define TX_V6_OFFSHORE_UNLOCK_BLOCKS 21*720 // 21 day unlock time diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 8fb3670..675c42e 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -111,6 +111,22 @@ namespace rct { typedef std::vector ctkeyV; typedef std::vector ctkeyM; + struct carrot_ctkey { + key x; + key y; + key mask; //C here if public + + bool operator==(const carrot_ctkey &other) const { + return (x == other.x) && (y == other.y) && (mask == other.mask); + } + + bool operator!=(const carrot_ctkey &other) const { + return !(*this == other); + } + }; + typedef std::vector carrot_ctkeyV; + typedef std::vector carrot_ctkeyM; + //used for multisig data struct multisig_kLRki { key k; @@ -159,12 +175,12 @@ namespace rct { key64 s1; key ee; }; - + //Container for precomp struct geDsmp { ge_dsmp k; }; - + //just contains the necessary keys to represent MLSAG sigs //c.f. https://eprint.iacr.org/2015/1098 struct mgSig { @@ -195,6 +211,24 @@ namespace rct { END_SERIALIZE() }; + // TCLSAG signature + struct tclsag { + keyV sx; // x scalars(responses) + keyV sy; // y scalars(responses) + key c1; + + key I; // signing key image + key D; // commitment key image + + BEGIN_SERIALIZE_OBJECT() + FIELD(sx) + FIELD(sy) + FIELD(c1) + // FIELD(I) - not serialized, it can be reconstructed + FIELD(D) + END_SERIALIZE() + }; + //contains the data for an Borromean sig // also contains the "Ci" values such that // \sum Ci = C @@ -305,7 +339,9 @@ namespace rct { RCTTypeBulletproof2 = 4, RCTTypeCLSAG = 5, RCTTypeBulletproofPlus = 6, - RCTTypeFullProofs = 7 + RCTTypeFullProofs = 7, + RCTTypeSalviumZero = 8, + RCTTypeSalviumOne = 9 }; enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof }; struct RCTConfig { @@ -318,6 +354,51 @@ namespace rct { VARINT_FIELD(bp_version) END_SERIALIZE() }; + + enum SalviumDataType { SalviumZero=0, SalviumZeroAudit=1, SalviumOne=2 }; + struct salvium_input_data_t { + crypto::key_derivation aR; + xmr_amount amount; + size_t i; + uint8_t origin_tx_type; + crypto::key_derivation aR_stake; + size_t i_stake; + + BEGIN_SERIALIZE_OBJECT() + FIELD(aR) + VARINT_FIELD(amount) + VARINT_FIELD(i) + VARINT_FIELD(origin_tx_type) + if (origin_tx_type != cryptonote::salvium_transaction_type::UNSET) { + FIELD(aR_stake) + FIELD(i_stake) + } + END_SERIALIZE() + }; + struct salvium_data_t { + + uint8_t salvium_data_type; // flag to indicate what type of data is valid + zk_proof pr_proof; // p_r + zk_proof sa_proof; // spend authority proof + zk_proof cz_proof; // change is zero proof + std::vector input_verification_data; + crypto::public_key spend_pubkey; + std::string enc_view_privkey_str; + + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(salvium_data_type) + FIELD(pr_proof) + FIELD(sa_proof) + if (salvium_data_type == SalviumZeroAudit) + { + FIELD(cz_proof) + FIELD(input_verification_data) + FIELD(spend_pubkey) + FIELD(enc_view_privkey_str) + } + END_SERIALIZE() + }; + struct rctSigBase { uint8_t type; key message; @@ -328,20 +409,20 @@ namespace rct { ctkeyV outPk; xmr_amount txnFee = 0; // contains b key p_r; - zk_proof pr_proof; // p_r + zk_proof pr_proof; // p_r zk_proof sa_proof; // spend authority proof - + rctSigBase() : type(RCTTypeNull), message{}, mixRing{}, pseudoOuts{}, ecdhInfo{}, outPk{}, txnFee(0), p_r{}, pr_proof{}, sa_proof{} {} - + template class Archive> bool serialize_rctsig_base(Archive &ar, size_t inputs, size_t outputs) { FIELD(type) if (type == RCTTypeNull) return ar.stream().good(); - if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs) + if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumZero && type != RCTTypeSalviumOne) return false; VARINT_FIELD(txnFee) // inputs/outputs not saved, only here for serialization help @@ -354,7 +435,7 @@ namespace rct { return false; for (size_t i = 0; i < outputs; ++i) { - if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs) + if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne) { // Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the // first 8 bytes of ecdhInfo[i].amount @@ -370,10 +451,10 @@ namespace rct { FIELDS(ecdhInfo[i]) } if (outputs - i > 1) - ar.delimit_array(); + ar.delimit_array(); } ar.end_array(); - + ar.tag("outPk"); ar.begin_array(); PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, outPk); @@ -388,7 +469,11 @@ namespace rct { ar.end_array(); FIELD(p_r) - if (type == RCTTypeFullProofs) + if (type == RCTTypeSalviumZero || type == RCTTypeSalviumOne) + { + FIELD(salvium_data) + } + else if (type == RCTTypeFullProofs) { FIELD(pr_proof) FIELD(sa_proof) @@ -405,7 +490,11 @@ namespace rct { FIELD(outPk) VARINT_FIELD(txnFee) FIELD(p_r) - if (type == RCTTypeFullProofs) { + if (type == RCTTypeSalviumZero || type == RCTTypeSalviumOne) + { + FIELD(salvium_data) + } + else if (type == RCTTypeFullProofs) { FIELD(pr_proof) FIELD(sa_proof) } @@ -417,6 +506,7 @@ namespace rct { std::vector bulletproofs_plus; std::vector MGs; // simple rct has N, full has 1 std::vector CLSAGs; + std::vector TCLSAGs; keyV pseudoOuts; //C - for simple rct // when changing this function, update cryptonote::get_pruned_transaction_weight @@ -431,9 +521,9 @@ namespace rct { return false; if (type == RCTTypeNull) return ar.stream().good(); - if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs) + if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeFullProofs && type != RCTTypeSalviumZero && type != RCTTypeSalviumOne) return false; - if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs) + if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne) { uint32_t nbp = bulletproofs_plus.size(); VARINT_FIELD(nbp) @@ -490,7 +580,60 @@ namespace rct { ar.end_array(); } - if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs) + if (type == RCTTypeSalviumOne) + { + ar.tag("TCLSAGs"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(inputs, TCLSAGs); + if (TCLSAGs.size() != inputs) + return false; + for (size_t i = 0; i < inputs; ++i) + { + // we save the TCLSAGs contents directly, because we want it to save its + // arrays without the size prefixes, and the load can't know what size + // to expect if it's not in the data + ar.begin_object(); + ar.tag("sx"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, TCLSAGs[i].sx); + if (TCLSAGs[i].sx.size() != mixin + 1) + return false; + for (size_t j = 0; j <= mixin; ++j) + { + FIELDS(TCLSAGs[i].sx[j]) + if (mixin + 1 - j > 1) + ar.delimit_array(); + } + ar.end_array(); + + ar.tag("sy"); + ar.begin_array(); + PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, TCLSAGs[i].sy); + if (TCLSAGs[i].sy.size() != mixin + 1) + return false; + for (size_t j = 0; j <= mixin; ++j) + { + FIELDS(TCLSAGs[i].sy[j]) + if (mixin + 1 - j > 1) + ar.delimit_array(); + } + ar.end_array(); + + ar.tag("c1"); + FIELDS(TCLSAGs[i].c1) + + // CLSAGs[i].I not saved, it can be reconstructed + ar.tag("D"); + FIELDS(TCLSAGs[i].D) + ar.end_object(); + + if (inputs - i > 1) + ar.delimit_array(); + } + + ar.end_array(); + + } else if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero) { ar.tag("CLSAGs"); ar.begin_array(); @@ -565,7 +708,7 @@ namespace rct { ar.delimit_array(); } ar.end_array(); - + if (mixin + 1 - j > 1) ar.delimit_array(); } @@ -581,7 +724,7 @@ namespace rct { } ar.end_array(); } - if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs) + if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne) { ar.tag("pseudoOuts"); ar.begin_array(); @@ -605,6 +748,7 @@ namespace rct { FIELD(bulletproofs_plus) FIELD(MGs) FIELD(CLSAGs) + FIELD(TCLSAGs) FIELD(pseudoOuts) END_SERIALIZE() }; @@ -613,12 +757,12 @@ namespace rct { keyV& get_pseudo_outs() { - return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs ? p.pseudoOuts : pseudoOuts; + return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts; } keyV const& get_pseudo_outs() const { - return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs ? p.pseudoOuts : pseudoOuts; + return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne ? p.pseudoOuts : pseudoOuts; } BEGIN_SERIALIZE_OBJECT() @@ -790,5 +934,8 @@ VARIANT_TAG(binary_archive, rct::multisig_out, 0x9e); VARIANT_TAG(binary_archive, rct::clsag, 0x9f); VARIANT_TAG(binary_archive, rct::BulletproofPlus, 0xa0); VARIANT_TAG(binary_archive, rct::zk_proof, 0xa1); +VARIANT_TAG(binary_archive, rct::salvium_input_data_t, 0xa2); +VARIANT_TAG(binary_archive, rct::salvium_data_t, 0xa3); +VARIANT_TAG(binary_archive, rct::tclsag, 0xa4); #endif /* RCTTYPES_H */ diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h index 6fa5479..62408bb 100644 --- a/src/serialization/crypto.h +++ b/src/serialization/crypto.h @@ -10,6 +10,7 @@ #include "crypto/chacha8.h" #include "crypto/crypto.h" #include "crypto/hash.h" +#include "carrot_core/core_types.h" // read template