diff --git a/src/run_program.rs b/src/run_program.rs index 2a23b531..42772b41 100644 --- a/src/run_program.rs +++ b/src/run_program.rs @@ -1316,12 +1316,12 @@ mod tests { // this program raises an exception if the computed coin ID matches the // expected #[case::coinid("(i (= (coinid (q . 0x1234500000000000000000000000000000000000000000000000000000000000) (q . 0x6789abcdef000000000000000000000000000000000000000000000000000000) (q . 123456789)) (q . 0x69bfe81b052bfc6bd7f3fb9167fec61793175b897c16a35827f947d5cc98e4bd)) (q . 0) (q x))", - (1432, 0, ENABLE_BLS_OPS_OUTSIDE_GUARD), + (1432, 0, 0), "clvm raise")] // also test the opposite. This program is the same as above but it raises // if the coin ID is a mismatch #[case::coinid("(i (= (coinid (q . 0x1234500000000000000000000000000000000000000000000000000000000000) (q . 0x6789abcdef000000000000000000000000000000000000000000000000000000) (q . 123456789)) (q . 0x69bfe81b052bfc6bd7f3fb9167fec61793175b897c16a35827f947d5cc98e4bc)) (q . 0) (q x))", - (1432, 0, ENABLE_BLS_OPS_OUTSIDE_GUARD), + (1432, 0, 0), "")] // modpow #[case::modpow( @@ -1363,155 +1363,142 @@ mod tests { #[case::g2_add("(i (= (g2_add (q . 0x93e12b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8) (q . 0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8)) (q . 0xaa4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c335771638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053)) (q . 0) (q x))", (3981700, 0, 0), "atom is not a G2 point")] + #[case::keccak( + "(i (= (keccak256 (q . \"foobar\")) (q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e)) (q . 0) (q x))", + (1134, 1, ENABLE_KECCAK_OPS_OUTSIDE_GUARD), + "" + )] + #[case::keccak( + "(i (= (keccak256 (q . \"foobar\")) (q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873f)) (q . 0) (q x))", + (1134, 1, ENABLE_KECCAK_OPS_OUTSIDE_GUARD), + "clvm raise" + )] fn test_softfork( #[case] prg: &'static str, #[case] fields: (u64, u8, u32), // cost, enabled, hard_fork_flag #[case] err: &'static str, - #[values(0)] flags: u32, + #[values(0, ENABLE_KECCAK)] flags: u32, #[values(false, true)] mempool: bool, - #[values(0, 1)] test_ext: u8, + #[values(0, 1, 2)] test_ext: u8, ) { let (cost, enabled, hard_fork_flag) = fields; let softfork_prg = format!("(softfork (q . {cost}) (q . {test_ext}) (q . (a {prg} (q . 0))) (q . 0))"); - #[case::keccak( - "(i (= (keccak256 (q . \"foobar\")) (q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e)) (q . 0) (q x))", - (1134, 1, ENABLE_KECCAK_OPS_OUTSIDE_GUARD), - "" -)] - #[case::keccak( - "(i (= (keccak256 (q . \"foobar\")) (q . 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873f)) (q . 0) (q x))", - (1134, 1, ENABLE_KECCAK_OPS_OUTSIDE_GUARD), - "clvm raise" -)] - fn test_softfork( - #[case] prg: &'static str, - #[case] fields: (u64, u8, u32), // cost, enabled, hard_fork_flag - #[case] err: &'static str, - #[values(0, ENABLE_KECCAK)] flags: u32, - #[values(false, true)] mempool: bool, - #[values(0, 1, 2)] test_ext: u8, - ) { - let (cost, enabled, hard_fork_flag) = fields; - let softfork_prg = - format!("(softfork (q . {cost}) (q . {test_ext}) (q . (a {prg} (q . 0))) (q . 0))"); - - let flags = flags | if mempool { NO_UNKNOWN_OPS } else { 0 }; - - // softfork extensions that are enabled - let ext_enabled = match test_ext { - 0 => true, - 1 => (flags & ENABLE_KECCAK) != 0, - _ => false, - }; + let flags = flags | if mempool { NO_UNKNOWN_OPS } else { 0 }; - println!("mempool: {mempool} ext: {test_ext} flags: {flags}"); - let expect_err = match (ext_enabled as u8, (test_ext >= enabled) as u8) { - // the extension we're running has not been activated, and we're not - // running an extension that supports the operator - (0, 0) => { - if mempool { - "unimplemented operator" - } else { - "" - } + // softfork extensions that are enabled + let ext_enabled = match test_ext { + 0 => true, + 1 => (flags & ENABLE_KECCAK) != 0, + _ => false, + }; + + println!("mempool: {mempool} ext: {test_ext} flags: {flags}"); + let expect_err = match (ext_enabled as u8, (test_ext >= enabled) as u8) { + // the extension we're running has not been activated, and we're not + // running an extension that supports the operator + (0, 0) => { + if mempool { + "unimplemented operator" + } else { + "" } - // the softfork extension hasn't been activated yet. It's a failure in - // mempool mode but ignored in consensus mode - (0, 1) => { - if mempool { - "unknown softfork extension" - } else { - "" - } + } + // the softfork extension hasn't been activated yet. It's a failure in + // mempool mode but ignored in consensus mode + (0, 1) => { + if mempool { + "unknown softfork extension" + } else { + "" } - // the extension we're invoking has been enabled, but the operator is - // not part of this extension. In mempool mode it's an error, in - // consensus mode the operator is considered unknown, returning - // NIL/false. This in turn will make the return value test fail, and - // raise an exception. - (1, 0) => { - if mempool { - "unimplemented operator" - } else { - "clvm raise" - } + } + // the extension we're invoking has been enabled, but the operator is + // not part of this extension. In mempool mode it's an error, in + // consensus mode the operator is considered unknown, returning + // NIL/false. This in turn will make the return value test fail, and + // raise an exception. + (1, 0) => { + if mempool { + "unimplemented operator" + } else { + "clvm raise" } - // the extension we're running has been activated, and we're running an - // extension the operator is available in. The program is executed and - // we get the expected result. - (1, 1) => err, - _ => unreachable!(), - }; + } + // the extension we're running has been activated, and we're running an + // extension the operator is available in. The program is executed and + // we get the expected result. + (1, 1) => err, + _ => unreachable!(), + }; - println!("expect: {expect_err} cost: {cost}"); - let t = RunProgramTest { - prg: softfork_prg.as_str(), - args: "()", - flags, - result: if expect_err.is_empty() { - Some("()") - } else { - None - }, - cost: cost + 81, - err: expect_err, - }; + println!("expect: {expect_err} cost: {cost}"); + let t = RunProgramTest { + prg: softfork_prg.as_str(), + args: "()", + flags, + result: if expect_err.is_empty() { + Some("()") + } else { + None + }, + cost: cost + 81, + err: expect_err, + }; - run_test_case(&t); + run_test_case(&t); - // now test outside the guard (should fail unless hard_fork_flag is set). + // now test outside the guard (should fail unless hard_fork_flag is set). - let outside_guard_prg = format!("(a {prg} (q . 0))"); + let outside_guard_prg = format!("(a {prg} (q . 0))"); - // without the hard fork flag - println!("outside guard, no hard fork"); - let t = RunProgramTest { - prg: outside_guard_prg.as_str(), - args: "()", - flags, - result: if err.is_empty() { Some("()") } else { None }, - cost: cost - 140, - err, - }; - run_test_case(&t); - - // with the hard fork flag - println!("outside guard, hard fork activated"); - let t = RunProgramTest { - prg: outside_guard_prg.as_str(), - args: "()", - flags: flags | hard_fork_flag, - result: if err.is_empty() { Some("()") } else { None }, - cost: cost - 140, - err, - }; - run_test_case(&t); - } + // without the hard fork flag + println!("outside guard, no hard fork"); + let t = RunProgramTest { + prg: outside_guard_prg.as_str(), + args: "()", + flags, + result: if err.is_empty() { Some("()") } else { None }, + cost: cost - 140, + err, + }; + run_test_case(&t); - #[cfg(feature = "counters")] - #[test] - fn test_counters() { - use crate::chia_dialect::ChiaDialect; + // with the hard fork flag + println!("outside guard, hard fork activated"); + let t = RunProgramTest { + prg: outside_guard_prg.as_str(), + args: "()", + flags: flags | hard_fork_flag, + result: if err.is_empty() { Some("()") } else { None }, + cost: cost - 140, + err, + }; + run_test_case(&t); + } - let mut a = Allocator::new(); + #[cfg(feature = "counters")] + #[test] + fn test_counters() { + use crate::chia_dialect::ChiaDialect; - let program = check(parse_exp(&mut a, "(a (q 2 2 (c 2 (c 5 (c 11 ())))) (c (q 2 (i (= 11 ()) (q 1 . 1) (q 18 5 (a 2 (c 2 (c 5 (c (- 11 (q . 1)) ())))))) 1) 1))")); - let args = check(parse_exp(&mut a, "(5033 1000)")); - let cost = 15073165; + let mut a = Allocator::new(); - let (counters, result) = - run_program_with_counters(&mut a, &ChiaDialect::new(0), program, args, cost); + let program = check(parse_exp(&mut a, "(a (q 2 2 (c 2 (c 5 (c 11 ())))) (c (q 2 (i (= 11 ()) (q 1 . 1) (q 18 5 (a 2 (c 2 (c 5 (c (- 11 (q . 1)) ())))))) 1) 1))")); + let args = check(parse_exp(&mut a, "(5033 1000)")); + let cost = 15073165; - assert_eq!(counters.val_stack_usage, 3015); - assert_eq!(counters.env_stack_usage, 1005); - assert_eq!(counters.op_stack_usage, 3014); - assert_eq!(counters.atom_count, 998); - assert_eq!(counters.small_atom_count, 1042); - assert_eq!(counters.pair_count, 22077); - assert_eq!(counters.heap_size, 769963); + let (counters, result) = + run_program_with_counters(&mut a, &ChiaDialect::new(0), program, args, cost); - assert_eq!(result.unwrap().0, cost); - } + assert_eq!(counters.val_stack_usage, 3015); + assert_eq!(counters.env_stack_usage, 1005); + assert_eq!(counters.op_stack_usage, 3014); + assert_eq!(counters.atom_count, 998); + assert_eq!(counters.small_atom_count, 1042); + assert_eq!(counters.pair_count, 22077); + assert_eq!(counters.heap_size, 769963); + + assert_eq!(result.unwrap().0, cost); } }