Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

limit modexp call to 8192 bit inputs #1391

Open
wants to merge 4 commits into
base: zkevm
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 47 additions & 10 deletions core/vm/contracts_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,27 @@ func (c *bigModExp_zkevm) RequiredGas(input []byte) uint64 {
} else {
input = input[:0]
}

// Retrieve the operands and execute the exponentiation
var (
base = new(big.Int).SetBytes(getData(input, 0, baseLen.Uint64()))
exp = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64()))
mod = new(big.Int).SetBytes(getData(input, baseLen.Uint64()+expLen.Uint64(), modLen.Uint64()))
baseBitLen = base.BitLen()
expBitLen = exp.BitLen()
modBitLen = mod.BitLen()
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if modulo size is 0, the precompile returns 0 and it consumes GAS. This case is not handled.
if base size is 0 & modsize < 8192, it should also return 0 and consume GAS. This case is not handled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image These are the revert cases to return a 0 gas so that we don't consume any. Anything else consumes gas as it would normally, unless I'm missing something?

// special revert case for ZK
if baseBitLen == 0 && modBitLen > 8192 {
return 0
}

// limit to 8192 bits for base, exp, and mod in ZK - revert if we go over
if baseBitLen > 8192 || expBitLen > 8192 || modBitLen > 8192 {
return 0
}

// Retrieve the head 32 bytes of exp for the adjusted exponent length
var expHead *big.Int
if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 {
Expand Down Expand Up @@ -373,21 +394,37 @@ func (c *bigModExp_zkevm) Run(input []byte) ([]byte, error) {
} else {
input = input[:0]
}
// Handle a special case when both the base and mod length is zero
if baseLen == 0 && modLen == 0 {
return []byte{}, nil
}

// Retrieve the operands and execute the exponentiation
var (
base = new(big.Int).SetBytes(getData(input, 0, baseLen))
exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
v []byte
base = new(big.Int).SetBytes(getData(input, 0, baseLen))
exp = new(big.Int).SetBytes(getData(input, baseLen, expLen))
mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen))
v []byte
baseBitLen = base.BitLen()
expBitLen = exp.BitLen()
modBitLen = mod.BitLen()
)
switch {
case mod.BitLen() == 0:

if modBitLen == 0 {
// Modulo 0 is undefined, return zero

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment is not right

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed this comment. It was there from the original erigon implementation.

return common.LeftPadBytes([]byte{}, int(modLen)), nil
}

if baseBitLen == 0 {
if modBitLen > 8192 {
return nil, ErrExecutionReverted
} else {
return []byte{}, nil
}
}

// limit to 8192 bits for base, exp, and mod in ZK
if baseBitLen > 8192 || expBitLen > 8192 || modBitLen > 8192 {
return nil, ErrExecutionReverted
}

switch {
case base.Cmp(libcommon.Big1) == 0:
//If base == 1, then we can just return base % mod (if mod >= 1, which it is)
v = base.Mod(base, mod).Bytes()
Expand Down
Loading