From 99bda32d0f3bb759a304e838a906445a18b5db8d Mon Sep 17 00:00:00 2001 From: j-berman Date: Fri, 6 Mar 2026 16:57:24 -0800 Subject: [PATCH] FCMP++: output_to_tuple {output pubkey, commitment} -> {O,I,C} - Function to convert an {output pubkey, commitment} to an output tuple {O,I,C} in prepartion to insert the output tuple into the curve tree. - O = torsion cleared valid output pubkey checked for identity. - I = key image generator. - C = torsion cleared valid Commitment checked for identity. - None of {O,I,C} should have torsion nor == identity. - Introduces the OutputPair variant, which can either be Legacy or Carrot V1 types. Legacy outputs are not checked for torsion at consensus, and use the legacy biased hash to point fn to derive the key image generator (I). Carrot V1 outputs **are** checked for torsion at consensus, and use the unbiased hash to point to derive the key image generator (I). --- src/fcmp_pp/CMakeLists.txt | 6 +- src/fcmp_pp/curve_trees.cpp | 109 ++++++++++++++++++++++ src/fcmp_pp/curve_trees.h | 46 ++++++++++ src/fcmp_pp/fcmp_pp_rust/CMakeLists.txt | 27 ++++++ src/fcmp_pp/fcmp_pp_rust/fcmp++.h | 39 ++++++++ src/fcmp_pp/fcmp_pp_types.cpp | 108 ++++++++++++++++++++++ src/fcmp_pp/fcmp_pp_types.h | 115 ++++++++++++++++++++++++ src/fcmp_pp/ffi_api_c_compat.c | 3 + 8 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 src/fcmp_pp/curve_trees.cpp create mode 100644 src/fcmp_pp/curve_trees.h create mode 100644 src/fcmp_pp/fcmp_pp_rust/CMakeLists.txt create mode 100644 src/fcmp_pp/fcmp_pp_rust/fcmp++.h create mode 100644 src/fcmp_pp/fcmp_pp_types.cpp create mode 100644 src/fcmp_pp/fcmp_pp_types.h create mode 100644 src/fcmp_pp/ffi_api_c_compat.c diff --git a/src/fcmp_pp/CMakeLists.txt b/src/fcmp_pp/CMakeLists.txt index 32ca1b4f2..d5eebdc3e 100644 --- a/src/fcmp_pp/CMakeLists.txt +++ b/src/fcmp_pp/CMakeLists.txt @@ -27,10 +27,14 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(fcmp_pp_sources - fcmp_pp_crypto.cpp) + curve_trees.cpp + fcmp_pp_crypto.cpp + fcmp_pp_types.cpp) monero_find_all_headers(fcmp_pp_headers "${CMAKE_CURRENT_SOURCE_DIR}") +add_subdirectory(fcmp_pp_rust) + monero_add_library(fcmp_pp ${fcmp_pp_sources} ${fcmp_pp_headers}) diff --git a/src/fcmp_pp/curve_trees.cpp b/src/fcmp_pp/curve_trees.cpp new file mode 100644 index 000000000..a533390d4 --- /dev/null +++ b/src/fcmp_pp/curve_trees.cpp @@ -0,0 +1,109 @@ +// 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. + +#include "curve_trees.h" + +#include "crypto/crypto.h" +#include "fcmp_pp_crypto.h" +#include "fcmp_pp_types.h" +#include "profile_tools.h" + + +namespace fcmp_pp +{ +namespace curve_trees +{ +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +OutputTuple output_to_tuple(const OutputPair &output_pair) +{ + const crypto::public_key &output_pubkey = output_pubkey_cref(output_pair); + const crypto::ec_point &commitment = commitment_cref(output_pair); + + TIME_MEASURE_NS_START(derive_key_image_generator_ns); + + // Derive key image generator using the original output pubkey. + // CRITICAL: it's CRITICALLY important that we use the original output pubkey here, and not `O` calculated later. + // If we were to use `O`, then an output with torsion could be double spent before and after the FCMP++ fork, since + // it would have 1 key image before the fork (tied to the output pubkey) and a distinct key image (tied to torsion + // cleared `O`). + crypto::ec_point I; + crypto::derive_key_image_generator(output_pubkey, use_biased_hash_to_point(output_pair), I); + + TIME_MEASURE_NS_FINISH(derive_key_image_generator_ns); + + LOG_PRINT_L3("derive_key_image_generator_ns: " << derive_key_image_generator_ns); + + // Get O and C from output pubkey and commitment + crypto::ec_point O = output_pubkey; + crypto::ec_point C = commitment; + + // If the output has already been checked for torsion, then we don't need to clear torsion here + if (!output_checked_for_torsion(output_pair)) + { + TIME_MEASURE_NS_START(clear_torsion_ns); + + if (!fcmp_pp::get_valid_torsion_cleared_point_vartime(output_pubkey, O)) + throw std::runtime_error("O is invalid for insertion to tree"); + if (!fcmp_pp::get_valid_torsion_cleared_point_vartime(commitment, C)) + throw std::runtime_error("C is invalid for insertion to tree"); + + if (O != output_pubkey) + LOG_PRINT_L2("Output pubkey has torsion: " << output_pubkey); + if (C != commitment) + LOG_PRINT_L2("Commitment has torsion: " << commitment); + + TIME_MEASURE_NS_FINISH(clear_torsion_ns); + + LOG_PRINT_L3("clear_torsion_ns: " << clear_torsion_ns); + } + +#if !defined(NDEBUG) + { + // Debug build safety checks + crypto::ec_point O_debug; + crypto::ec_point C_debug; + assert(fcmp_pp::get_valid_torsion_cleared_point_vartime(output_pubkey, O_debug)); + assert(fcmp_pp::get_valid_torsion_cleared_point_vartime(commitment, C_debug)); + assert(O == O_debug); + assert(C == C_debug); + } +#endif + + // Redundant check for safety + if (O == fcmp_pp::EC_I) + throw std::runtime_error("O cannot equal identity"); + if (C == fcmp_pp::EC_I) + throw std::runtime_error("C cannot equal identity"); + + return output_tuple_from_bytes(O, I, C); +} +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +} //namespace curve_trees +} //namespace fcmp_pp diff --git a/src/fcmp_pp/curve_trees.h b/src/fcmp_pp/curve_trees.h new file mode 100644 index 000000000..ceb62f354 --- /dev/null +++ b/src/fcmp_pp/curve_trees.h @@ -0,0 +1,46 @@ +// 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. + +#pragma once + +#include "crypto/crypto.h" +#include "fcmp_pp_types.h" +#include "misc_log_ex.h" + + +namespace fcmp_pp +{ +namespace curve_trees +{ +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +OutputTuple output_to_tuple(const OutputPair &output_pair); +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +} //namespace curve_trees +} //namespace fcmp_pp diff --git a/src/fcmp_pp/fcmp_pp_rust/CMakeLists.txt b/src/fcmp_pp/fcmp_pp_rust/CMakeLists.txt new file mode 100644 index 000000000..bdad6f5b5 --- /dev/null +++ b/src/fcmp_pp/fcmp_pp_rust/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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. diff --git a/src/fcmp_pp/fcmp_pp_rust/fcmp++.h b/src/fcmp_pp/fcmp_pp_rust/fcmp++.h new file mode 100644 index 000000000..a4f2e9381 --- /dev/null +++ b/src/fcmp_pp/fcmp_pp_rust/fcmp++.h @@ -0,0 +1,39 @@ +// Copyright (c) 2025, 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. + +#pragma once + +#include + + +struct OutputTuple +{ + uint8_t O[32]; + uint8_t I[32]; + uint8_t C[32]; +}; diff --git a/src/fcmp_pp/fcmp_pp_types.cpp b/src/fcmp_pp/fcmp_pp_types.cpp new file mode 100644 index 000000000..517f69f30 --- /dev/null +++ b/src/fcmp_pp/fcmp_pp_types.cpp @@ -0,0 +1,108 @@ +// 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. + +#include "fcmp_pp_types.h" + +#include "misc_log_ex.h" + +namespace fcmp_pp +{ +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +// Helpers +//---------------------------------------------------------------------------------------------------------------------- +OutputTuple output_tuple_from_bytes(const crypto::ec_point &O, const crypto::ec_point &I, const crypto::ec_point &C) +{ + OutputTuple output_tuple; + + static_assert(sizeof(output_tuple.O) == sizeof(O), "unexpected sizeof O"); + static_assert(sizeof(output_tuple.I) == sizeof(I), "unexpected sizeof I"); + static_assert(sizeof(output_tuple.C) == sizeof(C), "unexpected sizeof C"); + + memcpy(output_tuple.O, &O, sizeof(O)); + memcpy(output_tuple.I, &I, sizeof(I)); + memcpy(output_tuple.C, &C, sizeof(C)); + + return output_tuple; +} +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +const crypto::public_key &output_pubkey_cref(const OutputPair &output_pair) +{ + struct output_pair_visitor + { + const crypto::public_key &operator()(const LegacyOutputPair &o) const + { return o.output_pubkey; } + const crypto::public_key &operator()(const CarrotOutputPairV1 &o) const + { return o.output_pubkey; } + }; + + return std::visit(output_pair_visitor{}, output_pair); +} +//---------------------------------------------------------------------------------------------------------------------- +const crypto::ec_point &commitment_cref(const OutputPair &output_pair) +{ + struct output_pair_visitor + { + const crypto::ec_point &operator()(const LegacyOutputPair &o) const + { return o.commitment; } + const crypto::ec_point &operator()(const CarrotOutputPairV1 &o) const + { return o.commitment; } + }; + + return std::visit(output_pair_visitor{}, output_pair); +} +//---------------------------------------------------------------------------------------------------------------------- +bool output_checked_for_torsion(const OutputPair &output_pair) +{ + struct output_pair_visitor + { + bool operator()(const LegacyOutputPair&) const + { return false; } + bool operator()(const CarrotOutputPairV1&) const + { return true; } + }; + + return std::visit(output_pair_visitor{}, output_pair); +} +//---------------------------------------------------------------------------------------------------------------------- +bool use_biased_hash_to_point(const OutputPair &output_pair) +{ + struct output_pair_visitor + { + bool operator()(const LegacyOutputPair&) const + { return true; } + bool operator()(const CarrotOutputPairV1&) const + { return false; } + }; + + return std::visit(output_pair_visitor{}, output_pair); +} +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +}//namespace fcmp_pp diff --git a/src/fcmp_pp/fcmp_pp_types.h b/src/fcmp_pp/fcmp_pp_types.h new file mode 100644 index 000000000..80a783931 --- /dev/null +++ b/src/fcmp_pp/fcmp_pp_types.h @@ -0,0 +1,115 @@ +// 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. + +#pragma once + +#include +#include +#include + +#include "crypto/crypto.h" +#include "fcmp_pp_rust/fcmp++.h" + + +namespace fcmp_pp +{ +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +// Rust types +//---------------------------------------------------------------------------------------------------------------------- +using OutputTuple = ::OutputTuple; +//---------------------------------------------------------------------------------------------------------------------- +OutputTuple output_tuple_from_bytes(const crypto::ec_point &O, const crypto::ec_point &I, const crypto::ec_point &C); +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +// C++ types +//---------------------------------------------------------------------------------------------------------------------- +// Curve trees types +//---------------------------------------------------------------------------------------------------------------------- +// Output pubkey and commitment, ready to be converted to a leaf tuple +// - From {output_pubkey,commitment} -> {O,C} -> {O,I,C} -> {O.x,O.y,I.x,I.y,C.x,C.y} +// - Output pairs do NOT necessarily have torsion cleared. We need the output pubkey as it exists in the chain in order +// to derive the correct I (when deriving {O.x,O.y,I.x,I.y,C.x,C.y}). Torsion clearing O before deriving I from O +// would enable spending a torsioned output once before FCMP++ fork and again with a different key image via FCMP++. +template +struct OutputPairTemplate +{ + crypto::public_key output_pubkey; + // Uses the ec_point type to avoid a circular dep to ringct/rctTypes.h, and to differentiate from output_pubkey + crypto::ec_point commitment; + + OutputPairTemplate(const crypto::public_key &_output_pubkey, const crypto::ec_point &_commitment): + output_pubkey(_output_pubkey), + commitment(_commitment) + {}; + + OutputPairTemplate(): + output_pubkey{}, + commitment{} + {}; + + // WARNING: not constant time + bool operator==(const OutputPairTemplate &other) const + { + return output_pubkey == other.output_pubkey + && commitment == other.commitment; + } +}; + +// May have torsion, use biased key image generator for I +struct LegacyOutputPair : public OutputPairTemplate{}; +// No torsion, use unbiased key image generator for I +struct CarrotOutputPairV1 : public OutputPairTemplate{}; + +static_assert(sizeof(LegacyOutputPair) == (32+32), "sizeof LegacyOutputPair unexpected"); +static_assert(sizeof(CarrotOutputPairV1) == (32+32), "sizeof CarrotOutputPairV1 unexpected"); + +static_assert(std::has_unique_object_representations_v); +static_assert(std::has_unique_object_representations_v); + +using OutputPair = std::variant; + +const crypto::public_key &output_pubkey_cref(const OutputPair &output_pair); +const crypto::ec_point &commitment_cref(const OutputPair &output_pair); + +bool output_checked_for_torsion(const OutputPair &output_pair); +bool use_biased_hash_to_point(const OutputPair &output_pair); +//---------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------- +}//namespace fcmp_pp + +// WARNING: not constant time +inline bool operator==(const fcmp_pp::OutputTuple &a, const fcmp_pp::OutputTuple &b) +{ + static_assert(sizeof(fcmp_pp::OutputTuple) == (sizeof(a.O) + sizeof(a.I) + sizeof(a.C)), + "unexpected sizeof OutputTuple for == implementation"); + return + (memcmp(a.O, b.O, sizeof(a.O)) == 0) && + (memcmp(a.I, b.I, sizeof(a.I)) == 0) && + (memcmp(a.C, b.C, sizeof(a.C)) == 0); +} diff --git a/src/fcmp_pp/ffi_api_c_compat.c b/src/fcmp_pp/ffi_api_c_compat.c new file mode 100644 index 000000000..c92510ebd --- /dev/null +++ b/src/fcmp_pp/ffi_api_c_compat.c @@ -0,0 +1,3 @@ +#include "fcmp++.h" + +int main() { return 0; }