diff --git a/Cargo.lock b/Cargo.lock index 45d4359cc..2d6b3d84d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,21 +232,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", ] [[package]] name = "ark-bn254" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" dependencies = [ - "ark-ec", - "ark-ff", - "ark-std", + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-r1cs-std", + "ark-std 0.5.0", ] [[package]] @@ -255,10 +256,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" dependencies = [ - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", "itertools 0.10.5", @@ -266,6 +267,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash 0.8.11", + "ark-ff 0.5.0", + "ark-poly 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.2", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + [[package]] name = "ark-ed-on-bls12-381-bandersnatch" version = "0.4.0" @@ -273,9 +295,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9cde0f2aa063a2a5c28d39b47761aa102bda7c13c84fc118a61b87c7b2f785c" dependencies = [ "ark-bls12-381", - "ark-ec", - "ark-ff", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-std 0.4.0", ] [[package]] @@ -284,10 +306,10 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "ark-ff-asm", - "ark-ff-macros", - "ark-serialize", - "ark-std", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "digest 0.10.7", "itertools 0.10.5", @@ -298,6 +320,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec 0.7.4", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + [[package]] name = "ark-ff-asm" version = "0.4.2" @@ -308,6 +350,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.79", +] + [[package]] name = "ark-ff-macros" version = "0.4.2" @@ -321,29 +373,86 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "ark-poly" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", ] +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash 0.8.11", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.2", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec 0.5.0", + "ark-ff 0.5.0", + "ark-relations", + "ark-std 0.5.0", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff 0.5.0", + "ark-std 0.5.0", + "tracing", + "tracing-subscriber", +] + [[package]] name = "ark-scale" version = "0.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b08346a3e38e2be792ef53ee168623c9244d968ff00cd70fb9932f6fe36393" dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "parity-scale-codec", ] @@ -353,10 +462,10 @@ version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "parity-scale-codec", "scale-info", ] @@ -366,10 +475,10 @@ name = "ark-secret-scalar" version = "0.0.2" source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" dependencies = [ - "ark-ec", - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "ark-transcript", "digest 0.10.7", "rand_core 0.6.4", @@ -382,8 +491,21 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "ark-serialize-derive", - "ark-std", + "ark-serialize-derive 0.4.2", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive 0.5.0", + "ark-std 0.5.0", + "arrayvec 0.7.4", "digest 0.10.7", "num-bigint", ] @@ -399,6 +521,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "ark-std" version = "0.4.0" @@ -409,14 +542,24 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "ark-transcript" version = "0.0.2" source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" dependencies = [ - "ark-ff", - "ark-serialize", - "ark-std", + "ark-ff 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "digest 0.10.7", "rand_core 0.6.4", "sha3", @@ -751,12 +894,12 @@ version = "0.0.1" source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" dependencies = [ "ark-bls12-381", - "ark-ec", + "ark-ec 0.4.2", "ark-ed-on-bls12-381-bandersnatch", - "ark-ff", + "ark-ff 0.4.2", "ark-scale 0.0.12", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "dleq_vrf", "fflonk", "merlin 3.0.0", @@ -1441,11 +1584,11 @@ name = "common" version = "0.1.0" source = "git+https://github.com/w3f/ring-proof?rev=0e948f3#0e948f3c28cbacecdd3020403c4841c0eb339213" dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "fflonk", "merlin 3.0.0", ] @@ -2599,12 +2742,12 @@ name = "dleq_vrf" version = "0.0.2" source = "git+https://github.com/w3f/ring-vrf?rev=3119f51#3119f51b54b69308abfb0671f6176cb125ae1bf1" dependencies = [ - "ark-ec", - "ark-ff", + "ark-ec 0.4.2", + "ark-ff 0.4.2", "ark-scale 0.0.10", "ark-secret-scalar", - "ark-serialize", - "ark-std", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "ark-transcript", "arrayvec 0.7.4", "rand_core 0.6.4", @@ -2751,6 +2894,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "either" version = "1.11.0" @@ -2794,6 +2949,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "enumflags2" version = "0.7.9" @@ -3055,11 +3230,11 @@ name = "fflonk" version = "0.1.0" source = "git+https://github.com/w3f/fflonk#1e854f35e9a65d08b11a86291405cdc95baa0a35" dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "merlin 3.0.0", ] @@ -3862,6 +4037,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", +] + [[package]] name = "heck" version = "0.4.1" @@ -4083,7 +4267,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core", ] [[package]] @@ -4339,6 +4523,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -4623,7 +4816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -9644,11 +9837,11 @@ name = "ring" version = "0.1.0" source = "git+https://github.com/w3f/ring-proof?rev=0e948f3#0e948f3c28cbacecdd3020403c4841c0eb339213" dependencies = [ - "ark-ec", - "ark-ff", - "ark-poly", - "ark-serialize", - "ark-std", + "ark-ec 0.4.2", + "ark-ff 0.4.2", + "ark-poly 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", "common", "fflonk", "merlin 3.0.0", @@ -13753,7 +13946,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.8.5", + "rand 0.7.3", "static_assertions", ] @@ -14532,7 +14725,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core 0.51.1", + "windows-core", "windows-targets 0.48.5", ] @@ -14545,15 +14738,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.5", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -15194,7 +15378,7 @@ name = "zrml-combinatorial-tokens" version = "0.5.5" dependencies = [ "ark-bn254", - "ark-ff", + "ark-ff 0.5.0", "env_logger 0.10.2", "frame-benchmarking", "frame-support", diff --git a/Cargo.toml b/Cargo.toml index 13d473b46..e7b24ef66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -276,8 +276,8 @@ url = "2.5.0" # Other (wasm) arbitrary = { version = "1.3.2", default-features = false } -ark-bn254 = { version = "0.4.0", default-features = false, features = ["curve"] } -ark-ff = { version = "0.4.0", default-features = false } +ark-bn254 = { version = "0.5.0", default-features = false, features = ["curve"] } +ark-ff = { version = "0.5.0", default-features = false } arrayvec = { version = "0.7.4", default-features = false } cfg-if = { version = "1.0.0" } fixed = { version = "=1.15.0", default-features = false, features = ["num-traits"] } diff --git a/zrml/combinatorial-tokens/src/lib.rs b/zrml/combinatorial-tokens/src/lib.rs index 7e9a7ae8d..148af3f06 100644 --- a/zrml/combinatorial-tokens/src/lib.rs +++ b/zrml/combinatorial-tokens/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -39,7 +39,9 @@ pub use pallet::*; #[frame_support::pallet] mod pallet { use crate::{ - traits::CombinatorialIdManager, types::TransmutationType, weights::WeightInfoZeitgeist, + traits::CombinatorialIdManager, + types::{CollectionIdError, TransmutationType}, + weights::WeightInfoZeitgeist, }; use alloc::{vec, vec::Vec}; use core::{fmt::Debug, marker::PhantomData}; @@ -186,6 +188,9 @@ mod pallet { #[pallet::error] pub enum Error { + /// An error for the collection ID retrieval occured. + CollectionIdRetrievalFailed(CollectionIdError), + /// Specified index set is trival, empty, or doesn't match the market's number of outcomes. InvalidIndexSet, @@ -193,9 +198,6 @@ mod pallet { /// market's number of outcomes. InvalidPartition, - /// Specified collection ID is invalid. - InvalidCollectionId, - /// Specified market is not resolved. PayoutVectorNotFound, @@ -643,7 +645,9 @@ mod pallet { index_set, fuel, ) - .ok_or(Error::::InvalidCollectionId.into()) + .map_err(|collection_id_error| { + Error::::CollectionIdRetrievalFailed(collection_id_error).into() + }) } pub(crate) fn position_from_collection_id( diff --git a/zrml/combinatorial-tokens/src/traits/combinatorial_id_manager.rs b/zrml/combinatorial-tokens/src/traits/combinatorial_id_manager.rs index abf23ffff..47cb9389a 100644 --- a/zrml/combinatorial-tokens/src/traits/combinatorial_id_manager.rs +++ b/zrml/combinatorial-tokens/src/traits/combinatorial_id_manager.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -22,6 +22,7 @@ // , // and has been relicensed under GPL-3.0-or-later in this repository. +use crate::types::CollectionIdError; use alloc::vec::Vec; pub trait CombinatorialIdManager { @@ -40,7 +41,7 @@ pub trait CombinatorialIdManager { market_id: Self::MarketId, index_set: Vec, fuel: Self::Fuel, - ) -> Option; + ) -> Result; fn get_position_id( collateral: Self::Asset, diff --git a/zrml/combinatorial-tokens/src/types/collection_id_error.rs b/zrml/combinatorial-tokens/src/types/collection_id_error.rs new file mode 100644 index 000000000..2de7ce936 --- /dev/null +++ b/zrml/combinatorial-tokens/src/types/collection_id_error.rs @@ -0,0 +1,35 @@ +// Copyright 2025 Forecasting Technologies LTD. +// +// This file is part of Zeitgeist. +// +// Zeitgeist is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// Zeitgeist is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Zeitgeist. If not, see . +// +// This file incorporates work licensed under the GNU Lesser General +// Public License 3.0 but published without copyright notice by Gnosis +// (, info@gnosis.io) in the +// conditional-tokens-contracts repository +// , +// and has been relicensed under GPL-3.0-or-later in this repository. + +use frame_support::PalletError; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; + +#[derive(Decode, Encode, Eq, PartialEq, PalletError, RuntimeDebug, TypeInfo)] +pub enum CollectionIdError { + InvalidParentCollectionId, + EllipticCurvePointNotFoundWithFuel, + EllipticCurvePointXToBytesConversionFailed, +} diff --git a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/mod.rs b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/mod.rs index 236e2b821..b1947d3b0 100644 --- a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/mod.rs +++ b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -26,19 +26,23 @@ mod tests; -use crate::types::cryptographic_id_manager::Fuel; +use crate::types::{cryptographic_id_manager::Fuel, CollectionIdError}; use ark_bn254::{g1::G1Affine, Fq}; use ark_ff::{BigInteger, PrimeField}; use core::ops::Neg; use sp_runtime::traits::{One, Zero}; use zeitgeist_primitives::{traits::CombinatorialTokensFuel, types::CombinatorialId}; -/// Will return `None` if and only if `parent_collection_id` is not a valid collection ID. +/// Returns a valid collection ID from an `hash` and an optional `parent_collection_id`. +/// +/// Will return `None` if `parent_collection_id` is not a valid collection ID or +/// the decompression of the hash doesn't return a valid point of `alt_bn128` +/// (maybe insufficient `fuel` parameter) or because of a failing bytes conversion. pub(crate) fn get_collection_id( hash: CombinatorialId, parent_collection_id: Option, fuel: Fuel, -) -> Option { +) -> Result { let mut u = decompress_hash(hash, fuel)?; if let Some(pci) = parent_collection_id { @@ -49,13 +53,19 @@ pub(crate) fn get_collection_id( // Convert back to bytes _before_ flipping, as flipping will sometimes result in numbers larger // than the base field modulus. - let mut bytes: CombinatorialId = u.x.into_bigint().to_bytes_be().try_into().ok()?; + let bytes_y_even: CombinatorialId = + u.x.into_bigint() + .to_bytes_be() + .try_into() + .map_err(|_| CollectionIdError::EllipticCurvePointXToBytesConversionFailed)?; - if u.y.into_bigint().is_odd() { - flip_second_highest_bit(&mut bytes); - } + let bytes = if u.y.into_bigint().is_odd() { + flip_second_highest_bit(&bytes_y_even) + } else { + bytes_y_even + }; - Some(bytes) + Ok(bytes) } /// Decompresses a collection ID `hash` to a point of `alt_bn128`. The amount of work done can be @@ -66,7 +76,7 @@ pub(crate) fn get_collection_id( /// evidence that input hash requires more than `log_2(P) = 507.19338271000436` iterations. With a /// `fuel.total` value of `32`, statistical evidence suggests a 1 in 500_000_000 chance that the /// number of iterations will not be enough. -fn decompress_hash(hash: CombinatorialId, fuel: Fuel) -> Option { +fn decompress_hash(hash: CombinatorialId, fuel: Fuel) -> Result { // Calculate `odd` first, then get congruent point `x` in `Fq`. As `hash` might represent a // larger big endian number than `field_modulus()`, the MSB of `x` might be different from the // MSB of `x_u256`. @@ -103,9 +113,11 @@ fn decompress_hash(hash: CombinatorialId, fuel: Fuel) -> Option { } } } - core::hint::black_box(dummy_x); // Ensure that the dummies are considered "read" by rustc. + // Ensure that the dummies are considered "read" by rustc. + core::hint::black_box(dummy_x); core::hint::black_box(dummy_y); - let mut y = y_opt?; // This **should** be infallible if `DECOMPRESS_HASH_MAX_ITERS` is large. + // This **should** be infallible if `fuel.total()` is large. + let mut y = y_opt.ok_or(CollectionIdError::EllipticCurvePointNotFoundWithFuel)?; // We have two options for the y-coordinate of the corresponding point: `y` and `P - y`. If // `odd` is set but `y` isn't odd, we switch to the other option. @@ -113,21 +125,22 @@ fn decompress_hash(hash: CombinatorialId, fuel: Fuel) -> Option { y = y.neg(); } - Some(G1Affine::new(x, y)) + Ok(G1Affine::new(x, y)) } -fn decompress_collection_id(mut collection_id: CombinatorialId) -> Option { +fn decompress_collection_id(collection_id: CombinatorialId) -> Result { let odd = is_second_msb_set(&collection_id); - chop_off_two_highest_bits(&mut collection_id); - let x = Fq::from_be_bytes_mod_order(&collection_id); + let chopped_collection_id = chop_off_two_highest_bits(&collection_id); + let x = Fq::from_be_bytes_mod_order(&chopped_collection_id); // Ensure that the big-endian integer represented by `collection_id` was less than the field // modulus. Otherwise, we consider `collection_id` an invalid ID. - if x.into_bigint().to_bytes_be() != collection_id { - return None; + if x.into_bigint().to_bytes_be() != chopped_collection_id { + return Err(CollectionIdError::InvalidParentCollectionId); } - let mut y = matching_y_coordinate(x)?; // Fails if `collection_id` is not a collection ID. + // Fails if `collection_id` is not a collection ID. + let mut y = matching_y_coordinate(x).ok_or(CollectionIdError::InvalidParentCollectionId)?; // We have two options for the y-coordinate of the corresponding point: `y` and `P - y`. If // `odd` is set but `y` isn't odd, we switch to the other option. @@ -135,12 +148,14 @@ fn decompress_collection_id(mut collection_id: CombinatorialId) -> Option CombinatorialId { + let mut bytes = *bytes; bytes[0] ^= 0b01000000; + bytes } /// Checks if the most significant bit of the big-endian `bytes` is set. @@ -154,8 +169,10 @@ fn is_second_msb_set(bytes: &CombinatorialId) -> bool { } /// Zeroes out the two most significant bits off the big-endian `bytes`. -fn chop_off_two_highest_bits(bytes: &mut CombinatorialId) { +fn chop_off_two_highest_bits(bytes: &CombinatorialId) -> CombinatorialId { + let mut bytes = *bytes; bytes[0] &= 0b00111111; + bytes } /// Returns a value `y` of `Fq` so that `(x, y)` is a point on `alt_bn128` or `None` if there is no diff --git a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs index 5764626b1..926ff1cfc 100644 --- a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs +++ b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/decompress_collection_id.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -574,5 +574,5 @@ fn decompress_collection_id_works(collection_id: CombinatorialId, expected: (&st )] fn decompress_collection_id_fails_on_invalid_collection_id(collection_id: CombinatorialId) { let actual = decompress_collection_id(collection_id); - assert_eq!(actual, None); + assert_eq!(actual, Err(CollectionIdError::InvalidParentCollectionId)); } diff --git a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs index fd47e4345..34a698a89 100644 --- a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs +++ b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/decompressor/tests/get_collection_id.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -86,6 +86,7 @@ fn get_collection_id_works( #[values(false, true)] consume_all: bool, #[case] expected: Option, ) { - let actual = get_collection_id(hash, parent_collection_id, Fuel { total: 16, consume_all }); + let actual = + get_collection_id(hash, parent_collection_id, Fuel { total: 16, consume_all }).ok(); assert_eq!(actual, expected); } diff --git a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/mod.rs b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/mod.rs index 54343f14e..f29975101 100644 --- a/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/mod.rs +++ b/zrml/combinatorial-tokens/src/types/cryptographic_id_manager/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -25,6 +25,7 @@ mod decompressor; mod hash_tuple; +use super::CollectionIdError; use crate::traits::CombinatorialIdManager; use alloc::vec::Vec; use core::marker::PhantomData; @@ -83,7 +84,7 @@ where market_id: Self::MarketId, index_set: Vec, fuel: Self::Fuel, - ) -> Option { + ) -> Result { let input = (market_id, index_set); let hash = Hasher::hash_tuple(input); diff --git a/zrml/combinatorial-tokens/src/types/mod.rs b/zrml/combinatorial-tokens/src/types/mod.rs index bb5cce9cf..f23b68450 100644 --- a/zrml/combinatorial-tokens/src/types/mod.rs +++ b/zrml/combinatorial-tokens/src/types/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2024 Forecasting Technologies LTD. +// Copyright 2025 Forecasting Technologies LTD. // // This file is part of Zeitgeist. // @@ -15,10 +15,12 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . +mod collection_id_error; pub(crate) mod cryptographic_id_manager; pub(crate) mod hash; mod transmutation_type; +pub use collection_id_error::CollectionIdError; pub use cryptographic_id_manager::{CryptographicIdManager, Fuel}; pub(crate) use hash::Hash256; pub use transmutation_type::TransmutationType;