Skip to content

Commit 663717c

Browse files
authored
chore: cache hashing scripts (BitVM#294)
1 parent d3ee606 commit 663717c

1 file changed

Lines changed: 99 additions & 77 deletions

File tree

bitvm/src/chunk/wrap_hasher.rs

Lines changed: 99 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::elements::ElementType;
12
use 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-
1312
pub 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
3332
pub(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

Comments
 (0)