Remove cxx and expose scalars/points directly

This commit is contained in:
Luke Parker 2024-05-23 20:44:55 -04:00 committed by j-berman
parent af9b74fcc7
commit af47a135eb
14 changed files with 1099 additions and 303 deletions

2
.gitignore vendored
View File

@ -120,5 +120,3 @@ nbproject
__pycache__/ __pycache__/
*.pyc *.pyc
*.log *.log
Cargo.lock

3
.gitmodules vendored
View File

@ -14,6 +14,3 @@
path = external/supercop path = external/supercop
url = https://github.com/monero-project/supercop url = https://github.com/monero-project/supercop
branch = monero branch = monero
[submodule "external/fcmp-plus-plus"]
path = external/fcmp-plus-plus
url = https://github.com/kayabaNerve/fcmp-plus-plus.git

View File

@ -36,7 +36,7 @@ add_subdirectory(fcmp_rust)
monero_add_library_with_deps( monero_add_library_with_deps(
NAME fcmp NAME fcmp
DEPENDS rust_cxx DEPENDS fcmp_rust
SOURCES SOURCES
${fcmp_sources} ${fcmp_sources}
${fcmp_headers}) ${fcmp_headers})
@ -46,5 +46,5 @@ target_link_libraries(fcmp
crypto crypto
epee epee
PRIVATE PRIVATE
fcmp_rust ${CMAKE_CURRENT_BINARY_DIR}/fcmp_rust/libfcmp_rust.a
${EXTRA_LIBRARIES}) ${EXTRA_LIBRARIES})

View File

@ -1,21 +1,21 @@
// Copyright (c) 2024, The Monero Project // Copyright (c) 2024, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 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 // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // 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 // 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 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -46,7 +46,7 @@ typename C::Point get_new_parent(const C &curve, const typename C::Chunk &new_ch
{ {
// New parent means no prior children, fill priors with 0 // New parent means no prior children, fill priors with 0
std::vector<typename C::Scalar> prior_children; std::vector<typename C::Scalar> prior_children;
tower_cycle::extend_zeroes(curve, new_children.size(), prior_children); tower_cycle::extend_zeroes(curve, new_children.len, prior_children);
return curve.hash_grow( return curve.hash_grow(
curve.m_hash_init_point, curve.m_hash_init_point,
@ -76,17 +76,17 @@ static typename C::Point get_first_parent(const C &curve,
if (child_layer_last_hash_updated) if (child_layer_last_hash_updated)
{ {
// If the last chunk has updated children in it, then we need to get the delta to the old children // If the last chunk has updated children in it, then we need to get the delta to the old children
prior_children.emplace_back(curve.clone(last_chunk_ptr->last_child)); prior_children.emplace_back(last_chunk_ptr->last_child);
// Extend prior children by zeroes for any additional new children, since they must be new // Extend prior children by zeroes for any additional new children, since they must be new
if (new_children.size() > 1) if (new_children.len > 1)
tower_cycle::extend_zeroes(curve, new_children.size() - 1, prior_children); tower_cycle::extend_zeroes(curve, new_children.len - 1, prior_children);
} }
else if (offset > 0) else if (offset > 0)
{ {
// If we're updating the parent hash and no children were updated, then we're just adding new children // If we're updating the parent hash and no children were updated, then we're just adding new children
// to the existing last chunk and can fill priors with 0 // to the existing last chunk and can fill priors with 0
tower_cycle::extend_zeroes(curve, new_children.size(), prior_children); tower_cycle::extend_zeroes(curve, new_children.len, prior_children);
} }
else else
{ {
@ -190,8 +190,9 @@ static void hash_layer(const C &curve,
const auto chunk_start = child_scalars.data() + chunk_start_idx; const auto chunk_start = child_scalars.data() + chunk_start_idx;
const typename C::Chunk chunk{chunk_start, chunk_size}; const typename C::Chunk chunk{chunk_start, chunk_size};
for (const auto &c : chunk) for (uint c = 0; c < chunk_size; ++c) {
MDEBUG("Hashing " << curve.to_string(c)); MDEBUG("Hashing " << curve.to_string(chunk_start[c]));
}
// Hash the chunk of children // Hash the chunk of children
typename C::Point chunk_hash = chunk_start_idx == 0 typename C::Point chunk_hash = chunk_start_idx == 0
@ -264,9 +265,9 @@ typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extensio
for (const auto &leaf : new_leaf_tuples) for (const auto &leaf : new_leaf_tuples)
{ {
tree_extension.leaves.tuples.emplace_back(LeafTuple{ tree_extension.leaves.tuples.emplace_back(LeafTuple{
.O_x = m_c2.clone(leaf.O_x), .O_x = leaf.O_x,
.I_x = m_c2.clone(leaf.I_x), .I_x = leaf.I_x,
.C_x = m_c2.clone(leaf.C_x) .C_x = leaf.C_x
}); });
} }
@ -378,9 +379,9 @@ std::vector<typename C2::Scalar> CurveTrees<C1, C2>::flatten_leaves(const std::v
for (const auto &l : leaves) for (const auto &l : leaves)
{ {
// TODO: implement without cloning // TODO: implement without cloning
flattened_leaves.emplace_back(m_c2.clone(l.O_x)); flattened_leaves.emplace_back(l.O_x);
flattened_leaves.emplace_back(m_c2.clone(l.I_x)); flattened_leaves.emplace_back(l.I_x);
flattened_leaves.emplace_back(m_c2.clone(l.C_x)); flattened_leaves.emplace_back(l.C_x);
} }
return flattened_leaves; return flattened_leaves;

4
src/fcmp/fcmp_rust/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# If a developer runs cargo build inside this sub-directory to only work with
# the Rust side of things, they'll create this target directory which shouldn't
# be committed
target

View File

@ -34,37 +34,28 @@ else ()
set(TARGET_DIR "release") set(TARGET_DIR "release")
endif () endif ()
set(FCMP_RUST_CXX "${CMAKE_CURRENT_BINARY_DIR}/fcmp_rust.cc")
set(FCMP_RUST_HEADER_DIR "${MONERO_GENERATED_HEADERS_DIR}/fcmp_rust") set(FCMP_RUST_HEADER_DIR "${MONERO_GENERATED_HEADERS_DIR}/fcmp_rust")
set(FCMP_RUST_HEADER "${FCMP_RUST_HEADER_DIR}/fcmp_rust.h") set(FCMP_RUST_HEADER "${FCMP_RUST_HEADER_DIR}/fcmp++.h")
set(CXX_HEADER "${FCMP_RUST_HEADER_DIR}/cxx.h") set(FCMP_RUST_LIB "${CMAKE_CURRENT_BINARY_DIR}/libfcmp_rust.a")
# Removing OUTPUT files makes sure custom command runs every time # Removing OUTPUT files makes sure custom command runs every time
file(REMOVE_RECURSE "${FCMP_RUST_CXX}")
file(REMOVE_RECURSE "${FCMP_RUST_HEADER_DIR}") file(REMOVE_RECURSE "${FCMP_RUST_HEADER_DIR}")
file(MAKE_DIRECTORY "${FCMP_RUST_HEADER_DIR}") file(MAKE_DIRECTORY "${FCMP_RUST_HEADER_DIR}")
file(REMOVE "${FCMP_RUST_LIB}")
add_custom_command( add_custom_command(
COMMENT "Building rust fcmp lib" COMMENT "Building rust fcmp lib"
OUTPUT ${FCMP_RUST_CXX} ${FCMP_RUST_HEADER} ${CXX_HEADER} OUTPUT ${FCMP_RUST_HEADER}
OUTPUT ${FCMP_RUST_LIB}
COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} ${CARGO_CMD} COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} ${CARGO_CMD}
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/fcmp_rust/src/lib.rs.cc ${FCMP_RUST_CXX} COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/fcmp++.h ${FCMP_RUST_HEADER}
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/fcmp_rust/src/lib.rs.h ${FCMP_RUST_HEADER} COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR}/libfcmp_rust.a ${FCMP_RUST_LIB}
COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/cxxbridge/rust/cxx.h ${CXX_HEADER}
COMMAND echo "Finished copying fcmp rust targets" COMMAND echo "Finished copying fcmp rust targets"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM VERBATIM
) )
add_custom_target(rust_cxx ALL DEPENDS ${CXX_HEADER}) #monero_find_all_headers(fcmp_rust_headers "${FCMP_RUST_HEADER_DIR}")
add_custom_target(fcmp_rust DEPENDS ${FCMP_RUST_LIB})
set(fcmp_rust_sources ${FCMP_RUST_CXX}) #target_link_libraries(fcmp ${FCMP_RUST_LIB})
monero_find_all_headers(fcmp_rust_headers "${FCMP_RUST_HEAfDER_DIR}")
monero_add_library(fcmp_rust
${fcmp_rust_sources}
${fcmp_rust_headers})
set(FCMP_RUST_LIB "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_DIR}/libfcmp_rust.a")
target_link_libraries(fcmp_rust dl ${FCMP_RUST_LIB})

716
src/fcmp/fcmp_rust/Cargo.lock generated Normal file
View File

@ -0,0 +1,716 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "base16ct"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array 0.14.7",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "ciphersuite"
version = "0.4.1"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"blake2",
"dalek-ff-group",
"digest",
"elliptic-curve",
"ff",
"flexible-transcript",
"group",
"helioselene",
"k256",
"minimal-ed448",
"p256",
"rand_core",
"sha2",
"sha3",
"std-shims",
"subtle",
"zeroize",
]
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-bigint"
version = "0.5.5"
source = "git+https://github.com/kayabaNerve/crypto-bigint?branch=c-repr#78352771313f1e9b8e48abe5ce30d50d6bdd291d"
dependencies = [
"generic-array 0.14.7",
"rand_core",
"subtle",
"zeroize",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array 0.14.7",
"typenum",
]
[[package]]
name = "curve25519-dalek"
version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
"group",
"platforms",
"rand_core",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "dalek-ff-group"
version = "0.4.1"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"crypto-bigint",
"curve25519-dalek",
"digest",
"ff",
"group",
"rand_core",
"rustversion",
"subtle",
"zeroize",
]
[[package]]
name = "der"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
dependencies = [
"const-oid",
"zeroize",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "ec-divisors"
version = "0.1.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"dalek-ff-group",
"group",
"hex",
"rand_core",
"zeroize",
]
[[package]]
name = "ecdsa"
version = "0.16.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
dependencies = [
"der",
"elliptic-curve",
"signature",
"spki",
]
[[package]]
name = "elliptic-curve"
version = "0.13.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
dependencies = [
"base16ct",
"crypto-bigint",
"digest",
"ff",
"generic-array 0.14.7",
"group",
"pkcs8",
"rand_core",
"sec1",
"subtle",
"tap",
"zeroize",
]
[[package]]
name = "fcmp_rust"
version = "0.0.0"
dependencies = [
"ciphersuite",
"ec-divisors",
"flexible-transcript",
"full-chain-membership-proofs",
"generalized-bulletproofs",
"helioselene",
"rand_core",
]
[[package]]
name = "ff"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
dependencies = [
"bitvec",
"rand_core",
"subtle",
]
[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "flexible-transcript"
version = "0.3.2"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"blake2",
"digest",
"merlin",
"rustversion",
"subtle",
"zeroize",
]
[[package]]
name = "full-chain-membership-proofs"
version = "0.1.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"ciphersuite",
"ec-divisors",
"flexible-transcript",
"generalized-bulletproofs",
"multiexp",
"rand_core",
"zeroize",
]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "generalized-bulletproofs"
version = "0.1.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"ciphersuite",
"flexible-transcript",
"multiexp",
"rand_core",
"zeroize",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
"zeroize",
]
[[package]]
name = "generic-array"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0"
dependencies = [
"typenum",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "group"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
dependencies = [
"ff",
"rand_core",
"subtle",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "helioselene"
version = "0.1.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"crypto-bigint",
"dalek-ff-group",
"ec-divisors",
"ff",
"group",
"rand_core",
"rustversion",
"subtle",
"zeroize",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "k256"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b"
dependencies = [
"cfg-if",
"ecdsa",
"elliptic-curve",
"once_cell",
]
[[package]]
name = "keccak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
dependencies = [
"cpufeatures",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "merlin"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d"
dependencies = [
"byteorder",
"keccak",
"rand_core",
"zeroize",
]
[[package]]
name = "minimal-ed448"
version = "0.4.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"crypto-bigint",
"ff",
"generic-array 1.0.0",
"group",
"rand_core",
"rustversion",
"subtle",
"zeroize",
]
[[package]]
name = "multiexp"
version = "0.4.0"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"ff",
"group",
"rand_core",
"rustversion",
"std-shims",
"zeroize",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "p256"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
dependencies = [
"ecdsa",
"elliptic-curve",
"primeorder",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]]
name = "platforms"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
[[package]]
name = "primeorder"
version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
dependencies = [
"elliptic-curve",
]
[[package]]
name = "proc-macro2"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "sec1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
dependencies = [
"base16ct",
"der",
"generic-array 0.14.7",
"pkcs8",
"subtle",
"zeroize",
]
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"rand_core",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
]
[[package]]
name = "std-shims"
version = "0.1.1"
source = "git+https://github.com/kayabaNerve/fcmp-plus-plus#a17500708f5c6d79ec9cc33d53c771149db152c3"
dependencies = [
"hashbrown",
"spin",
]
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "2.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]]
name = "zerocopy"
version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -8,14 +8,16 @@ name = "fcmp_rust"
crate-type = ["staticlib"] crate-type = ["staticlib"]
[dependencies] [dependencies]
cxx = "1.0"
full-chain-membership-proofs = { path = "../../../external/fcmp-plus-plus/crypto/fcmps" }
ciphersuite = { path = "../../../external/fcmp-plus-plus/crypto/ciphersuite", features = ["helioselene", "ed25519"] }
ec-divisors = { path = "../../../external/fcmp-plus-plus/crypto/divisors", features = ["ed25519"] }
rand_core = { version = "0.6", features = ["getrandom"] } rand_core = { version = "0.6", features = ["getrandom"] }
transcript = { package = "flexible-transcript", path = "../../../external/fcmp-plus-plus/crypto/transcript", features = ["recommended"] }
generalized-bulletproofs = { path = "../../../external/fcmp-plus-plus/crypto/generalized-bulletproofs", features = ["tests"] }
[build-dependencies] transcript = { package = "flexible-transcript", git = "https://github.com/kayabaNerve/fcmp-plus-plus", features = ["recommended"] }
cxx-build = "1.0" helioselene = { git = "https://github.com/kayabaNerve/fcmp-plus-plus" }
ciphersuite = { git = "https://github.com/kayabaNerve/fcmp-plus-plus", features = ["ed25519", "helioselene"] }
generalized-bulletproofs = { git = "https://github.com/kayabaNerve/fcmp-plus-plus", features = ["tests"] }
ec-divisors = { git = "https://github.com/kayabaNerve/fcmp-plus-plus", features = ["ed25519"] }
full-chain-membership-proofs = { git = "https://github.com/kayabaNerve/fcmp-plus-plus" }
[patch.crates-io]
crypto-bigint = { git = "https://github.com/kayabaNerve/crypto-bigint", branch = "c-repr" }

View File

@ -1,5 +0,0 @@
fn main() {
let _ = cxx_build::bridge("src/lib.rs");
println!("cargo:rerun-if-changed=src/lib.rs");
}

144
src/fcmp/fcmp_rust/fcmp++.h Normal file
View File

@ -0,0 +1,144 @@
namespace fcmp_rust {
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
// ----- deps C bindings -----
/// Inner integer type that the [`Limb`] newtype wraps.
// TODO: This is only valid for 64-bit platforms
using Word = uint64_t;
/// Big integers are represented as an array of smaller CPU word-size integers
/// called "limbs".
using Limb = Word;
/// Stack-allocated big unsigned integer.
///
/// Generic over the given number of `LIMBS`
///
/// # Encoding support
/// This type supports many different types of encodings, either via the
/// [`Encoding`][`crate::Encoding`] trait or various `const fn` decoding and
/// encoding functions that can be used with [`Uint`] constants.
///
/// Optional crate features for encoding (off-by-default):
/// - `generic-array`: enables [`ArrayEncoding`][`crate::ArrayEncoding`] trait which can be used to
/// [`Uint`] as `GenericArray<u8, N>` and a [`ArrayDecoding`][`crate::ArrayDecoding`] trait which
/// can be used to `GenericArray<u8, N>` as [`Uint`].
/// - `rlp`: support for [Recursive Length Prefix (RLP)][RLP] encoding.
///
/// [RLP]: https://eth.wiki/fundamentals/rlp
template<uintptr_t LIMBS>
struct Uint {
/// Inner limb array. Stored from least significant to most significant.
Limb limbs[LIMBS];
};
/// A residue mod `MOD`, represented using `LIMBS` limbs. The modulus of this residue is constant, so it cannot be set at runtime.
/// Internally, the value is stored in Montgomery form (multiplied by MOD::R) until it is retrieved.
template<uintptr_t LIMBS>
struct Residue {
Uint<LIMBS> montgomery_form;
};
/// A constant-time implementation of the Ed25519 field.
struct SeleneScalar {
Residue<4> _0;
};
/// The field novel to Helios/Selene.
struct HeliosScalar {
Residue<4> _0;
};
struct HeliosPoint {
SeleneScalar x;
SeleneScalar y;
SeleneScalar z;
};
struct SelenePoint {
HeliosScalar x;
HeliosScalar y;
HeliosScalar z;
};
// ----- End deps C bindings -----
template<typename T = void>
struct Box;
struct HeliosGenerators {
void* generators;
};
struct SeleneGenerators {
void* generators;
};
template<typename T>
struct CResult {
T value;
void* err;
};
template<typename T>
struct Slice {
const T *buf;
uintptr_t len;
};
using HeliosScalarSlice = Slice<HeliosScalar>;
using SeleneScalarSlice = Slice<SeleneScalar>;
extern "C" {
HeliosGenerators random_helios_generators(uintptr_t n);
SeleneGenerators random_selene_generators(uintptr_t n);
HeliosPoint random_helios_hash_init_point();
SelenePoint random_selene_hash_init_point();
uint8_t *helios_scalar_to_bytes(HeliosScalar helios_scalar);
uint8_t *selene_scalar_to_bytes(SeleneScalar selene_scalar);
uint8_t *helios_point_to_bytes(HeliosPoint helios_point);
uint8_t *selene_point_to_bytes(SelenePoint selene_point);
SeleneScalar ed25519_point_to_selene_scalar(const uint8_t *ed25519_point);
HeliosScalar selene_point_to_helios_scalar(SelenePoint selene_point);
SeleneScalar helios_point_to_selene_scalar(HeliosPoint helios_point);
HeliosScalar helios_zero_scalar();
SeleneScalar selene_zero_scalar();
CResult<HeliosPoint> hash_grow_helios(const HeliosGenerators *helios_generators,
HeliosPoint existing_hash,
uintptr_t offset,
HeliosScalarSlice prior_children,
HeliosScalarSlice new_children);
CResult<SelenePoint> hash_grow_selene(const SeleneGenerators *selene_generators,
SelenePoint existing_hash,
uintptr_t offset,
SeleneScalarSlice prior_children,
SeleneScalarSlice new_children);
} // extern "C"
}

View File

@ -1,226 +1,186 @@
use rand_core::OsRng;
use std::io; use std::io;
use full_chain_membership_proofs::tree::hash_grow; use rand_core::OsRng;
use transcript::RecommendedTranscript; use transcript::RecommendedTranscript;
use helioselene::{HeliosPoint, SelenePoint, HelioseleneField as HeliosScalar, Field25519 as SeleneScalar};
use ciphersuite::{group::{Group, GroupEncoding, ff::{PrimeField, Field}}, Ciphersuite, Ed25519, Selene, Helios}; use ciphersuite::{group::{Group, GroupEncoding, ff::{PrimeField, Field}}, Ciphersuite, Ed25519, Selene, Helios};
use ec_divisors::DivisorCurve;
use generalized_bulletproofs::Generators; use generalized_bulletproofs::Generators;
// TODO: lint use ec_divisors::DivisorCurve;
#[cxx::bridge] use full_chain_membership_proofs::tree::hash_grow;
mod ffi {
// Rust types and signatures exposed to C++.
#[namespace = "fcmp_rust"]
extern "Rust" {
// TODO: Separate Helios and Selene namespaces
type HeliosGenerators;
type HeliosPoint;
type HeliosScalar;
type SeleneGenerators;
type SelenePoint;
type SeleneScalar;
fn random_helios_generators(n: usize) -> Box<HeliosGenerators>;
fn random_helios_hash_init_point() -> Box<HeliosPoint>;
fn random_selene_generators(n: usize) -> Box<SeleneGenerators>;
fn random_selene_hash_init_point() -> Box<SelenePoint>;
fn clone_helios_scalar(helios_scalar: &Box<HeliosScalar>) -> Box<HeliosScalar>;
fn clone_selene_scalar(selene_scalar: &Box<SeleneScalar>) -> Box<SeleneScalar>;
fn clone_helios_point(helios_point: &Box<HeliosPoint>) -> Box<HeliosPoint>;
fn clone_selene_point(selene_point: &Box<SelenePoint>) -> Box<SelenePoint>;
fn helios_scalar_to_bytes(helios_scalar: &Box<HeliosScalar>) -> [u8; 32];
fn selene_scalar_to_bytes(selene_scalar: &Box<SeleneScalar>) -> [u8; 32];
fn helios_point_to_bytes(helios_point: &Box<HeliosPoint>) -> [u8; 32];
fn selene_point_to_bytes(selene_point: &Box<SelenePoint>) -> [u8; 32];
fn ed25519_point_to_selene_scalar(ed25519_point: &[u8; 32]) -> Box<SeleneScalar>;
fn selene_point_to_helios_scalar(selene_point: &Box<SelenePoint>) -> Box<HeliosScalar>;
fn helios_point_to_selene_scalar(helios_point: &Box<HeliosPoint>) -> Box<SeleneScalar>;
fn helios_zero_scalar() -> Box<HeliosScalar>;
fn selene_zero_scalar() -> Box<SeleneScalar>;
pub fn hash_grow_helios(
helios_generators: &Box<HeliosGenerators>,
existing_hash: &Box<HeliosPoint>,
offset: usize,
prior_children: &[Box<HeliosScalar>],
new_children: &[Box<HeliosScalar>]
) -> Result<Box<HeliosPoint>>;
pub fn hash_grow_selene(
selene_generators: &Box<SeleneGenerators>,
existing_hash: &Box<SelenePoint>,
offset: usize,
prior_children: &[Box<SeleneScalar>],
new_children: &[Box<SeleneScalar>]
) -> Result<Box<SelenePoint>>;
}
}
// TODO: cleaner const usage of generators // TODO: cleaner const usage of generators
// TODO: try to get closer to underlying types // TODO: try to get closer to underlying types
// TODO: maybe don't do both tuple and Box? Just make these all boxes // TODO: maybe don't do both tuple and Box? Just make these all boxes
pub struct HeliosGenerators(Generators<RecommendedTranscript, Helios>); #[repr(C)]
pub struct HeliosPoint(<Helios as Ciphersuite>::G); pub struct HeliosGenerators {
pub struct HeliosScalar(<Helios as Ciphersuite>::F); generators: Box<Generators<RecommendedTranscript, Helios>>
}
#[repr(C)]
pub struct SeleneGenerators {
generators: Box<Generators<RecommendedTranscript, Selene>>
}
pub struct SeleneGenerators(Generators<RecommendedTranscript, Selene>); #[no_mangle]
pub struct SelenePoint(<Selene as Ciphersuite>::G); pub extern "C" fn random_helios_generators(n: usize) -> HeliosGenerators {
pub struct SeleneScalar(<Selene as Ciphersuite>::F);
#[allow(non_snake_case)]
pub fn random_helios_generators(n: usize) -> Box<HeliosGenerators> {
let helios_generators = generalized_bulletproofs::tests::generators::<Helios>(n); let helios_generators = generalized_bulletproofs::tests::generators::<Helios>(n);
Box::new(HeliosGenerators(helios_generators)) HeliosGenerators { generators: Box::new(helios_generators) }
} }
#[allow(non_snake_case)] #[no_mangle]
pub fn random_selene_generators(n: usize) -> Box<SeleneGenerators> { pub extern "C" fn random_selene_generators(n: usize) -> SeleneGenerators {
let selene_generators = generalized_bulletproofs::tests::generators::<Selene>(n); let selene_generators = generalized_bulletproofs::tests::generators::<Selene>(n);
Box::new(SeleneGenerators(selene_generators)) SeleneGenerators { generators: Box::new(selene_generators) }
} }
#[allow(non_snake_case)] #[no_mangle]
pub fn random_helios_hash_init_point() -> Box<HeliosPoint> { pub extern "C" fn random_helios_hash_init_point() -> HeliosPoint {
let helios_hash_init_point = <Helios as Ciphersuite>::G::random(&mut OsRng); HeliosPoint::random(&mut OsRng)
dbg!(&helios_hash_init_point);
Box::new(HeliosPoint(helios_hash_init_point))
} }
#[allow(non_snake_case)] #[no_mangle]
pub fn random_selene_hash_init_point() -> Box<SelenePoint> { pub extern "C" fn random_selene_hash_init_point() -> SelenePoint {
let selene_hash_init_point = <Selene as Ciphersuite>::G::random(&mut OsRng); SelenePoint::random(&mut OsRng)
dbg!(&selene_hash_init_point);
Box::new(SelenePoint(selene_hash_init_point))
} }
// TODO: should be able to use generics fn c_u8_32(bytes: [u8; 32]) -> *const u8 {
// TODO: shorter names let arr_ptr = Box::into_raw(Box::new(bytes));
pub fn clone_helios_scalar(helios_scalar: &Box<HeliosScalar>) -> Box<HeliosScalar> { arr_ptr as *const u8
Box::new(HeliosScalar(helios_scalar.0))
} }
pub fn clone_selene_scalar(selene_scalar: &Box<SeleneScalar>) -> Box<SeleneScalar> { #[no_mangle]
Box::new(SeleneScalar(selene_scalar.0)) pub extern "C" fn helios_scalar_to_bytes(helios_scalar: HeliosScalar) -> *const u8 {
c_u8_32(helios_scalar.to_repr())
} }
pub fn clone_helios_point(helios_point: &Box<HeliosPoint>) -> Box<HeliosPoint> { #[no_mangle]
Box::new(HeliosPoint(helios_point.0)) pub extern "C" fn selene_scalar_to_bytes(selene_scalar: SeleneScalar) -> *const u8 {
c_u8_32(selene_scalar.to_repr())
} }
pub fn clone_selene_point(selene_point: &Box<SelenePoint>) -> Box<SelenePoint> { #[no_mangle]
Box::new(SelenePoint(selene_point.0)) pub extern "C" fn helios_point_to_bytes(helios_point: HeliosPoint) -> *const u8 {
c_u8_32(helios_point.to_bytes())
} }
// TODO: generics #[no_mangle]
pub fn helios_scalar_to_bytes(helios_scalar: &Box<HeliosScalar>) -> [u8; 32] { pub extern "C" fn selene_point_to_bytes(selene_point: SelenePoint) -> *const u8 {
helios_scalar.0.to_repr() c_u8_32(selene_point.to_bytes())
}
pub fn selene_scalar_to_bytes(selene_scalar: &Box<SeleneScalar>) -> [u8; 32] {
selene_scalar.0.to_repr()
}
pub fn helios_point_to_bytes(helios_point: &Box<HeliosPoint>) -> [u8; 32] {
helios_point.0.to_bytes()
}
pub fn selene_point_to_bytes(selene_point: &Box<SelenePoint>) -> [u8; 32] {
selene_point.0.to_bytes()
} }
// Get the x coordinate of the ed25519 point // Get the x coordinate of the ed25519 point
// TODO: use generics for below logic // TODO: use generics for below logic
pub fn ed25519_point_to_selene_scalar(ed25519_point: &[u8; 32]) -> Box<SeleneScalar> { #[no_mangle]
pub extern "C" fn ed25519_point_to_selene_scalar(ed25519_point: *const u8) -> SeleneScalar {
// TODO: unwrap or else error // TODO: unwrap or else error
let ed25519_point = <Ed25519>::read_G(&mut ed25519_point.as_slice()).unwrap(); let mut ed25519_point = unsafe { core::slice::from_raw_parts(ed25519_point, 32) };
let ed25519_point = <Ed25519>::read_G(&mut ed25519_point).unwrap();
let xy_coords = <Ed25519 as Ciphersuite>::G::to_xy(ed25519_point); let xy_coords = <Ed25519 as Ciphersuite>::G::to_xy(ed25519_point);
let x: <Selene as Ciphersuite>::F = xy_coords.0; let x: SeleneScalar = xy_coords.0;
Box::new(SeleneScalar(x)) x
} }
// TODO: use generics for below logic // TODO: use generics for below logic
pub fn selene_point_to_helios_scalar(selene_point: &Box<SelenePoint>) -> Box<HeliosScalar> { #[no_mangle]
let xy_coords = <Selene as Ciphersuite>::G::to_xy(selene_point.0); pub extern "C" fn selene_point_to_helios_scalar(selene_point: SelenePoint) -> HeliosScalar {
let x: <Helios as Ciphersuite>::F = xy_coords.0; let xy_coords = SelenePoint::to_xy(selene_point);
Box::new(HeliosScalar(x)) let x: HeliosScalar = xy_coords.0;
x
} }
// TODO: use generics for below logic // TODO: use generics for below logic
pub fn helios_point_to_selene_scalar(helios_point: &Box<HeliosPoint>) -> Box<SeleneScalar> { #[no_mangle]
let xy_coords = <Helios as Ciphersuite>::G::to_xy(helios_point.0); pub extern "C" fn helios_point_to_selene_scalar(helios_point: HeliosPoint) -> SeleneScalar {
let x: <Selene as Ciphersuite>::F = xy_coords.0; let xy_coords = HeliosPoint::to_xy(helios_point);
Box::new(SeleneScalar(x)) let x: SeleneScalar = xy_coords.0;
x
} }
pub fn helios_zero_scalar() -> Box<HeliosScalar> { #[no_mangle]
Box::new(HeliosScalar(<Helios as Ciphersuite>::F::ZERO)) pub extern "C" fn helios_zero_scalar() -> HeliosScalar {
HeliosScalar::ZERO
} }
pub fn selene_zero_scalar() -> Box<SeleneScalar> { #[no_mangle]
Box::new(SeleneScalar(<Selene as Ciphersuite>::F::ZERO)) pub extern "C" fn selene_zero_scalar() -> SeleneScalar {
SeleneScalar::ZERO
} }
// TODO: use generics for curves #[repr(C)]
pub fn hash_grow_helios( pub struct Slice<T> {
helios_generators: &Box<HeliosGenerators>, buf: *const T,
existing_hash: &Box<HeliosPoint>, len: usize,
offset: usize, }
prior_children: &[Box<HeliosScalar>], pub type HeliosScalarSlice = Slice<HeliosScalar>;
new_children: &[Box<HeliosScalar>] pub type SeleneScalarSlice = Slice<SeleneScalar>;
) -> Result<Box<HeliosPoint>, io::Error> { impl<'a, T> Into<&'a [T]> for Slice<T> {
let prior_children = prior_children.iter().map(|c| c.0).collect::<Vec<_>>(); fn into(self) -> &'a [T] {
let new_children = new_children.iter().map(|c| c.0).collect::<Vec<_>>(); unsafe { core::slice::from_raw_parts(self.buf, self.len) }
}
}
let hash = hash_grow( #[repr(C)]
&helios_generators.0, pub struct CResult<T, E> {
existing_hash.0, value: T,
offset, err: *const E,
&prior_children, }
&new_children impl<T, E> CResult<T, E> {
); fn ok(value: T) -> Self {
CResult { value, err: core::ptr::null() }
if let Some(hash) = hash { }
Ok(Box::new(HeliosPoint(hash))) fn err(default: T, err: E) -> Self {
} else { CResult { value: default, err: Box::into_raw(Box::new(err)) }
Err(io::Error::new(io::ErrorKind::Other, "failed to grow hash"))
} }
} }
// TODO: use generics for curves // TODO: use generics for curves
pub fn hash_grow_selene( #[no_mangle]
selene_generators: &Box<SeleneGenerators>, pub extern "C" fn hash_grow_helios(
existing_hash: &Box<SelenePoint>, helios_generators: &HeliosGenerators,
existing_hash: HeliosPoint,
offset: usize, offset: usize,
prior_children: &[Box<SeleneScalar>], prior_children: HeliosScalarSlice,
new_children: &[Box<SeleneScalar>] new_children: HeliosScalarSlice
) -> Result<Box<SelenePoint>, io::Error> { ) -> CResult<HeliosPoint, io::Error> {
let prior_children = prior_children.iter().map(|c| c.0).collect::<Vec<_>>();
let new_children = new_children.iter().map(|c| c.0).collect::<Vec<_>>();
let hash = hash_grow( let hash = hash_grow(
&selene_generators.0, &helios_generators.generators,
existing_hash.0, existing_hash,
offset, offset,
&prior_children, prior_children.into(),
&new_children new_children.into(),
); );
if let Some(hash) = hash { if let Some(hash) = hash {
Ok(Box::new(SelenePoint(hash))) CResult::ok(hash)
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "failed to grow hash")) CResult::err(HeliosPoint::identity(), io::Error::new(io::ErrorKind::Other, "failed to grow hash"))
} }
} }
// TODO: use generics for curves
#[no_mangle]
pub extern "C" fn hash_grow_selene(
selene_generators: &SeleneGenerators,
existing_hash: SelenePoint,
offset: usize,
prior_children: SeleneScalarSlice,
new_children: SeleneScalarSlice
) -> CResult<SelenePoint, io::Error> {
let hash = hash_grow(
&selene_generators.generators,
existing_hash,
offset,
prior_children.into(),
new_children.into(),
);
if let Some(hash) = hash {
CResult::ok(hash)
} else {
CResult::err(SelenePoint::identity(), io::Error::new(io::ErrorKind::Other, "failed to grow hash"))
}
}

