Initial work on a tables lib

Incomplete lib intended to offer tables for all cryptographic libraries 
expecting them. Right now, it creates the tables at runtime. While that 
would still offer improvements, ideally large tables are built at 
compile time and simply entered into memory at runtime.

My best idea for that was a linked list in the binary itself, where this 
app (at first call), reads a table stored to a section of data, then 
grabs the next reference to one and continues reading. The main issue 
with this idea, besides not yet researching how to encode data into the 
binary, was the fact the same table would be saved to disk multiple 
times under this simplistic model. An O(n) iteration when writing to the 
bin could potentially solve that.

Related https://github.com/serai-dex/serai/issues/41.
This commit is contained in:
Luke Parker 2022-07-16 16:25:55 -04:00
parent 0b879a53fa
commit f029471f9f
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
4 changed files with 97 additions and 0 deletions

View file

@ -3,6 +3,7 @@ members = [
"crypto/transcript",
"crypto/dalek-ff-group",
"crypto/tables",
"crypto/multiexp",
"crypto/dleq",

16
crypto/tables/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "tables"
version = "0.1.0"
description = "Efficient multiplication tables for ff/group"
license = "MIT"
repository = "https://github.com/serai-dex/serai"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = ["ff", "group"]
edition = "2021"
[dependencies]
ff = "0.12"
group = "0.12"
[dev-dependencies]
k256 = { version = "0.11", features = ["bits"] }

21
crypto/tables/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Luke Parker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

59
crypto/tables/src/lib.rs Normal file
View file

@ -0,0 +1,59 @@
use std::{any::TypeId, mem, sync::Once, cell::Cell, boxed::Box, collections::HashMap};
use group::Group;
struct Tables(Cell<mem::MaybeUninit<HashMap<TypeId, *const ()>>>, Once);
static mut TABLES: Tables = Tables(Cell::new(mem::MaybeUninit::uninit()), Once::new());
pub struct Table<G>(Vec<G>);
fn acquire() -> &'static mut HashMap<TypeId, *const ()> {
unsafe {
TABLES.1.call_once(|| {
TABLES.0.set(mem::MaybeUninit::new(HashMap::new()));
});
&mut (*(*TABLES.0.as_ptr()).as_mut_ptr())
}
}
/// This should ONLY be called via the generate_table macro. It is solely public to make said
/// macro work
#[doc(hidden)]
pub fn __unsafe_add_table<G: Group>(table: Table<G>) {
let tables = acquire();
if tables.contains_key(&TypeId::of::<G>()) {
return;
}
let ptr = std::ptr::addr_of!(*Box::leak(Box::new(table)));
unsafe {
tables.insert(TypeId::of::<G>(), mem::transmute::<*const Table<G>, *const ()>(ptr));
}
}
macro_rules! generate_table {
($G: ident) => {
__unsafe_add_table(Table(vec![$G::generator()]));
};
}
/// Returns a table usable for fast multiplication. This will panic if the table was not registered
/// via the generate_table macro
pub fn generator_table<G: Group>() -> &'static Table<G> {
generate_table!(G);
unsafe {
acquire()
.get(&TypeId::of::<G>())
.map(|arc| &*mem::transmute::<*const (), *const Table<G>>(*arc))
.unwrap()
}
}
#[test]
fn test_static() {
use k256::ProjectivePoint;
let table: &'static Table<ProjectivePoint> = generator_table::<ProjectivePoint>();
dbg!("Read");
dbg!(table.0.len());
dbg!(&table.0);
}