1use sha2::{Digest, Sha256 as Sha256Hasher};
8
9pub use runar_lang_macros::{contract, methods, public, stateful_contract};
11
12pub type Int = i64;
18
19pub type Bigint = i64;
21
22pub type PubKey = Vec<u8>;
28
29pub type Sig = Vec<u8>;
31
32pub type Addr = Vec<u8>;
34
35pub type ByteString = Vec<u8>;
37
38pub type Sha256 = Vec<u8>;
40
41pub type Ripemd160 = Vec<u8>;
43
44pub type SigHashPreimage = Vec<u8>;
46
47pub type RabinSig = Vec<u8>;
49
50pub type RabinPubKey = Vec<u8>;
52
53pub type Point = Vec<u8>;
55
56#[derive(Debug, Clone)]
62pub struct OutputSnapshot {
63 pub satoshis: Bigint,
64 pub values: Vec<Vec<u8>>,
65}
66
67pub fn check_sig(sig: &[u8], pk: &[u8]) -> bool {
77 crate::ecdsa::ecdsa_verify(sig, pk)
78}
79
80pub fn check_multi_sig(sigs: &[&[u8]], pks: &[&[u8]]) -> bool {
85 if sigs.len() != pks.len() {
86 return false;
87 }
88 for (sig, pk) in sigs.iter().zip(pks.iter()) {
89 if !crate::ecdsa::ecdsa_verify(sig, pk) {
90 return false;
91 }
92 }
93 true
94}
95
96pub fn check_preimage(_preimage: &[u8]) -> bool {
98 true
99}
100
101pub fn verify_rabin_sig(msg: &[u8], sig: &[u8], padding: &[u8], pk: &[u8]) -> bool {
106 crate::rabin::rabin_verify(msg, sig, padding, pk)
107}
108
109pub fn verify_wots(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
111 crate::wots::wots_verify_impl(msg, sig, pk)
112}
113
114pub fn verify_slh_dsa_sha2_128s(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
118 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_128S, msg, sig, pk)
119}
120
121pub fn verify_slh_dsa_sha2_128f(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
123 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_128F, msg, sig, pk)
124}
125
126pub fn verify_slh_dsa_sha2_192s(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
128 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_192S, msg, sig, pk)
129}
130
131pub fn verify_slh_dsa_sha2_192f(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
133 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_192F, msg, sig, pk)
134}
135
136pub fn verify_slh_dsa_sha2_256s(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
138 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_256S, msg, sig, pk)
139}
140
141pub fn verify_slh_dsa_sha2_256f(msg: &[u8], sig: &[u8], pk: &[u8]) -> bool {
143 crate::slh_dsa::slh_verify(&crate::slh_dsa::SLH_SHA2_256F, msg, sig, pk)
144}
145
146pub use crate::ec::{
152 ec_add, ec_encode_compressed, ec_make_point, ec_mod_reduce, ec_mul, ec_mul_gen,
153 ec_negate, ec_on_curve, ec_point_x, ec_point_y,
154};
155
156pub use crate::wots::{wots_keygen, wots_sign, WotsKeyPair};
157
158pub use crate::slh_dsa::{
159 slh_keygen, slh_sign, slh_verify, SlhKeyPair, SlhParams,
160 SLH_SHA2_128S, SLH_SHA2_128F, SLH_SHA2_192S, SLH_SHA2_192F,
161 SLH_SHA2_256S, SLH_SHA2_256F,
162};
163
164pub use crate::ecdsa::{
165 sign_test_message, pub_key_from_priv_key, ecdsa_verify,
166 TEST_MESSAGE, TEST_MESSAGE_DIGEST,
167};
168
169pub use crate::test_keys::{TestKeyPair, ALICE, BOB, CHARLIE};
170
171pub use crate::rabin::rabin_sign_trivial;
172
173pub fn hash160(data: &[u8]) -> Addr {
179 let sha = Sha256Hasher::digest(data);
180 let mut hasher = ripemd::Ripemd160::new();
181 hasher.update(&sha);
182 hasher.finalize().to_vec()
183}
184
185pub fn hash256(data: &[u8]) -> Sha256 {
187 let h1 = Sha256Hasher::digest(data);
188 let h2 = Sha256Hasher::digest(&h1);
189 h2.to_vec()
190}
191
192pub fn sha256(data: &[u8]) -> Sha256 {
194 Sha256Hasher::digest(data).to_vec()
195}
196
197pub fn ripemd160(data: &[u8]) -> Ripemd160 {
199 let mut hasher = ripemd::Ripemd160::new();
200 hasher.update(data);
201 hasher.finalize().to_vec()
202}
203
204pub fn blake3_compress(_chaining_value: &[u8], _block: &[u8]) -> ByteString {
212 vec![0u8; 32]
213}
214
215pub fn blake3_hash(_message: &[u8]) -> ByteString {
220 vec![0u8; 32]
221}
222
223const SHA256_K: [u32; 64] = [
228 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
229 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
230 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
231 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
232 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
233 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
234 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
235 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
236 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
237 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
238 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
239 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
240 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
241 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
242 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
243 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
244];
245
246pub fn sha256_compress(state: &[u8], block: &[u8]) -> ByteString {
251 assert!(state.len() == 32, "sha256_compress: state must be 32 bytes");
252 assert!(block.len() == 64, "sha256_compress: block must be 64 bytes");
253
254 let mut h = [0u32; 8];
256 for i in 0..8 {
257 h[i] = u32::from_be_bytes(state[i * 4..i * 4 + 4].try_into().unwrap());
258 }
259
260 let mut w = [0u32; 64];
262 for i in 0..16 {
263 w[i] = u32::from_be_bytes(block[i * 4..i * 4 + 4].try_into().unwrap());
264 }
265
266 for t in 16..64 {
268 let s0 = w[t - 15].rotate_right(7) ^ w[t - 15].rotate_right(18) ^ (w[t - 15] >> 3);
269 let s1 = w[t - 2].rotate_right(17) ^ w[t - 2].rotate_right(19) ^ (w[t - 2] >> 10);
270 w[t] = w[t - 16]
271 .wrapping_add(s0)
272 .wrapping_add(w[t - 7])
273 .wrapping_add(s1);
274 }
275
276 let mut a = h[0];
278 let mut b = h[1];
279 let mut c = h[2];
280 let mut d = h[3];
281 let mut e = h[4];
282 let mut f = h[5];
283 let mut g = h[6];
284 let mut hh = h[7];
285
286 for t in 0..64 {
288 let big_s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
289 let ch = (e & f) ^ ((!e) & g);
290 let temp1 = hh
291 .wrapping_add(big_s1)
292 .wrapping_add(ch)
293 .wrapping_add(SHA256_K[t])
294 .wrapping_add(w[t]);
295 let big_s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
296 let maj = (a & b) ^ (a & c) ^ (b & c);
297 let temp2 = big_s0.wrapping_add(maj);
298
299 hh = g;
300 g = f;
301 f = e;
302 e = d.wrapping_add(temp1);
303 d = c;
304 c = b;
305 b = a;
306 a = temp1.wrapping_add(temp2);
307 }
308
309 h[0] = h[0].wrapping_add(a);
311 h[1] = h[1].wrapping_add(b);
312 h[2] = h[2].wrapping_add(c);
313 h[3] = h[3].wrapping_add(d);
314 h[4] = h[4].wrapping_add(e);
315 h[5] = h[5].wrapping_add(f);
316 h[6] = h[6].wrapping_add(g);
317 h[7] = h[7].wrapping_add(hh);
318
319 let mut result = vec![0u8; 32];
321 for i in 0..8 {
322 result[i * 4..i * 4 + 4].copy_from_slice(&h[i].to_be_bytes());
323 }
324 result
325}
326
327pub fn sha256_finalize(state: &[u8], remaining: &[u8], msg_bit_len: i64) -> ByteString {
333 assert!(state.len() == 32, "sha256_finalize: state must be 32 bytes");
334 assert!(remaining.len() <= 64, "sha256_finalize: remaining must be <= 64 bytes");
335
336 let rem_len = remaining.len();
337
338 if rem_len < 56 {
342 let mut block = [0u8; 64];
344 block[..rem_len].copy_from_slice(remaining);
345 block[rem_len] = 0x80;
346 let bit_len = msg_bit_len as u64;
348 block[56..64].copy_from_slice(&bit_len.to_be_bytes());
349 sha256_compress(state, &block)
350 } else {
351 let mut block1 = [0u8; 64];
353 block1[..rem_len].copy_from_slice(remaining);
354 block1[rem_len] = 0x80;
355 let intermediate = sha256_compress(state, &block1);
357
358 let mut block2 = [0u8; 64];
360 let bit_len = msg_bit_len as u64;
361 block2[56..64].copy_from_slice(&bit_len.to_be_bytes());
362 sha256_compress(&intermediate, &block2)
363 }
364}
365
366pub fn extract_locktime(_p: &[u8]) -> Int {
372 0
373}
374
375pub fn extract_output_hash(p: &[u8]) -> ByteString {
380 if p.len() >= 32 {
381 p[..32].to_vec()
382 } else {
383 vec![0u8; 32]
384 }
385}
386
387pub fn extract_hash_prevouts(_p: &[u8]) -> Sha256 {
391 hash256(&vec![0u8; 72])
392}
393
394pub fn extract_outpoint(_p: &[u8]) -> ByteString {
396 vec![0u8; 36]
397}
398
399pub fn get_state_script<T>(_contract: &T) -> ByteString {
401 vec![]
402}
403
404pub fn substr(data: &[u8], start: i64, length: i64) -> ByteString {
410 let s = start as usize;
411 let l = length as usize;
412 data[s..s + l].to_vec()
413}
414
415pub fn num2bin(v: &Bigint, length: usize) -> ByteString {
419 let mut buf = vec![0u8; length];
420 if *v == 0 || length == 0 {
421 return buf;
422 }
423 let abs = v.unsigned_abs();
424 let mut val = abs;
425 for byte in buf.iter_mut() {
426 if val == 0 {
427 break;
428 }
429 *byte = (val & 0xff) as u8;
430 val >>= 8;
431 }
432 if *v < 0 {
433 buf[length - 1] |= 0x80;
434 }
435 buf
436}
437
438pub fn bin2num(data: &[u8]) -> Bigint {
441 if data.is_empty() {
442 return 0;
443 }
444 let last = data[data.len() - 1];
445 let negative = (last & 0x80) != 0;
446 let mut result: u64 = (last & 0x7f) as u64;
447 for i in (0..data.len() - 1).rev() {
448 result = (result << 8) | data[i] as u64;
449 }
450 if negative {
451 -(result as i64)
452 } else {
453 result as i64
454 }
455}
456
457pub fn cat(a: &[u8], b: &[u8]) -> ByteString {
459 let mut result = a.to_vec();
460 result.extend_from_slice(b);
461 result
462}
463
464pub fn safediv(a: Int, b: Int) -> Int {
470 assert!(b != 0, "safediv: division by zero");
471 a / b
472}
473
474pub fn safemod(a: Int, b: Int) -> Int {
476 assert!(b != 0, "safemod: modulo by zero");
477 a % b
478}
479
480pub fn clamp(value: Int, lo: Int, hi: Int) -> Int {
482 if value < lo { lo } else if value > hi { hi } else { value }
483}
484
485pub fn sign(n: Int) -> Int {
487 if n > 0 { 1 } else if n < 0 { -1 } else { 0 }
488}
489
490pub fn pow(base: Int, exp: Int) -> Int {
492 assert!(exp >= 0, "pow: negative exponent");
493 let mut result: Int = 1;
494 for _ in 0..exp {
495 result = result.checked_mul(base).unwrap_or_else(|| {
496 panic!("runar: i64 overflow in {} * {} — Bitcoin Script supports arbitrary precision but Rust tests use i64", result, base)
497 });
498 }
499 result
500}
501
502pub fn mul_div(a: Int, b: Int, c: Int) -> Int {
504 assert!(c != 0, "mulDiv: division by zero");
505 let product = a.checked_mul(b).unwrap_or_else(|| {
506 panic!("runar: i64 overflow in {} * {} — Bitcoin Script supports arbitrary precision but Rust tests use i64", a, b)
507 });
508 product / c
509}
510
511pub fn percent_of(amount: Int, bps: Int) -> Int {
513 let product = amount.checked_mul(bps).unwrap_or_else(|| {
514 panic!("runar: i64 overflow in {} * {} — Bitcoin Script supports arbitrary precision but Rust tests use i64", amount, bps)
515 });
516 product / 10000
517}
518
519pub fn sqrt(n: Int) -> Int {
521 assert!(n >= 0, "sqrt: negative input");
522 if n == 0 { return 0; }
523 let mut guess = n;
524 for _ in 0..256 {
525 let sum = guess.checked_add(n / guess).unwrap_or_else(|| {
526 panic!("runar: i64 overflow in sqrt — Bitcoin Script supports arbitrary precision but Rust tests use i64")
527 });
528 let next = sum / 2;
529 if next >= guess { break; }
530 guess = next;
531 }
532 guess
533}
534
535pub fn gcd(mut a: Int, mut b: Int) -> Int {
538 a = a.checked_abs().unwrap_or_else(|| {
539 panic!("runar: i64 overflow in gcd — |i64::MIN| not representable; Bitcoin Script supports arbitrary precision but Rust tests use i64")
540 });
541 b = b.checked_abs().unwrap_or_else(|| {
542 panic!("runar: i64 overflow in gcd — |i64::MIN| not representable; Bitcoin Script supports arbitrary precision but Rust tests use i64")
543 });
544 while b != 0 { let t = b; b = a % b; a = t; }
545 a
546}
547
548pub fn divmod(a: Int, b: Int) -> Int {
550 assert!(b != 0, "divmod: division by zero");
551 a / b
552}
553
554pub fn log2(n: Int) -> Int {
556 if n <= 0 { return 0; }
557 let mut bits: Int = 0;
558 let mut val = n;
559 while val > 1 { val >>= 1; bits += 1; }
560 bits
561}
562
563pub fn bool_cast(n: Int) -> bool {
565 n != 0
566}
567
568pub fn mock_sig() -> Sig {
574 vec![0u8; 72]
575}
576
577pub fn mock_pub_key() -> PubKey {
579 let mut pk = vec![0u8; 33];
580 pk[0] = 0x02;
581 pk
582}
583
584pub fn mock_preimage() -> SigHashPreimage {
586 vec![0u8; 181]
587}
588
589#[cfg(test)]
590mod tests {
591 use super::*;
592
593 #[test]
594 fn test_check_sig_real_ecdsa() {
595 let sig = ALICE.sign_test_message();
596 assert!(check_sig(&sig, ALICE.pub_key));
597 }
598
599 #[test]
600 fn test_check_sig_rejects_wrong_key() {
601 let sig = ALICE.sign_test_message();
602 assert!(!check_sig(&sig, BOB.pub_key));
603 }
604
605 #[test]
606 fn test_check_multi_sig_real() {
607 let alice_sig = ALICE.sign_test_message();
608 let bob_sig = BOB.sign_test_message();
609 assert!(check_multi_sig(
610 &[alice_sig.as_slice(), bob_sig.as_slice()],
611 &[ALICE.pub_key, BOB.pub_key],
612 ));
613 }
614
615 #[test]
616 fn test_check_multi_sig_rejects_wrong_order() {
617 let alice_sig = ALICE.sign_test_message();
618 let bob_sig = BOB.sign_test_message();
619 assert!(!check_multi_sig(
621 &[alice_sig.as_slice(), bob_sig.as_slice()],
622 &[BOB.pub_key, ALICE.pub_key],
623 ));
624 }
625
626 #[test]
627 fn test_check_preimage_always_true() {
628 assert!(check_preimage(&mock_preimage()));
629 }
630
631 #[test]
632 fn test_hash160_produces_20_bytes() {
633 assert_eq!(hash160(b"hello").len(), 20);
634 }
635
636 #[test]
637 fn test_hash160_deterministic() {
638 assert_eq!(hash160(b"test data"), hash160(b"test data"));
639 }
640
641 #[test]
642 fn test_hash256_produces_32_bytes() {
643 assert_eq!(hash256(b"hello").len(), 32);
644 }
645
646 #[test]
647 fn test_hash256_deterministic() {
648 assert_eq!(hash256(b"test data"), hash256(b"test data"));
649 }
650
651 #[test]
652 fn test_sha256_produces_32_bytes() {
653 assert_eq!(sha256(b"hello").len(), 32);
654 }
655
656 #[test]
657 fn test_ripemd160_produces_20_bytes() {
658 assert_eq!(ripemd160(b"hello").len(), 20);
659 }
660
661 #[test]
662 fn test_num2bin_zero() {
663 assert_eq!(num2bin(&0, 4), vec![0, 0, 0, 0]);
664 }
665
666 #[test]
667 fn test_num2bin_positive() {
668 assert_eq!(num2bin(&42, 4)[0], 42);
669 }
670
671 #[test]
672 fn test_num2bin_negative() {
673 let result = num2bin(&-42, 4);
674 assert_eq!(result[0], 42);
675 assert!(result[3] & 0x80 != 0);
676 }
677
678 #[test]
679 fn test_mock_sig_length() {
680 assert_eq!(mock_sig().len(), 72);
681 }
682
683 #[test]
684 fn test_mock_pub_key_length() {
685 let pk = mock_pub_key();
686 assert_eq!(pk.len(), 33);
687 assert_eq!(pk[0], 0x02);
688 }
689
690 #[test]
695 fn test_pow_small_values() {
696 assert_eq!(pow(2, 10), 1024);
697 assert_eq!(pow(3, 0), 1);
698 }
699
700 #[test]
701 #[should_panic(expected = "i64 overflow")]
702 fn test_pow_overflow() {
703 pow(i64::MAX, 2);
704 }
705
706 #[test]
707 fn test_mul_div_small_values() {
708 assert_eq!(mul_div(100, 3, 2), 150);
709 }
710
711 #[test]
712 #[should_panic(expected = "i64 overflow")]
713 fn test_mul_div_overflow() {
714 mul_div(i64::MAX, 2, 1);
715 }
716
717 #[test]
718 fn test_percent_of_small_values() {
719 assert_eq!(percent_of(10000, 2500), 2500);
720 }
721
722 #[test]
723 #[should_panic(expected = "i64 overflow")]
724 fn test_percent_of_overflow() {
725 percent_of(i64::MAX, 5000);
726 }
727
728 #[test]
729 fn test_gcd_small_values() {
730 assert_eq!(gcd(12, 8), 4);
731 }
732
733 #[test]
734 #[should_panic(expected = "i64 overflow")]
735 fn test_gcd_min_panics() {
736 gcd(i64::MIN, 1);
737 }
738
739 #[test]
744 fn test_safediv_positive() {
745 assert_eq!(safediv(10, 3), 3);
747 }
748
749 #[test]
750 fn test_safediv_truncates_toward_zero() {
751 assert_eq!(safediv(-7, 2), -3);
753 }
754
755 #[test]
756 #[should_panic(expected = "safediv: division by zero")]
757 fn test_safediv_by_zero_panics() {
758 safediv(42, 0);
759 }
760
761 #[test]
766 fn test_safemod_positive() {
767 assert_eq!(safemod(10, 3), 1);
768 }
769
770 #[test]
771 fn test_safemod_negative() {
772 assert_eq!(safemod(-7, 2), -1);
774 }
775
776 #[test]
781 fn test_clamp_within_range() {
782 assert_eq!(clamp(5, 0, 10), 5);
783 }
784
785 #[test]
786 fn test_clamp_below() {
787 assert_eq!(clamp(-1, 0, 10), 0);
788 }
789
790 #[test]
791 fn test_clamp_above() {
792 assert_eq!(clamp(15, 0, 10), 10);
793 }
794
795 #[test]
800 fn test_sign_positive() {
801 assert_eq!(sign(42), 1);
802 }
803
804 #[test]
805 fn test_sign_negative() {
806 assert_eq!(sign(-42), -1);
807 }
808
809 #[test]
810 fn test_sign_zero() {
811 assert_eq!(sign(0), 0);
812 }
813
814 #[test]
819 fn test_sqrt_perfect_square() {
820 assert_eq!(sqrt(9), 3);
821 }
822
823 #[test]
824 fn test_sqrt_non_perfect() {
825 assert_eq!(sqrt(10), 3);
827 }
828
829 #[test]
834 fn test_log2_power_of_two() {
835 assert_eq!(log2(8), 3);
836 }
837
838 #[test]
839 fn test_log2_non_power() {
840 assert_eq!(log2(9), 3);
842 }
843
844 fn hex_decode(s: &str) -> Vec<u8> {
850 assert!(s.len() % 2 == 0, "hex string must have even length");
851 (0..s.len())
852 .step_by(2)
853 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
854 .collect()
855 }
856
857 fn hex_encode(data: &[u8]) -> String {
859 data.iter().map(|b| format!("{:02x}", b)).collect()
860 }
861
862 #[test]
863 fn test_sha256_compress_abc() {
864 let state = hex_decode("6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19");
865 let block = hex_decode(
866 "6162638000000000000000000000000000000000000000000000000000000000\
867 0000000000000000000000000000000000000000000000000000000000000018"
868 );
869 let result = sha256_compress(&state, &block);
870 assert_eq!(
871 hex_encode(&result),
872 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
873 );
874 }
875
876 #[test]
877 fn test_sha256_finalize_abc() {
878 let state = hex_decode("6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19");
879 let result = sha256_finalize(&state, b"abc", 24);
880 assert_eq!(
881 hex_encode(&result),
882 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
883 );
884 }
885
886 #[test]
887 fn test_sha256_finalize_empty() {
888 let state = hex_decode("6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19");
889 let result = sha256_finalize(&state, b"", 0);
890 assert_eq!(
891 hex_encode(&result),
892 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
893 );
894 }
895
896 #[test]
897 fn test_sha256_finalize_cross_verify() {
898 let state = hex_decode("6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19");
899 for msg in &["", "abc", "hello world"] {
900 let finalized = sha256_finalize(&state, msg.as_bytes(), (msg.len() * 8) as i64);
901 let hashed = sha256(msg.as_bytes());
902 assert_eq!(finalized, hashed, "mismatch for {:?}", msg);
903 }
904 }
905}