View File

@ -1,21 +1,21 @@
// Copyright (c) 2024, The Monero Project // Copyright (c) 2024, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 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 // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // 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 // 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 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -51,12 +51,16 @@ Helios::Point Helios::hash_grow(
const Helios::Chunk &prior_children, const Helios::Chunk &prior_children,
const Helios::Chunk &new_children) const const Helios::Chunk &new_children) const
{ {
return fcmp_rust::hash_grow_helios( auto res = fcmp_rust::hash_grow_helios(
m_generators, &m_generators,
existing_hash, existing_hash,
offset, offset,
prior_children, prior_children,
new_children); new_children);
if (res.err != 0) {
throw std::runtime_error("failed to hash grow");
}
return res.value;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
Selene::Point Selene::hash_grow( Selene::Point Selene::hash_grow(
@ -65,32 +69,16 @@ Selene::Point Selene::hash_grow(
const Selene::Chunk &prior_children, const Selene::Chunk &prior_children,
const Selene::Chunk &new_children) const const Selene::Chunk &new_children) const
{ {
return fcmp_rust::hash_grow_selene( auto res = fcmp_rust::hash_grow_selene(
m_generators, &m_generators,
existing_hash, existing_hash,
offset, offset,
prior_children, prior_children,
new_children); new_children);
} if (res.err != 0) {
//---------------------------------------------------------------------------------------------------------------------- throw std::runtime_error("failed to hash grow");
Helios::Scalar Helios::clone(const Helios::Scalar &scalar) const }
{ return res.value;
return fcmp_rust::clone_helios_scalar(scalar);
}
//----------------------------------------------------------------------------------------------------------------------
Selene::Scalar Selene::clone(const Selene::Scalar &scalar) const
{
return fcmp_rust::clone_selene_scalar(scalar);
}
//----------------------------------------------------------------------------------------------------------------------
Helios::Point Helios::clone(const Helios::Point &point) const
{
return fcmp_rust::clone_helios_point(point);
}
//----------------------------------------------------------------------------------------------------------------------
Selene::Point Selene::clone(const Selene::Point &point) const
{
return fcmp_rust::clone_selene_point(point);
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
Helios::Scalar Helios::zero_scalar() const Helios::Scalar Helios::zero_scalar() const
@ -105,22 +93,38 @@ Selene::Scalar Selene::zero_scalar() const
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::array<uint8_t, 32UL> Helios::to_bytes(const Helios::Scalar &scalar) const std::array<uint8_t, 32UL> Helios::to_bytes(const Helios::Scalar &scalar) const
{ {
return fcmp_rust::helios_scalar_to_bytes(scalar); auto bytes = fcmp_rust::helios_scalar_to_bytes(scalar);
std::array<uint8_t, 32UL> res;
memcpy(&res, bytes, 32);
free(bytes);
return res;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::array<uint8_t, 32UL> Selene::to_bytes(const Selene::Scalar &scalar) const std::array<uint8_t, 32UL> Selene::to_bytes(const Selene::Scalar &scalar) const
{ {
return fcmp_rust::selene_scalar_to_bytes(scalar); auto bytes = fcmp_rust::selene_scalar_to_bytes(scalar);
std::array<uint8_t, 32UL> res;
memcpy(&res, bytes, 32);
free(bytes);
return res;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::array<uint8_t, 32UL> Helios::to_bytes(const Helios::Point &point) const std::array<uint8_t, 32UL> Helios::to_bytes(const Helios::Point &point) const
{ {
return fcmp_rust::helios_point_to_bytes(point); auto bytes = fcmp_rust::helios_point_to_bytes(point);
std::array<uint8_t, 32UL> res;
memcpy(&res, bytes, 32);
free(bytes);
return res;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::array<uint8_t, 32UL> Selene::to_bytes(const Selene::Point &point) const std::array<uint8_t, 32UL> Selene::to_bytes(const Selene::Point &point) const
{ {
return fcmp_rust::selene_point_to_bytes(point); auto bytes = fcmp_rust::selene_point_to_bytes(point);
std::array<uint8_t, 32UL> res;
memcpy(&res, bytes, 32);
free(bytes);
return res;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::string Helios::to_string(const typename Helios::Scalar &scalar) const std::string Helios::to_string(const typename Helios::Scalar &scalar) const
@ -148,13 +152,7 @@ std::string Selene::to_string(const typename Selene::Point &point) const
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point) SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point)
{ {
static_assert(sizeof(RustEd25519Point) == sizeof(crypto::ec_point), return fcmp_rust::ed25519_point_to_selene_scalar((uint8_t*) &point.data);
"expected same size ed25519 point to rust representation");
// TODO: implement reading just the x coordinate of ed25519 point in C/C++
fcmp::tower_cycle::RustEd25519Point rust_point;
memcpy(&rust_point, &point, sizeof(fcmp::tower_cycle::RustEd25519Point));
return fcmp_rust::ed25519_point_to_selene_scalar(rust_point);
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
template<typename C> template<typename C>

View File

@ -1,21 +1,21 @@
// Copyright (c) 2024, The Monero Project // Copyright (c) 2024, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 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 // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // 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 // 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 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -29,8 +29,7 @@
#pragma once #pragma once
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "fcmp_rust/cxx.h" #include "fcmp_rust/fcmp++.h"
#include "fcmp_rust/fcmp_rust.h"
#include <string> #include <string>
@ -45,24 +44,24 @@ namespace tower_cycle
using RustEd25519Point = std::array<uint8_t, 32UL>; using RustEd25519Point = std::array<uint8_t, 32UL>;
// Need to forward declare Scalar types for point_to_cycle_scalar below // Need to forward declare Scalar types for point_to_cycle_scalar below
using SeleneScalar = rust::Box<fcmp_rust::SeleneScalar>; using SeleneScalar = fcmp_rust::SeleneScalar;
using HeliosScalar = rust::Box<fcmp_rust::HeliosScalar>; using HeliosScalar = fcmp_rust::HeliosScalar;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
struct HeliosT final struct HeliosT final
{ {
using Generators = rust::Box<fcmp_rust::HeliosGenerators>; using Generators = fcmp_rust::HeliosGenerators;
using Scalar = HeliosScalar; using Scalar = HeliosScalar;
using Point = rust::Box<fcmp_rust::HeliosPoint>; using Point = fcmp_rust::HeliosPoint;
using Chunk = rust::Slice<const Scalar>; using Chunk = fcmp_rust::HeliosScalarSlice;
using CycleScalar = SeleneScalar; using CycleScalar = SeleneScalar;
}; };
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
struct SeleneT final struct SeleneT final
{ {
using Generators = rust::Box<fcmp_rust::SeleneGenerators>; using Generators = fcmp_rust::SeleneGenerators;
using Scalar = SeleneScalar; using Scalar = SeleneScalar;
using Point = rust::Box<fcmp_rust::SelenePoint>; using Point = fcmp_rust::SelenePoint;
using Chunk = rust::Slice<const Scalar>; using Chunk = fcmp_rust::SeleneScalarSlice;
using CycleScalar = HeliosScalar; using CycleScalar = HeliosScalar;
}; };
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -89,9 +88,6 @@ public:
const typename C::Chunk &prior_children, const typename C::Chunk &prior_children,
const typename C::Chunk &new_children) const = 0; const typename C::Chunk &new_children) const = 0;
virtual typename C::Scalar clone(const typename C::Scalar &scalar) const = 0;
virtual typename C::Point clone(const typename C::Point &point) const = 0;
virtual typename C::Scalar zero_scalar() const = 0; virtual typename C::Scalar zero_scalar() const = 0;
virtual std::array<uint8_t, 32UL> to_bytes(const typename C::Scalar &scalar) const = 0; virtual std::array<uint8_t, 32UL> to_bytes(const typename C::Scalar &scalar) const = 0;
@ -133,9 +129,6 @@ public:
const Chunk &prior_children, const Chunk &prior_children,
const Chunk &new_children) const override; const Chunk &new_children) const override;
Scalar clone(const Scalar &scalar) const override;
Point clone(const Point &point) const override;
Scalar zero_scalar() const override; Scalar zero_scalar() const override;
std::array<uint8_t, 32UL> to_bytes(const Scalar &scalar) const override; std::array<uint8_t, 32UL> to_bytes(const Scalar &scalar) const override;
@ -171,9 +164,6 @@ public:
const Chunk &prior_children, const Chunk &prior_children,
const Chunk &new_children) const override; const Chunk &new_children) const override;
Scalar clone(const Scalar &scalar) const override;
Point clone(const Point &point) const override;
Scalar zero_scalar() const override; Scalar zero_scalar() const override;
std::array<uint8_t, 32UL> to_bytes(const Scalar &scalar) const override; std::array<uint8_t, 32UL> to_bytes(const Scalar &scalar) const override;

View File

@ -1,21 +1,21 @@
// Copyright (c) 2014, The Monero Project // Copyright (c) 2014, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be // 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 // used to endorse or promote products derived from this software without specific
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // 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 // 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 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@ -49,8 +49,8 @@ static fcmp::curve_trees::LastChunkData<C> get_last_child_layer_chunk(const C &c
return fcmp::curve_trees::LastChunkData<C>{ return fcmp::curve_trees::LastChunkData<C>{
.child_offset = child_offset, .child_offset = child_offset,
.last_child = curve.clone(last_child), .last_child = last_child,
.last_parent = curve.clone(last_parent), .last_parent = last_parent,
.child_layer_size = child_layer_size, .child_layer_size = child_layer_size,
.parent_layer_size = parent_layer_size .parent_layer_size = parent_layer_size
}; };
@ -204,9 +204,9 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
for (const auto &leaf : tree_extension.leaves.tuples) for (const auto &leaf : tree_extension.leaves.tuples)
{ {
tree_inout.leaves.emplace_back(CurveTreesV1::LeafTuple{ tree_inout.leaves.emplace_back(CurveTreesV1::LeafTuple{
.O_x = m_curve_trees.m_c2.clone(leaf.O_x), .O_x = leaf.O_x,
.I_x = m_curve_trees.m_c2.clone(leaf.I_x), .I_x = leaf.I_x,
.C_x = m_curve_trees.m_c2.clone(leaf.C_x) .C_x = leaf.C_x
}); });
} }
@ -240,10 +240,10 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
// We updated the last hash // We updated the last hash
if (started_at_tip) if (started_at_tip)
c2_inout.back() = m_curve_trees.m_c2.clone(c2_ext.hashes.front()); c2_inout.back() = c2_ext.hashes.front();
for (std::size_t i = started_at_tip ? 1 : 0; i < c2_ext.hashes.size(); ++i) for (std::size_t i = started_at_tip ? 1 : 0; i < c2_ext.hashes.size(); ++i)
c2_inout.emplace_back(m_curve_trees.m_c2.clone(c2_ext.hashes[i])); c2_inout.emplace_back(c2_ext.hashes[i]);
++c2_idx; ++c2_idx;
} }
@ -266,10 +266,10 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
// We updated the last hash // We updated the last hash
if (started_at_tip) if (started_at_tip)
c1_inout.back() = m_curve_trees.m_c1.clone(c1_ext.hashes.front()); c1_inout.back() = c1_ext.hashes.front();
for (std::size_t i = started_at_tip ? 1 : 0; i < c1_ext.hashes.size(); ++i) for (std::size_t i = started_at_tip ? 1 : 0; i < c1_ext.hashes.size(); ++i)
c1_inout.emplace_back(m_curve_trees.m_c1.clone(c1_ext.hashes[i])); c1_inout.emplace_back(c1_ext.hashes[i]);
++c1_idx; ++c1_idx;
} }