[Bug] CI job failure (test_assert_eq_succeeds)
Detected in https://github.com/AleoHQ/snarkVM/pull/982:
thread 'program::instruction::operation::assert::tests::test_assert_eq_succeeds' panicked at 'assertion failed: `(left == right)`
left: `0`,
right: `1`: Constant constraint failed: (0 * 1) =?= 1', /home/circleci/project/circuit/environment/src/circuit.rs:156:29
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
program::instruction::operation::assert::tests::test_assert_eq_succeeds
@ljedrz I have assigned you to both #985 and #986, as I believe the underlying issue (whatever it may be) is the same under the hood.
I originally wrote that test framework 2 weeks ago and am happy to debug it with you. I believe just updating it to do more iterations will cause it to eventually hit the case. I suggest adding some additional println! statements to catch the exact literal_a, literal_b, mode_a, and mode_b case that causes it to fail.
If you need additional guidance, I'm happy to triage it with you.
Reproducing rng seed (with https://github.com/AleoHQ/snarkVM/pull/999): 1420944100681073831 or 2576108600482558396. There are likely many others.
The Mode (Public or Private) doesn't seem to make a difference.
minified reproducer:
#[test]
fn test_assert_eq_succeeds_minified() {
// Initialize the operation.
let operation = |operands| AssertEq::<CurrentNetwork> { operands };
// Initialize the opcode.
let opcode = AssertEq::<CurrentNetwork>::opcode();
// Prepare the test.
let literal_a = Literal::String(console::types::StringType::new("T0vAPUMXjeh7Gfkj67r5UJTmG7rz44S98owL2jjvAHFKfu"));
let literal_b = Literal::String(console::types::StringType::new("6KridYJbJ"));
check_assert(operation, opcode, &literal_a, &literal_b, &circuit::Mode::Public, &circuit::Mode::Public);
}
I haven't fully confirmed it yet, but it seems that this issue is limited to the String literals; also, it doesn't seem to be related to #985.
The specific point of failure is here (called from here), and the value of input_a.is_equal(&input_b) is false.private (when using the minified reproducer provided earlier).
@ljedrz I've added a little println to those tests in #1007 to help with debugging.
It is very sporadic, but there are some corner cases where I seem to be able to still hit it. Unfortunately, I have not hit it after adding the println however.
What about https://github.com/AleoHQ/snarkVM/issues/986#issuecomment-1227273374? That one should fail every time.
CI came across an error case (now easier to reproduce with the new logging):
Checking 'assert.eq' for '"VP5MvWmcwQcfgUY".public' and '"IprcMHTOjNE7I5yjktaRZ1CMrxMCH9yTfQbJWx7kTquHgWNT".public'
It seems that strings with a length of 0 or 32 and above cause issues, regardless of their contents.
Confirmed; I can't trigger a failure with the following test case:
#[test]
fn test_assert_eq_succeeds_minified() {
// Initialize the operation.
let operation = |operands| AssertEq::<CurrentNetwork> { operands };
// Initialize the opcode.
let opcode = AssertEq::<CurrentNetwork>::opcode();
// Prepare the key cache.
let mut cache = Default::default();
let mut rng = TestRng::default();
use rand::distributions::{Alphanumeric, DistString};
loop {
let len_a = rng.gen_range(1..32);
let len_b = rng.gen_range(1..32);
let literal_a = Literal::String(console::types::StringType::new(&Alphanumeric.sample_string(&mut rng, len_a)));
let literal_b = Literal::String(console::types::StringType::new(&Alphanumeric.sample_string(&mut rng, len_b)));
check_assert(operation, opcode, &literal_a, &literal_b, &circuit::Mode::Public, &circuit::Mode::Public, &mut cache);
}
}
I might be onto something: when inspecting the Equal::is_equal impl for StringType, I noticed that string literals with lengths of 0 and anything other than 0 and ones differing by 32 or more crash the test; in other words:
| literal_a.len() | literal_b.len() | result |
|---|---|---|
| 0 | 0 | pass |
| 0 | not 0 | fail |
| 1 - 31 | 1-31 | pass |
| 1 - 31 | 32 and more | fail |
| 32 - 63 | 32 - 63 | pass |
| 32 - 63 | below 32 or 64 and more | fail |
and so on. As long as the number of underlying fields is the same, the test passes.
Also, the related check doesn't actually compare the lengths of strings, but the underlying fields.
@ljedrz Has this issue been resolved?
I can no longer reproduce the issue with https://github.com/AleoNet/snarkVM/issues/986#issuecomment-1227273374. However, the related PR states that it was only a temporary solution.