1+ use super :: elements:: ElementType ;
12use crate :: {
23 bn254:: { fp254impl:: Fp254Impl , fq:: Fq } ,
34 hash:: blake3:: blake3_compute_script,
@@ -8,8 +9,6 @@ use hash_utils::{
89 hash_fp2, hash_fp6, hash_g2acc, hash_g2acc_with_hash_t, hash_g2acc_with_hashed_le,
910} ;
1011
11- use super :: elements:: ElementType ;
12-
1312pub const BLAKE3_HASH_LENGTH : usize = wots_api:: HASH_LEN as usize ;
1413
1514/// truncate 32 byte output hash to {BLAKE3_HASH_LENGTH} hash output and pad with zeros
@@ -31,6 +30,8 @@ pub(crate) fn hash_n_bytes<const N: usize>() -> Script {
3130// helpers to directly hash data structures that we work with
3231// example: extension field elements, point accumulators
3332pub ( crate ) mod hash_utils {
33+ use std:: sync:: LazyLock ;
34+
3435 use crate :: {
3536 bn254:: { fp254impl:: Fp254Impl , fq:: Fq , fq2:: Fq2 } ,
3637 chunk:: { helpers:: pack_nibbles_to_limbs, wrap_hasher:: hash_n_bytes} ,
@@ -41,113 +42,134 @@ pub(crate) mod hash_utils {
4142 /// Compute hash of top two field elements on stack: [a00, a01]
4243 /// Output is {BLAKE3_HASH_LENGTH} byte output represented in limb-form
4344 pub ( crate ) fn hash_fp2 ( ) -> Script {
44- script ! {
45- // [a00, a01]
46- { hash_n_bytes:: <64 >( ) }
47- // Hash(a00|a01)
48- { pack_nibbles_to_limbs( ) }
49- }
45+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
46+ script ! {
47+ // [a00, a01]
48+ { hash_n_bytes:: <64 >( ) }
49+ // Hash(a00|a01)
50+ { pack_nibbles_to_limbs( ) }
51+ }
52+ } ) ;
53+ SCRIPT . clone ( )
5054 }
5155
5256 /// Compute hash of top four field elements on stack: [a00, a01, a10, a11]
5357 /// Output is {BLAKE3_HASH_LENGTH} byte output represented in limb-form
5458 pub ( crate ) fn hash_fp4 ( ) -> Script {
55- script ! {
56- // [a00, a01, a10, a11]
57- { Fq2 :: roll( 2 ) }
58- // [a10, a11, a00, a01]
59- // Requires first msg-block at the top of stack
60- { hash_n_bytes:: <128 >( ) }
61- // Hash(a00|a01|a10|a11)
62- { pack_nibbles_to_limbs( ) }
63- }
59+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
60+ script ! {
61+ // [a00, a01, a10, a11]
62+ { Fq2 :: roll( 2 ) }
63+ // [a10, a11, a00, a01]
64+ // Requires first msg-block at the top of stack
65+ { hash_n_bytes:: <128 >( ) }
66+ // Hash(a00|a01|a10|a11)
67+ { pack_nibbles_to_limbs( ) }
68+ }
69+ } ) ;
70+ SCRIPT . clone ( )
6471 }
6572
6673 /// Compute hash of top six field elements on stack: [a00, a01, a10, a11, a20, a21]
6774 /// Output is {BLAKE3_HASH_LENGTH} byte output represented in limb-form
6875 pub ( crate ) fn hash_fp6 ( ) -> Script {
69- script ! {
70- // [a00, a01, a10, a11, a20, a21]
71- { Fq2 :: roll( 2 ) } { Fq2 :: roll( 4 ) }
72- // [a20, a21, a10, a11, a00, a01]
73- // Requires first msg-block at the top of stack
74- { hash_n_bytes:: <192 >( ) }
75- // Hash(a00|a01|a10|a11|a20|a21)
76- { pack_nibbles_to_limbs( ) }
77- }
76+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
77+ script ! {
78+ // [a00, a01, a10, a11, a20, a21]
79+ { Fq2 :: roll( 2 ) } { Fq2 :: roll( 4 ) }
80+ // [a20, a21, a10, a11, a00, a01]
81+ // Requires first msg-block at the top of stack
82+ { hash_n_bytes:: <192 >( ) }
83+ // Hash(a00|a01|a10|a11|a20|a21)
84+ { pack_nibbles_to_limbs( ) }
85+ }
86+ } ) ;
87+ SCRIPT . clone ( )
7888 }
7989
8090 /// Compute hash of top six field elements on stack: [a00, a01,.., a60, a61]
8191 /// Output is {BLAKE3_HASH_LENGTH} byte output represented in limb-form
8292 pub ( crate ) fn hash_fp14 ( ) -> Script {
83- script ! {
84- // [a00, a01,... ,a60, a61]
85- { Fq2 :: roll( 2 ) } { Fq2 :: roll( 4 ) } { Fq2 :: roll( 6 ) }
86- { Fq2 :: roll( 8 ) } { Fq2 :: roll( 10 ) } { Fq2 :: roll( 12 ) }
87- // [a60, a61,... ,a00, a01]
88- { hash_n_bytes:: <448 >( ) }
89- // Hash(a00|a01|..|a60|a61)
90- { pack_nibbles_to_limbs( ) }
91- }
93+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
94+ script ! {
95+ // [a00, a01,... ,a60, a61]
96+ { Fq2 :: roll( 2 ) } { Fq2 :: roll( 4 ) } { Fq2 :: roll( 6 ) }
97+ { Fq2 :: roll( 8 ) } { Fq2 :: roll( 10 ) } { Fq2 :: roll( 12 ) }
98+ // [a60, a61,... ,a00, a01]
99+ { hash_n_bytes:: <448 >( ) }
100+ // Hash(a00|a01|..|a60|a61)
101+ { pack_nibbles_to_limbs( ) }
102+ }
103+ } ) ;
104+ SCRIPT . clone ( )
92105 }
93106
94107 /// Compute hash of G2 Point Accumulator (i.e. [t(4), partial_product(14)]) where Hash(partial_product) has been passed as auxiliary input on stack.
95108 /// Stack: [t(4), Hash_partial_product(1)]
96109 pub ( crate ) fn hash_g2acc_with_hashed_le ( ) -> Script {
97- script ! {
98- // [t, Hash_partial_product]
99- { Fq :: toaltstack( ) }
100- { hash_fp4( ) }
101- { Fq :: fromaltstack( ) }
102- // [Hash_t, Hash_partial_product]
103- { hash_fp2( ) }
104- // [ Hash(Hash_t|Hash_partial_product) ]
105- // [ Hash(G2Acc) ]
106- }
110+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
111+ script ! {
112+ // [t, Hash_partial_product]
113+ { Fq :: toaltstack( ) }
114+ { hash_fp4( ) }
115+ { Fq :: fromaltstack( ) }
116+ // [Hash_t, Hash_partial_product]
117+ { hash_fp2( ) }
118+ // [ Hash(Hash_t|Hash_partial_product) ]
119+ // [ Hash(G2Acc) ]
120+ }
121+ } ) ;
122+ SCRIPT . clone ( )
107123 }
108124
109125 /// Compute hash of G2 Point Accumulator (i.e. [t(4), partial_product(14)]) where all elements are passed as raw value on stack
110126 /// Stack: [t(4), partial_product(14)]
111127 pub ( crate ) fn hash_g2acc ( ) -> Script {
112- script ! {
113- // [t, partial_product]
114- for _ in 0 ..14 {
115- { Fq :: toaltstack( ) }
116- }
117- // [t] [partial_product]
118- { hash_fp4( ) }
119- // [Hash_t] [partial_product]
120- for _ in 0 ..14 {
128+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
129+ script ! {
130+ // [t, partial_product]
131+ for _ in 0 ..14 {
132+ { Fq :: toaltstack( ) }
133+ }
134+ // [t] [partial_product]
135+ { hash_fp4( ) }
136+ // [Hash_t] [partial_product]
137+ for _ in 0 ..14 {
138+ { Fq :: fromaltstack( ) }
139+ }
140+ // [Hash_t partial_product]
141+ { Fq :: roll( 14 ) } { Fq :: toaltstack( ) }
142+ // [partial_product] [Hash_t]
143+ { hash_fp14( ) }
144+ // [Hash_partial_product] [Hash_t]
121145 { Fq :: fromaltstack( ) }
146+ { Fq :: roll( 1 ) }
147+ // [ Hash_t, Hash_partial_product ]
148+ { hash_fp2( ) }
149+ // [ Hash(Hash_t|Hash_partial_priduct) ]
150+ // [ Hash(G2Acc) ]
122151 }
123- // [Hash_t partial_product]
124- { Fq :: roll( 14 ) } { Fq :: toaltstack( ) }
125- // [partial_product] [Hash_t]
126- { hash_fp14( ) }
127- // [Hash_partial_product] [Hash_t]
128- { Fq :: fromaltstack( ) }
129- { Fq :: roll( 1 ) }
130- // [ Hash_t, Hash_partial_product ]
131- { hash_fp2( ) }
132- // [ Hash(Hash_t|Hash_partial_priduct) ]
133- // [ Hash(G2Acc) ]
134- }
152+ } ) ;
153+ SCRIPT . clone ( )
135154 }
136155
137156 /// Compute hash of G2 Point Accumulator (i.e. [t(4), partial_product(14)]) where Hash(t) has been passed as auxiliary input on stack.
138157 /// Stack: [Hash_partial_priduct(14), Hash_t(1)]
139158 pub ( crate ) fn hash_g2acc_with_hash_t ( ) -> Script {
140- script ! {
141- // [partial_product, Hash_t]
142- { Fq :: toaltstack( ) }
143- { hash_fp14( ) }
144- { Fq :: fromaltstack( ) }
145- { Fq :: roll( 1 ) }
146- // [ Hash_t, Hash_partial_product ]
147- { hash_fp2( ) }
148- // [ Hash(Hash_t|Hash_partial_priduct) ]
149- // [ Hash(G2Acc) ]
150- }
159+ static SCRIPT : LazyLock < Script > = LazyLock :: new ( || {
160+ script ! {
161+ // [partial_product, Hash_t]
162+ { Fq :: toaltstack( ) }
163+ { hash_fp14( ) }
164+ { Fq :: fromaltstack( ) }
165+ { Fq :: roll( 1 ) }
166+ // [ Hash_t, Hash_partial_product ]
167+ { hash_fp2( ) }
168+ // [ Hash(Hash_t|Hash_partial_priduct) ]
169+ // [ Hash(G2Acc) ]
170+ }
171+ } ) ;
172+ SCRIPT . clone ( )
151173 }
152174}
153175
0 commit comments