Skip to content

Commit

Permalink
Fixes 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Rigidity committed Oct 28, 2024
1 parent d026a1e commit f4ee6b1
Showing 1 changed file with 115 additions and 128 deletions.
243 changes: 115 additions & 128 deletions src/run_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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);
}
}

0 comments on commit f4ee6b1

Please sign in to comment.