diff --git a/src/classic/clvm/mod.rs b/src/classic/clvm/mod.rs index 0c54c0087..bb269fa56 100644 --- a/src/classic/clvm/mod.rs +++ b/src/classic/clvm/mod.rs @@ -20,7 +20,7 @@ struct KwAtomPair { version: usize, } -const KW_PAIRS: [KwAtomPair; 46] = [ +const KW_PAIRS: [KwAtomPair; 48] = [ KwAtomPair { v: &[0x01], n: "q", @@ -241,6 +241,16 @@ const KW_PAIRS: [KwAtomPair; 46] = [ n: "bls_verify", version: 1, }, + KwAtomPair { + v: &[0x3c], + n: "modpow", + version: 1, + }, + KwAtomPair { + v: &[0x3d], + n: "%", + version: 1, + }, KwAtomPair { v: &[0x13, 0xd6, 0x1f, 0x00], n: "secp256k1_verify", diff --git a/src/compiler/prims.rs b/src/compiler/prims.rs index 8a30023b2..4b51554c3 100644 --- a/src/compiler/prims.rs +++ b/src/compiler/prims.rs @@ -187,6 +187,14 @@ pub fn prims() -> Vec<(Vec, SExp)> { "bls_verify".as_bytes().to_vec(), SExp::Integer(primloc.clone(), 59_u32.to_bigint().unwrap()), ), + ( + "modpow".as_bytes().to_vec(), + SExp::Integer(primloc.clone(), 60_u32.to_bigint().unwrap()), + ), + ( + "%".as_bytes().to_vec(), + SExp::Integer(primloc.clone(), 61_u32.to_bigint().unwrap()), + ), ( "secp256k1_verify".as_bytes().to_vec(), SExp::Integer(primloc.clone(), 0x13d61f00.to_bigint().unwrap()), diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index 410e4060d..702efd80d 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -2429,6 +2429,50 @@ fn test_assign_cse_tricky_2() { assert_eq!(program, wanted_repr); } +#[test] +fn test_classic_modpow() { + let result = do_basic_brun(&vec![ + "brun".to_string(), + "(modpow (q . 2) (q . 6) (q . 5))".to_string(), + ]); + // 64 % 5 == 4 + assert_eq!(result.trim(), "4"); +} + +#[test] +fn test_classic_mod_op() { + let result = do_basic_brun(&vec![ + "brun".to_string(), + "(% (q . 13) (q . 10))".to_string(), + ]); + // 13 % 10 == 3 + assert_eq!(result.trim(), "3"); +} + +#[test] +fn test_modern_modpow() { + let program = do_basic_run(&vec![ + "run".to_string(), + "(mod (X Y Z) (include *standard-cl-23*) (modpow X Y Z))".to_string(), + ]); + assert_eq!(program.trim(), "(60 2 5 11)"); + let result = do_basic_brun(&vec!["brun".to_string(), program, "(2 7 10)".to_string()]); + // 128 % 10 == 8 + assert_eq!(result.trim(), "8"); +} + +#[test] +fn test_modern_mod_op() { + let program = do_basic_run(&vec![ + "run".to_string(), + "(mod (X Y) (include *standard-cl-23*) (% X Y))".to_string(), + ]); + assert_eq!(program.trim(), "(61 2 5)"); + let result = do_basic_brun(&vec!["brun".to_string(), program, "(137 6)".to_string()]); + // 137 % 6 == 5 + assert_eq!(result.trim(), "5"); +} + #[test] fn test_include_zero_bin() { let program = do_basic_run(&vec![