airbender_crypto/secp256k1/
context.rs1#[cfg(feature = "alloc")]
2use alloc::boxed::Box;
3#[cfg(feature = "alloc")]
4use core::alloc::{AllocError, Allocator, Layout};
5
6use super::points::{AffineStorage, JacobianConst};
7
8pub(crate) const WINDOW_A: usize = 5;
9
10pub(crate) const WINDOW_G: usize = 10;
11
12pub(crate) const ECMULT_TABLE_SIZE_A: usize = 1 << (WINDOW_A - 2);
13pub(crate) const ECMULT_TABLE_SIZE_G: usize = 1 << (WINDOW_G - 2);
14pub(crate) const WNAF_BITS: usize = 129;
15
16pub struct ECMultContext {
17 pub(crate) pre_g: [AffineStorage; ECMULT_TABLE_SIZE_G],
18 pub(crate) pre_g_128: [AffineStorage; ECMULT_TABLE_SIZE_G],
19}
20
21#[cfg(feature = "secp256k1-static-context")]
22pub(crate) const ECRECOVER_CONTEXT: ECMultContext = ECMultContext::const_new();
23
24impl ECMultContext {
25 pub const fn const_new() -> Self {
29 let mut context = Self {
30 pre_g: [AffineStorage::DEFAULT; ECMULT_TABLE_SIZE_G],
31 pre_g_128: [AffineStorage::DEFAULT; ECMULT_TABLE_SIZE_G],
32 };
33
34 context.initialize();
35
36 context
37 }
38
39 const fn compute_table(table: &mut [AffineStorage; ECMULT_TABLE_SIZE_G], gen: &JacobianConst) {
40 use const_for::const_for;
41
42 let mut gj = *gen;
43 table[0] = gj.to_affine_storage_const();
45
46 let g_doubled = gen.double(None);
47 let g_doubled = g_doubled.to_affine_const();
49
50 const_for!(i in 1..ECMULT_TABLE_SIZE_G => {
51 gj = gj.add_ge(&g_doubled, None);
53 table[i] = gj.to_affine_storage_const();
55 });
56 }
57
58 const fn initialize(&mut self) {
59 let mut gj = JacobianConst::GENERATOR;
60
61 Self::compute_table(&mut self.pre_g, &gj);
62
63 use const_for::const_for;
64 const_for!(_ in 0..128 => {
65 gj = gj.double(None);
66 });
67
68 Self::compute_table(&mut self.pre_g_128, &gj);
69 }
70
71 #[cfg(feature = "alloc")]
72 pub fn new_in<A: Allocator>(allocator: A) -> Result<Box<Self, A>, AllocError> {
73 let mut context = unsafe {
74 let layout = Layout::new::<ECMultContext>();
75 let ptr = allocator.allocate(layout)?.cast::<ECMultContext>().as_ptr();
76 let mut this = Box::from_raw_in(ptr, allocator);
77
78 for i in 0..ECMULT_TABLE_SIZE_G {
79 this.pre_g[i] = AffineStorage::DEFAULT;
80 this.pre_g_128[i] = AffineStorage::DEFAULT;
81 }
82
83 this
84 };
85
86 context.initialize();
87
88 Ok(context)
89 }
90
91 pub fn new_from_raw_unchecked(
92 pre_g: [AffineStorage; ECMULT_TABLE_SIZE_G],
93 pre_g_128: [AffineStorage; ECMULT_TABLE_SIZE_G],
94 ) -> Self {
95 Self { pre_g, pre_g_128 }
96 }
97}