runar_compiler_rust/codegen/
sha256.rs1use super::stack::{PushValue, StackOp};
15
16use std::sync::OnceLock;
17
18const K: [u32; 64] = [
20 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
21 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
22 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
23 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
24 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
25 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
26 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
27 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
28 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
29 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
30 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
31 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
32 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
33 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
34 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
35 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
36];
37
38fn u32_to_le(n: u32) -> Vec<u8> {
40 vec![
41 (n & 0xff) as u8,
42 ((n >> 8) & 0xff) as u8,
43 ((n >> 16) & 0xff) as u8,
44 ((n >> 24) & 0xff) as u8,
45 ]
46}
47
48struct Emitter {
53 ops: Vec<StackOp>,
54 depth: i64,
55 alt_depth: i64,
56}
57
58impl Emitter {
59 fn new(initial_depth: i64) -> Self {
60 Emitter {
61 ops: Vec::new(),
62 depth: initial_depth,
63 alt_depth: 0,
64 }
65 }
66
67 fn e_raw(&mut self, sop: StackOp) {
68 self.ops.push(sop);
69 }
70
71 fn oc(&mut self, code: &str) {
72 self.ops.push(StackOp::Opcode(code.to_string()));
73 }
74
75 fn push_i(&mut self, v: i128) {
76 self.ops.push(StackOp::Push(PushValue::Int(v)));
77 self.depth += 1;
78 }
79
80 fn push_b(&mut self, v: Vec<u8>) {
81 self.ops.push(StackOp::Push(PushValue::Bytes(v)));
82 self.depth += 1;
83 }
84
85 fn dup(&mut self) {
86 self.ops.push(StackOp::Dup);
87 self.depth += 1;
88 }
89
90 fn drop(&mut self) {
91 self.ops.push(StackOp::Drop);
92 self.depth -= 1;
93 }
94
95 fn swap(&mut self) {
96 self.ops.push(StackOp::Swap);
97 }
98
99 fn over(&mut self) {
100 self.ops.push(StackOp::Over);
101 self.depth += 1;
102 }
103
104 fn rot(&mut self) {
105 self.ops.push(StackOp::Rot);
106 }
107
108 fn pick(&mut self, d: usize) {
109 if d == 0 {
110 self.dup();
111 return;
112 }
113 if d == 1 {
114 self.over();
115 return;
116 }
117 self.push_i(d as i128);
118 self.ops.push(StackOp::Pick { depth: d });
119 }
121
122 fn roll(&mut self, d: usize) {
123 if d == 0 {
124 return;
125 }
126 if d == 1 {
127 self.swap();
128 return;
129 }
130 if d == 2 {
131 self.rot();
132 return;
133 }
134 self.push_i(d as i128);
135 self.ops.push(StackOp::Roll { depth: d });
136 self.depth -= 1; }
138
139 fn to_alt(&mut self) {
140 self.oc("OP_TOALTSTACK");
141 self.depth -= 1;
142 self.alt_depth += 1;
143 }
144
145 fn from_alt(&mut self) {
146 self.oc("OP_FROMALTSTACK");
147 self.depth += 1;
148 self.alt_depth -= 1;
149 }
150
151 fn bin_op(&mut self, code: &str) {
152 self.oc(code);
153 self.depth -= 1;
154 }
155
156 fn uni_op(&mut self, code: &str) {
157 self.oc(code);
158 }
159
160 fn dup2(&mut self) {
161 self.oc("OP_2DUP");
162 self.depth += 2;
163 }
164
165 fn split(&mut self) {
166 self.oc("OP_SPLIT");
167 }
169
170 fn split4(&mut self) {
171 self.push_i(4);
172 self.split();
173 }
174
175 fn assert_depth(&self, expected: i64, msg: &str) {
176 assert_eq!(
177 self.depth, expected,
178 "SHA256 codegen: {}. Expected depth {}, got {}",
179 msg, expected, self.depth
180 );
181 }
182
183 fn reverse_bytes4(&mut self) {
187 self.push_i(1);
188 self.split();
189 self.push_i(1);
190 self.split();
191 self.push_i(1);
192 self.split();
193 self.swap();
194 self.bin_op("OP_CAT");
195 self.swap();
196 self.bin_op("OP_CAT");
197 self.swap();
198 self.bin_op("OP_CAT");
199 }
200
201 fn le2num(&mut self) {
205 self.push_b(vec![0x00]); self.bin_op("OP_CAT");
207 self.uni_op("OP_BIN2NUM");
208 }
209
210 fn num2le(&mut self) {
212 self.push_i(5);
213 self.bin_op("OP_NUM2BIN"); self.push_i(4);
215 self.split(); self.drop(); }
218
219 fn add32(&mut self) {
223 self.le2num();
224 self.swap();
225 self.le2num();
226 self.bin_op("OP_ADD");
227 self.num2le();
228 }
229
230 fn add_n(&mut self, n: usize) {
232 if n < 2 {
233 return;
234 }
235 self.le2num();
236 for _ in 1..n {
237 self.swap();
238 self.le2num();
239 self.bin_op("OP_ADD");
240 }
241 self.num2le();
242 }
243
244 fn rotr_be(&mut self, n: usize) {
248 self.dup(); self.push_i(n as i128);
250 self.bin_op("OP_RSHIFT"); self.swap(); self.push_i((32 - n) as i128);
253 self.bin_op("OP_LSHIFT"); self.bin_op("OP_OR"); }
256
257 fn shr_be(&mut self, n: usize) {
259 self.push_i(n as i128);
260 self.bin_op("OP_RSHIFT");
261 }
262
263 fn big_sigma0(&mut self) {
267 self.reverse_bytes4(); self.dup();
269 self.dup();
270 self.rotr_be(2);
271 self.swap();
272 self.rotr_be(13);
273 self.bin_op("OP_XOR");
274 self.swap();
275 self.rotr_be(22);
276 self.bin_op("OP_XOR");
277 self.reverse_bytes4(); }
279
280 fn big_sigma1(&mut self) {
282 self.reverse_bytes4();
283 self.dup();
284 self.dup();
285 self.rotr_be(6);
286 self.swap();
287 self.rotr_be(11);
288 self.bin_op("OP_XOR");
289 self.swap();
290 self.rotr_be(25);
291 self.bin_op("OP_XOR");
292 self.reverse_bytes4();
293 }
294
295 fn small_sigma0(&mut self) {
297 self.reverse_bytes4();
298 self.dup();
299 self.dup();
300 self.rotr_be(7);
301 self.swap();
302 self.rotr_be(18);
303 self.bin_op("OP_XOR");
304 self.swap();
305 self.shr_be(3);
306 self.bin_op("OP_XOR");
307 self.reverse_bytes4();
308 }
309
310 fn small_sigma1(&mut self) {
312 self.reverse_bytes4();
313 self.dup();
314 self.dup();
315 self.rotr_be(17);
316 self.swap();
317 self.rotr_be(19);
318 self.bin_op("OP_XOR");
319 self.swap();
320 self.shr_be(10);
321 self.bin_op("OP_XOR");
322 self.reverse_bytes4();
323 }
324
325 fn ch(&mut self) {
327 self.rot();
328 self.dup();
329 self.uni_op("OP_INVERT");
330 self.rot();
331 self.bin_op("OP_AND");
332 self.to_alt();
333 self.bin_op("OP_AND");
334 self.from_alt();
335 self.bin_op("OP_XOR");
336 }
337
338 fn maj(&mut self) {
340 self.to_alt();
341 self.dup2();
342 self.bin_op("OP_AND");
343 self.to_alt();
344 self.bin_op("OP_XOR");
345 self.from_alt();
346 self.swap();
347 self.from_alt();
348 self.bin_op("OP_AND");
349 self.bin_op("OP_OR");
350 }
351
352 fn be_words_to_le(&mut self, n: usize) {
354 for _ in 0..n {
355 self.reverse_bytes4();
356 self.to_alt();
357 }
358 for _ in 0..n {
359 self.from_alt();
360 }
361 }
362
363 fn be_words_to_le_reversed8(&mut self) {
365 for i in (0..8).rev() {
366 self.roll(i);
367 self.reverse_bytes4();
368 self.to_alt();
369 }
370 for _ in 0..8 {
371 self.from_alt();
372 }
373 }
374}
375
376fn emit_round(em: &mut Emitter, t: usize) {
382 let d0 = em.depth;
383
384 em.pick(4); em.big_sigma1(); em.pick(5);
389 em.pick(7);
390 em.pick(9); em.ch(); em.pick(9); em.push_b(u32_to_le(K[t])); em.pick(75 - t); em.add_n(5); em.dup();
401 em.to_alt(); em.pick(1); em.big_sigma0(); em.pick(2);
407 em.pick(4);
408 em.pick(6); em.maj(); em.add32(); em.from_alt(); em.swap();
416 em.add32(); em.swap();
419 em.roll(5); em.add32(); em.roll(8);
423 em.drop(); em.swap();
427 em.roll(4);
428 em.roll(4);
429 em.roll(4);
430 em.roll(3);
431
432 em.assert_depth(d0, &format!("compress: after round {}", t));
433}
434
435fn generate_compress_ops() -> Vec<StackOp> {
440 let mut em = Emitter::new(2); em.swap();
444 em.dup();
445 em.to_alt();
446 em.to_alt();
447 em.assert_depth(1, "compress: after state save");
448
449 for _ in 0..15 {
450 em.split4();
451 }
452 em.assert_depth(16, "compress: after block unpack");
453 em.be_words_to_le(16);
454 em.assert_depth(16, "compress: after block LE convert");
455
456 for _t in 16..64 {
458 em.over();
459 em.small_sigma1();
460 em.pick(6 + 1);
461 em.pick(14 + 2);
462 em.small_sigma0();
463 em.pick(15 + 3);
464 em.add_n(4);
465 }
466 em.assert_depth(64, "compress: after W expansion");
467
468 em.from_alt();
470 for _ in 0..7 {
471 em.split4();
472 }
473 em.assert_depth(72, "compress: after state unpack");
474 em.be_words_to_le_reversed8();
475 em.assert_depth(72, "compress: after state LE convert");
476
477 for t in 0..64 {
479 emit_round(&mut em, t);
480 }
481
482 em.from_alt();
484 em.assert_depth(73, "compress: before final add");
485
486 for _ in 0..7 {
487 em.split4();
488 }
489 em.be_words_to_le_reversed8();
490 em.assert_depth(80, "compress: after init unpack");
491
492 for i in 0..8 {
493 em.roll(8 - i);
494 em.add32();
495 em.to_alt();
496 }
497 em.assert_depth(64, "compress: after final add");
498
499 em.from_alt();
500 em.reverse_bytes4();
501 for _ in 1..8 {
502 em.from_alt();
503 em.reverse_bytes4();
504 em.swap();
505 em.bin_op("OP_CAT");
506 }
507 em.assert_depth(65, "compress: after pack");
508
509 for _ in 0..64 {
510 em.swap();
511 em.drop();
512 }
513 em.assert_depth(1, "compress: final");
514
515 em.ops
516}
517
518static COMPRESS_OPS: OnceLock<Vec<StackOp>> = OnceLock::new();
520
521fn get_compress_ops() -> &'static Vec<StackOp> {
522 COMPRESS_OPS.get_or_init(generate_compress_ops)
523}
524
525pub fn emit_sha256_compress(emit: &mut dyn FnMut(StackOp)) {
533 for op in get_compress_ops() {
534 emit(op.clone());
535 }
536}
537
538pub fn emit_sha256_finalize(emit: &mut dyn FnMut(StackOp)) {
542 let mut em = Emitter::new(3); em.push_i(9);
546 em.bin_op("OP_NUM2BIN"); em.push_i(8);
548 em.split(); em.drop(); em.push_i(4);
552 em.split(); em.reverse_bytes4(); em.swap();
555 em.reverse_bytes4(); em.bin_op("OP_CAT"); em.to_alt(); em.assert_depth(2, "finalize: after bitLen conversion");
559
560 em.push_b(vec![0x80]);
562 em.bin_op("OP_CAT"); em.oc("OP_SIZE");
566 em.depth += 1; em.dup();
570 em.push_i(57);
571 em.bin_op("OP_LESSTHAN"); em.oc("OP_IF");
574 em.depth -= 1; em.push_i(56);
578 em.swap();
579 em.bin_op("OP_SUB"); em.push_i(0);
581 em.swap();
582 em.bin_op("OP_NUM2BIN"); em.bin_op("OP_CAT"); em.from_alt(); em.bin_op("OP_CAT"); let compress_ops = get_compress_ops();
588 for op in compress_ops {
589 em.e_raw(op.clone());
590 }
591 em.depth = 1; em.oc("OP_ELSE");
594 em.depth = 3; em.push_i(120);
598 em.swap();
599 em.bin_op("OP_SUB"); em.push_i(0);
601 em.swap();
602 em.bin_op("OP_NUM2BIN"); em.bin_op("OP_CAT"); em.from_alt(); em.bin_op("OP_CAT"); em.push_i(64);
609 em.split(); em.to_alt(); for op in compress_ops {
614 em.e_raw(op.clone());
615 }
616 em.depth = 1; em.from_alt(); for op in compress_ops {
621 em.e_raw(op.clone());
622 }
623 em.depth = 1; em.oc("OP_ENDIF");
626 em.assert_depth(1, "finalize: final");
628
629 for op in em.ops {
630 emit(op);
631 }
632}