Skip to content

fix: BigInt256 modulo must use mathematical mod, not remainder#857

Open
mwaddip wants to merge 1 commit into
ergoplatform:developfrom
mwaddip:fix/bigint-modulo-semantics
Open

fix: BigInt256 modulo must use mathematical mod, not remainder#857
mwaddip wants to merge 1 commit into
ergoplatform:developfrom
mwaddip:fix/bigint-modulo-semantics

Conversation

@mwaddip
Copy link
Copy Markdown

@mwaddip mwaddip commented Apr 11, 2026

BigInt256::checked_rem uses Rust remainder (%) and returns negative values for negative dividends; ErgoScript's % on BigInt maps to java.math.BigInteger.mod(), which is always non-negative. Mainnet block 670,557: byteArrayToBigInt(boxId.slice(0,15)) % 5 returns JVM 2 vs sigma-rust -3.

Fix only affects BigInt256; primitive int types keep remainder semantics — JVM uses % for those too.

ErgoScript's % operator on BigInt maps to Java's BigInteger.mod()
which always returns a non-negative result. sigma-rust was using
checked_rem (Rust remainder semantics) which can return negative
values for negative dividends.

This causes consensus failures on mainnet — e.g. block 670,557
contains a script that checks `byteArrayToBigInt(boxId.slice(0,15)) % 5 == 2`.
The box ID bytes produce a negative BigInt. Java's mod(5) returns 2,
but Rust's rem(5) returns -3, causing the script to evaluate to false.

The JVM sigmastate-interpreter explicitly documents this in
BigIntegerOps.scala:
  "Even though this method is called divisionRemainder, the semantics
   of ErgoTree language requires it to correspond to BigInteger.mod"

Fix: if checked_rem returns a negative result, add the divisor to
make it non-negative. Only affects BigInt256; primitive integer types
correctly use remainder semantics matching the JVM.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant