diff --git a/nimbus/vm/interpreter/utils/utils_numeric.nim b/nimbus/vm/interpreter/utils/utils_numeric.nim index 8d6fca3ce..3d6af2d63 100644 --- a/nimbus/vm/interpreter/utils/utils_numeric.nim +++ b/nimbus/vm/interpreter/utils/utils_numeric.nim @@ -68,16 +68,35 @@ proc rangeToPadded*[T: StUint](x: openarray[byte], first, last: int, toLen = 0): if toLen > hi-lo+1: var temp: array[N, byte] - temp[0..hi-lo] = x.toOpenArray(lo, hi) + temp[0..hi-lo] = x.toOpenArray(lo, hi) result = T.fromBytesBE( temp, - allowPadding = true + allowPadding = false ) else: result = T.fromBytesBE( x.toOpenArray(lo, hi), allowPadding = true ) + +proc rangeToPadded2*[T: StUint](x: openarray[byte], first, last: int, toLen = 0): T = + ## Convert take a slice of a sequence of bytes interpret it as the big endian + ## representation of an Uint256. Use padding for sequence shorter than 32 bytes + ## including 0-length sequences. + const N = T.bits div 8 + + let lo = max(0, first) + let hi = min(min(x.high, last), (lo+N)-1) + + if not(lo <= hi): + return # 0 + + var temp: array[N, byte] + temp[0..hi-lo] = x.toOpenArray(lo, hi) + result = T.fromBytesBE( + temp.toOpenArray(0, toLen-1), + allowPadding = true + ) # calculates the memory size required for a step func calcMemSize*(offset, length: int): int {.inline.} = diff --git a/nimbus/vm/interpreter_dispatch.nim b/nimbus/vm/interpreter_dispatch.nim index a38e29817..857e400f6 100644 --- a/nimbus/vm/interpreter_dispatch.nim +++ b/nimbus/vm/interpreter_dispatch.nim @@ -323,17 +323,19 @@ proc selectVM(computation: BaseComputation, fork: Fork) {.gcsafe.} = computation.constantinopleVM() proc executeOpcodes(computation: BaseComputation) = - try: - let fork = computation.getFork - if computation.execPrecompiles(fork): - computation.nextProc() - return - computation.selectVM(fork) - except: - let msg = getCurrentExceptionMsg() - computation.setError(&"Opcode Dispatch Error msg={msg}, depth={computation.msg.depth}", true) - computation.nextProc() + let fork = computation.getFork + block: + if computation.execPrecompiles(fork): + break + + try: + computation.selectVM(fork) + except: + let msg = getCurrentExceptionMsg() + computation.setError(&"Opcode Dispatch Error msg={msg}, depth={computation.msg.depth}", true) + + computation.nextProc() if computation.isError(): if computation.tracingEnabled: computation.traceError() debug "executeOpcodes error", msg=computation.error.info diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index b53a64612..1508e6a7b 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -150,11 +150,11 @@ proc modExpInternal(computation: BaseComputation, base_len, exp_len, mod_len: in let adj_exp_len = block: # TODO deal with negative length + let first32 = rawMsg.rangeToPadded2[:Uint256](96 + base_len, 95 + base_len + exp_len, min(exp_len, 32)) if exp_len <= 32: - if exp.isZero(): 0 - else: log2(exp) # highest-bit in exponent + if first32.isZero(): 0 + else: log2(first32) # highest-bit in exponent else: - let first32 = rawMsg.rangeToPadded[:Uint256](96 + base_len, 95 + base_len + exp_len) # TODO: `modexpRandomInput.json` require Uint256 arithmetic for this code below if not first32.isZero: 8 * (exp_len - 32) + first32.log2