parent
f08178c592
commit
72947b3647
|
@ -157,9 +157,9 @@ proc processBeaconBlockRoot*(vmState: BaseVMState, beaconRoot: Hash256):
|
|||
)
|
||||
|
||||
# runComputation a.k.a syscall/evm.call
|
||||
let res = call.runComputation()
|
||||
if res.isError:
|
||||
return err("processBeaconBlockRoot: " & res.error)
|
||||
let res = call.runComputation(string)
|
||||
if res.len > 0:
|
||||
return err("processBeaconBlockRoot: " & res)
|
||||
|
||||
statedb.persist(clearEmptyAccount = true)
|
||||
ok()
|
||||
|
|
|
@ -46,9 +46,9 @@ type
|
|||
StoData ## Slot storage data
|
||||
|
||||
PayloadRef* = ref object of RootRef
|
||||
## The payload type depends on the sub-tree used. The `VertesID(1)` rooted
|
||||
## sub-tree only has `AccountData` type payload, while all other sub-trees
|
||||
## have `RawData` payload.
|
||||
## The payload type depends on the sub-tree used. The `VertexID(1)` rooted
|
||||
## sub-tree only has `AccountData` type payload, stoID-based have StoData
|
||||
## while generic have RawData
|
||||
case pType*: PayloadType
|
||||
of RawData:
|
||||
rawBlob*: Blob ## Opaque data, default value
|
||||
|
|
|
@ -31,15 +31,15 @@ import
|
|||
# ------------------------------------------------------------------------------
|
||||
|
||||
when false:
|
||||
func toError(e: AristoError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||
CoreDbErrorRef(
|
||||
func toError(e: AristoError; s: string; error = Unspecified): CoreDbError =
|
||||
CoreDbError(
|
||||
error: error,
|
||||
ctx: s,
|
||||
isAristo: true,
|
||||
aErr: e)
|
||||
|
||||
func toError(e: KvtError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||
CoreDbErrorRef(
|
||||
func toError(e: KvtError; s: string; error = Unspecified): CoreDbError =
|
||||
CoreDbError(
|
||||
error: error,
|
||||
ctx: s,
|
||||
isAristo: false,
|
||||
|
|
|
@ -25,7 +25,7 @@ export
|
|||
#CoreDbCaptRef,
|
||||
CoreDbCtxRef,
|
||||
CoreDbErrorCode,
|
||||
CoreDbErrorRef,
|
||||
CoreDbError,
|
||||
CoreDbKvtRef,
|
||||
CoreDbMptRef,
|
||||
CoreDbPersistentTypes,
|
||||
|
@ -120,11 +120,11 @@ proc finish*(db: CoreDbRef; eradicate = false) =
|
|||
CoreDbAccRef(db.ctx).call(finish, db.ctx.mpt, eradicate)
|
||||
db.ifTrackNewApi: debug logTxt, api, elapsed
|
||||
|
||||
proc `$$`*(e: CoreDbErrorRef): string =
|
||||
proc `$$`*(e: CoreDbError): string =
|
||||
## Pretty print error symbol, note that this directive may have side effects
|
||||
## as it calls a backend function.
|
||||
##
|
||||
if e.isNil: "$ø" else: e.toStr()
|
||||
e.toStr()
|
||||
|
||||
proc persistent*(
|
||||
db: CoreDbRef;
|
||||
|
|
|
@ -89,7 +89,7 @@ type
|
|||
TxRollbackFn = "rollback"
|
||||
TxSaveDisposeFn = "safeDispose"
|
||||
|
||||
func toStr*(e: CoreDbErrorRef): string {.gcsafe.}
|
||||
func toStr*(e: CoreDbError): string {.gcsafe.}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private helpers
|
||||
|
@ -148,7 +148,7 @@ func toStr(rc: CoreDbRc[CoreDbAccRef]): string = rc.toStr "acc"
|
|||
# Public API logging helpers
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func toStr*(e: CoreDbErrorRef): string =
|
||||
func toStr*(e: CoreDbError): string =
|
||||
result = $e.error & "("
|
||||
result &= (if e.isAristo: "Aristo" else: "Kvt")
|
||||
result &= ", ctx=" & $e.ctx & ", error="
|
||||
|
|
|
@ -36,7 +36,7 @@ type
|
|||
CoreDbProfData* = AristoDbProfData
|
||||
## Borrowed from `aristo_profile`, only used in profiling mode
|
||||
|
||||
CoreDbRc*[T] = Result[T,CoreDbErrorRef]
|
||||
CoreDbRc*[T] = Result[T,CoreDbError]
|
||||
|
||||
CoreDbAccount* = AristoAccount
|
||||
## Generic account record representation. The data fields
|
||||
|
@ -93,14 +93,14 @@ type
|
|||
|
||||
CoreDbMptRef* = distinct CoreDbCtxRef
|
||||
## Generic MPT
|
||||
|
||||
|
||||
CoreDbTxRef* = ref object
|
||||
## Transaction descriptor
|
||||
ctx*: CoreDbCtxRef ## Context (also contains `Aristo` descriptor)
|
||||
aTx*: AristoTxRef ## `Aristo` transaction (if any)
|
||||
kTx*: KvtTxRef ## `KVT` transaction (if any)
|
||||
|
||||
CoreDbErrorRef* = ref object
|
||||
CoreDbError* = object
|
||||
## Generic error object
|
||||
error*: CoreDbErrorCode
|
||||
ctx*: string ## Context where the exception or error occured
|
||||
|
|
|
@ -69,8 +69,8 @@ template call*(kvt: CoreDbKvtRef; fn: untyped; args: varArgs[untyped]): untyped
|
|||
|
||||
# ---------------
|
||||
|
||||
func toError*(e: KvtError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||
CoreDbErrorRef(
|
||||
func toError*(e: KvtError; s: string; error = Unspecified): CoreDbError =
|
||||
CoreDbError(
|
||||
error: error,
|
||||
ctx: s,
|
||||
isAristo: false,
|
||||
|
@ -106,8 +106,8 @@ template call*(
|
|||
|
||||
# ---------------
|
||||
|
||||
func toError*(e: AristoError; s: string; error = Unspecified): CoreDbErrorRef =
|
||||
CoreDbErrorRef(
|
||||
func toError*(e: AristoError; s: string; error = Unspecified): CoreDbError =
|
||||
CoreDbError(
|
||||
error: error,
|
||||
ctx: s,
|
||||
isAristo: true,
|
||||
|
|
|
@ -623,12 +623,11 @@ proc selfDestructLen*(ac: AccountsLedgerRef): int =
|
|||
proc addLogEntry*(ac: AccountsLedgerRef, log: Log) =
|
||||
ac.savePoint.logEntries.add log
|
||||
|
||||
proc logEntries*(ac: AccountsLedgerRef): seq[Log] =
|
||||
proc logEntries*(ac: AccountsLedgerRef): lent seq[Log] =
|
||||
ac.savePoint.logEntries
|
||||
|
||||
proc getAndClearLogEntries*(ac: AccountsLedgerRef): seq[Log] =
|
||||
result = ac.savePoint.logEntries
|
||||
ac.savePoint.logEntries.setLen(0)
|
||||
swap(result, ac.savePoint.logEntries)
|
||||
|
||||
proc ripemdSpecial*(ac: AccountsLedgerRef) =
|
||||
ac.ripemdSpecial = true
|
||||
|
|
|
@ -140,7 +140,7 @@ template getBlobBaseFee*(c: Computation): UInt256 =
|
|||
else:
|
||||
c.vmState.txCtx.blobBaseFee
|
||||
|
||||
proc getBlockHash*(c: Computation, number: BlockNumber): Hash256 {.gcsafe, raises:[].} =
|
||||
proc getBlockHash*(c: Computation, number: BlockNumber): Hash256 =
|
||||
when evmc_enabled:
|
||||
let
|
||||
blockNumber = BlockNumber c.host.getTxContext().block_number
|
||||
|
@ -229,8 +229,8 @@ proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
|
|||
new result
|
||||
result.vmState = vmState
|
||||
result.msg = message
|
||||
result.memory = EvmMemoryRef.new()
|
||||
result.stack = EvmStackRef.new()
|
||||
result.memory = EvmMemory.init()
|
||||
result.stack = EvmStack.init()
|
||||
result.returnStack = @[]
|
||||
result.gasMeter.init(message.gas)
|
||||
result.sysCall = sysCall
|
||||
|
@ -248,8 +248,8 @@ func newComputation*(vmState: BaseVMState, sysCall: bool,
|
|||
new result
|
||||
result.vmState = vmState
|
||||
result.msg = message
|
||||
result.memory = EvmMemoryRef.new()
|
||||
result.stack = EvmStackRef.new()
|
||||
result.memory = EvmMemory.init()
|
||||
result.stack = EvmStack.init()
|
||||
result.returnStack = @[]
|
||||
result.gasMeter.init(message.gas)
|
||||
result.code = CodeStream.init(code)
|
||||
|
@ -418,7 +418,7 @@ proc refundSelfDestruct*(c: Computation) =
|
|||
func tracingEnabled*(c: Computation): bool =
|
||||
c.vmState.tracingEnabled
|
||||
|
||||
func traceOpCodeStarted*(c: Computation, op: Op): int {.raises: [].} =
|
||||
func traceOpCodeStarted*(c: Computation, op: Op): int =
|
||||
c.vmState.captureOpStart(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
|
@ -426,7 +426,7 @@ func traceOpCodeStarted*(c: Computation, op: Op): int {.raises: [].} =
|
|||
c.gasMeter.gasRemaining,
|
||||
c.msg.depth + 1)
|
||||
|
||||
func traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.raises: [].} =
|
||||
func traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) =
|
||||
c.vmState.captureOpEnd(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
|
@ -437,7 +437,7 @@ func traceOpCodeEnded*(c: Computation, op: Op, opIndex: int) {.raises: [].} =
|
|||
c.msg.depth + 1,
|
||||
opIndex)
|
||||
|
||||
func traceError*(c: Computation) {.raises: [].} =
|
||||
func traceError*(c: Computation) =
|
||||
c.vmState.captureFault(
|
||||
c,
|
||||
c.code.pc - 1,
|
||||
|
@ -451,15 +451,15 @@ func traceError*(c: Computation) {.raises: [].} =
|
|||
func prepareTracer*(c: Computation) =
|
||||
c.vmState.capturePrepare(c, c.msg.depth)
|
||||
|
||||
func opcodeGastCost*(
|
||||
c: Computation, op: Op, gasCost: GasInt, reason: string): EvmResultVoid
|
||||
{.raises: [].} =
|
||||
c.vmState.captureGasCost(
|
||||
c,
|
||||
op,
|
||||
gasCost,
|
||||
c.gasMeter.gasRemaining,
|
||||
c.msg.depth + 1)
|
||||
func opcodeGasCost*(
|
||||
c: Computation, op: Op, gasCost: GasInt, reason: static string): EvmResultVoid =
|
||||
if c.vmState.tracingEnabled:
|
||||
c.vmState.captureGasCost(
|
||||
c,
|
||||
op,
|
||||
gasCost,
|
||||
c.gasMeter.gasRemaining,
|
||||
c.msg.depth + 1)
|
||||
c.gasMeter.consumeGas(gasCost, reason)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -19,9 +19,12 @@ func init*(m: var GasMeter, startGas: GasInt) =
|
|||
m.gasRemaining = startGas
|
||||
m.gasRefunded = 0
|
||||
|
||||
func consumeGas*(gasMeter: var GasMeter; amount: GasInt; reason: string): EvmResultVoid =
|
||||
func consumeGas*(
|
||||
gasMeter: var GasMeter; amount: GasInt; reason: static string): EvmResultVoid =
|
||||
# TODO report reason - consumeGas is a hotspot in EVM execution so it has to
|
||||
# be done carefully
|
||||
if amount > gasMeter.gasRemaining:
|
||||
return err(memErr(OutOfGas))
|
||||
return err(gasErr(OutOfGas))
|
||||
gasMeter.gasRemaining -= amount
|
||||
ok()
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ template handleFixedGasCostsDirective(fork: EVMFork; op: Op; k: var VmCtx) =
|
|||
if k.cpt.tracingEnabled:
|
||||
k.cpt.opIndex = k.cpt.traceOpCodeStarted(op)
|
||||
|
||||
? k.cpt.opcodeGastCost(op, k.cpt.gasCosts[op].cost, reason = $op)
|
||||
? k.cpt.opcodeGasCost(op, k.cpt.gasCosts[op].cost, reason = $op)
|
||||
? vmOpHandlers[fork][op].run(k)
|
||||
|
||||
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.
|
||||
|
|
|
@ -139,7 +139,7 @@ proc expOp(k: var VmCtx): EvmResultVoid =
|
|||
## 0x0A, Exponentiation
|
||||
let (base, exponent) = ? k.cpt.stack.popInt(2)
|
||||
|
||||
? k.cpt.opcodeGastCost(Exp,
|
||||
? k.cpt.opcodeGasCost(Exp,
|
||||
k.cpt.gasCosts[Exp].d_handler(exponent),
|
||||
reason = "EXP: exponent bytes")
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ proc callOp(k: var VmCtx): EvmResultVoid =
|
|||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
? cpt.opcodeGastCost(Call, gasCost, reason = $Call)
|
||||
? cpt.opcodeGasCost(Call, gasCost, reason = $Call)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
|
||||
|
@ -297,7 +297,7 @@ proc callCodeOp(k: var VmCtx): EvmResultVoid =
|
|||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
? cpt.opcodeGastCost(CallCode, gasCost, reason = $CallCode)
|
||||
? cpt.opcodeGasCost(CallCode, gasCost, reason = $CallCode)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
|
||||
|
@ -370,7 +370,7 @@ proc delegateCallOp(k: var VmCtx): EvmResultVoid =
|
|||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
? cpt.opcodeGastCost(DelegateCall, gasCost, reason = $DelegateCall)
|
||||
? cpt.opcodeGasCost(DelegateCall, gasCost, reason = $DelegateCall)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
if cpt.msg.depth >= MaxCallDepth:
|
||||
|
@ -437,7 +437,7 @@ proc staticCallOp(k: var VmCtx): EvmResultVoid =
|
|||
memOffset: p.memOffset,
|
||||
memLength: p.memLength))
|
||||
|
||||
? cpt.opcodeGastCost(StaticCall, gasCost, reason = $StaticCall)
|
||||
? cpt.opcodeGasCost(StaticCall, gasCost, reason = $StaticCall)
|
||||
|
||||
cpt.returnData.setLen(0)
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ proc createOp(k: var VmCtx): EvmResultVoid =
|
|||
memLength: memLen)
|
||||
gasCost = cpt.gasCosts[Create].cr_handler(1.u256, gasParams)
|
||||
|
||||
? cpt.opcodeGastCost(Create,
|
||||
? cpt.opcodeGasCost(Create,
|
||||
gasCost, reason = "CREATE: GasCreate + memLen * memory expansion")
|
||||
cpt.memory.extend(memPos, memLen)
|
||||
cpt.returnData.setLen(0)
|
||||
|
@ -192,7 +192,7 @@ proc create2Op(k: var VmCtx): EvmResultVoid =
|
|||
var gasCost = cpt.gasCosts[Create].cr_handler(1.u256, gasParams)
|
||||
gasCost = gasCost + cpt.gasCosts[Create2].m_handler(0, 0, memLen)
|
||||
|
||||
? cpt.opcodeGastCost(Create2,
|
||||
? cpt.opcodeGasCost(Create2,
|
||||
gasCost, reason = "CREATE2: GasCreate + memLen * memory expansion")
|
||||
cpt.memory.extend(memPos, memLen)
|
||||
cpt.returnData.setLen(0)
|
||||
|
|
|
@ -55,7 +55,7 @@ proc balanceEIP2929Op (k: var VmCtx): EvmResultVoid =
|
|||
address = ? cpt.stack.popAddress()
|
||||
gasCost = cpt.gasEip2929AccountCheck(address)
|
||||
|
||||
? cpt.opcodeGastCost(Balance, gasCost, reason = "Balance EIP2929")
|
||||
? cpt.opcodeGasCost(Balance, gasCost, reason = "Balance EIP2929")
|
||||
cpt.stack.push cpt.getBalance(address)
|
||||
|
||||
# ------------------
|
||||
|
@ -106,7 +106,7 @@ proc callDataCopyOp (k: var VmCtx): EvmResultVoid =
|
|||
let (memPos, copyPos, len) =
|
||||
(memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef)
|
||||
|
||||
? k.cpt.opcodeGastCost(CallDataCopy,
|
||||
? k.cpt.opcodeGasCost(CallDataCopy,
|
||||
k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len),
|
||||
reason = "CallDataCopy fee")
|
||||
|
||||
|
@ -130,7 +130,7 @@ proc codeCopyOp (k: var VmCtx): EvmResultVoid =
|
|||
let (memPos, copyPos, len) =
|
||||
(memStartPos.cleanMemRef, copyStartPos.cleanMemRef, size.cleanMemRef)
|
||||
|
||||
? cpt.opcodeGastCost(CodeCopy,
|
||||
? cpt.opcodeGasCost(CodeCopy,
|
||||
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
|
||||
reason = "CodeCopy fee")
|
||||
|
||||
|
@ -158,7 +158,7 @@ proc extCodeSizeEIP2929Op (k: var VmCtx): EvmResultVoid =
|
|||
address = ? cpt.stack.popAddress()
|
||||
gasCost = cpt.gasEip2929AccountCheck(address)
|
||||
|
||||
? cpt.opcodeGastCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
|
||||
? cpt.opcodeGasCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
|
||||
cpt.stack.push cpt.getCodeSize(address)
|
||||
|
||||
# -----------
|
||||
|
@ -172,7 +172,7 @@ proc extCodeCopyOp (k: var VmCtx): EvmResultVoid =
|
|||
(memPos, codePos, len) =
|
||||
(memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef)
|
||||
|
||||
? cpt.opcodeGastCost(ExtCodeCopy,
|
||||
? cpt.opcodeGasCost(ExtCodeCopy,
|
||||
cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len),
|
||||
reason = "ExtCodeCopy fee")
|
||||
|
||||
|
@ -192,7 +192,7 @@ proc extCodeCopyEIP2929Op (k: var VmCtx): EvmResultVoid =
|
|||
|
||||
gasCost = cpt.gasCosts[ExtCodeCopy].m_handler(cpt.memory.len, memPos, len) +
|
||||
cpt.gasEip2929AccountCheck(address)
|
||||
? cpt.opcodeGastCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
|
||||
? cpt.opcodeGasCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
|
||||
|
||||
let code = cpt.getCode(address)
|
||||
cpt.memory.writePadded(code.bytes(), memPos, codePos, len)
|
||||
|
@ -215,7 +215,7 @@ proc returnDataCopyOp (k: var VmCtx): EvmResultVoid =
|
|||
gasCost = k.cpt.gasCosts[ReturnDataCopy].m_handler(
|
||||
k.cpt.memory.len, memPos, len)
|
||||
|
||||
? k.cpt.opcodeGastCost(ReturnDataCopy, gasCost, reason = "returnDataCopy fee")
|
||||
? k.cpt.opcodeGasCost(ReturnDataCopy, gasCost, reason = "returnDataCopy fee")
|
||||
|
||||
if copyPos + len > k.cpt.returnData.len:
|
||||
return err(opErr(OutOfBounds))
|
||||
|
@ -239,7 +239,7 @@ proc extCodeHashEIP2929Op (k: var VmCtx): EvmResultVoid =
|
|||
address = ? k.cpt.stack.popAddress()
|
||||
gasCost = cpt.gasEip2929AccountCheck(address)
|
||||
|
||||
? cpt.opcodeGastCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
|
||||
? cpt.opcodeGasCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
|
||||
cpt.stack.push cpt.getCodeHash(address)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -39,7 +39,7 @@ proc sha3Op(k: var VmCtx): EvmResultVoid =
|
|||
if pos < 0 or len < 0 or pos > 2147483648'i64:
|
||||
return err(opErr(OutOfBounds))
|
||||
|
||||
? k.cpt.opcodeGastCost(Op.Sha3,
|
||||
? k.cpt.opcodeGasCost(Op.Sha3,
|
||||
k.cpt.gasCosts[Op.Sha3].m_handler(k.cpt.memory.len, pos, len),
|
||||
reason = "SHA3: word gas cost")
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ proc logImpl(c: Computation, opcode: Op, topicCount: static int): EvmResultVoid
|
|||
if memPos < 0 or len < 0:
|
||||
return err(opErr(OutOfBounds))
|
||||
|
||||
? c.opcodeGastCost(opcode,
|
||||
? c.opcodeGasCost(opcode,
|
||||
c.gasCosts[opcode].m_handler(c.memory.len, memPos, len),
|
||||
reason = "Memory expansion, Log topic and data gas cost")
|
||||
c.memory.extend(memPos, len)
|
||||
|
|
|
@ -49,7 +49,7 @@ when evmc_enabled:
|
|||
res = ForkToSstoreCost[c.fork][status]
|
||||
gasCost = res.gasCost.GasInt + coldAccess
|
||||
|
||||
? c.opcodeGastCost(Sstore, gasCost, "SSTORE")
|
||||
? c.opcodeGasCost(Sstore, gasCost, "SSTORE")
|
||||
c.gasMeter.refundGas(res.gasRefund)
|
||||
ok()
|
||||
|
||||
|
@ -61,7 +61,7 @@ else:
|
|||
currentValue: currentValue)
|
||||
res = c.gasCosts[Sstore].ss_handler(newValue, gasParam)
|
||||
|
||||
? c.opcodeGastCost(Sstore, res.gasCost, "SSTORE")
|
||||
? c.opcodeGasCost(Sstore, res.gasCost, "SSTORE")
|
||||
c.gasMeter.refundGas(res.gasRefund)
|
||||
|
||||
c.vmState.mutateStateDB:
|
||||
|
@ -80,7 +80,7 @@ else:
|
|||
|
||||
res = c.gasCosts[Sstore].ss_handler(newValue, gasParam)
|
||||
|
||||
? c.opcodeGastCost(Sstore, res.gasCost + coldAccess, "SSTORE")
|
||||
? c.opcodeGasCost(Sstore, res.gasCost + coldAccess, "SSTORE")
|
||||
|
||||
c.gasMeter.refundGas(res.gasRefund)
|
||||
|
||||
|
@ -132,7 +132,7 @@ proc mloadOp (k: var VmCtx): EvmResultVoid =
|
|||
let memStartPos = ? k.cpt.stack.popInt()
|
||||
|
||||
let memPos = memStartPos.cleanMemRef
|
||||
? k.cpt.opcodeGastCost(Mload,
|
||||
? k.cpt.opcodeGasCost(Mload,
|
||||
k.cpt.gasCosts[Mload].m_handler(k.cpt.memory.len, memPos, 32),
|
||||
reason = "MLOAD: GasVeryLow + memory expansion")
|
||||
|
||||
|
@ -145,7 +145,7 @@ proc mstoreOp (k: var VmCtx): EvmResultVoid =
|
|||
let (memStartPos, value) = ? k.cpt.stack.popInt(2)
|
||||
|
||||
let memPos = memStartPos.cleanMemRef
|
||||
? k.cpt.opcodeGastCost(Mstore,
|
||||
? k.cpt.opcodeGasCost(Mstore,
|
||||
k.cpt.gasCosts[Mstore].m_handler(k.cpt.memory.len, memPos, 32),
|
||||
reason = "MSTORE: GasVeryLow + memory expansion")
|
||||
|
||||
|
@ -158,7 +158,7 @@ proc mstore8Op (k: var VmCtx): EvmResultVoid =
|
|||
let (memStartPos, value) = ? k.cpt.stack.popInt(2)
|
||||
|
||||
let memPos = memStartPos.cleanMemRef
|
||||
? k.cpt.opcodeGastCost(Mstore8,
|
||||
? k.cpt.opcodeGasCost(Mstore8,
|
||||
k.cpt.gasCosts[Mstore8].m_handler(k.cpt.memory.len, memPos, 1),
|
||||
reason = "MSTORE8: GasVeryLow + memory expansion")
|
||||
|
||||
|
@ -181,7 +181,7 @@ proc sloadEIP2929Op (k: var VmCtx): EvmResultVoid =
|
|||
cpt = k.cpt
|
||||
slot = ? cpt.stack.popInt()
|
||||
gasCost = cpt.gasEip2929AccountCheck(cpt.msg.contractAddress, slot)
|
||||
? cpt.opcodeGastCost(Sload, gasCost, reason = "sloadEIP2929")
|
||||
? cpt.opcodeGasCost(Sload, gasCost, reason = "sloadEIP2929")
|
||||
cpt.stack.push cpt.getStorage(slot)
|
||||
|
||||
# -------
|
||||
|
@ -305,7 +305,7 @@ proc mCopyOp (k: var VmCtx): EvmResultVoid =
|
|||
let (dstPos, srcPos, len) =
|
||||
(dst.cleanMemRef, src.cleanMemRef, size.cleanMemRef)
|
||||
|
||||
? k.cpt.opcodeGastCost(Mcopy,
|
||||
? k.cpt.opcodeGasCost(Mcopy,
|
||||
k.cpt.gasCosts[Mcopy].m_handler(k.cpt.memory.len, max(dstPos, srcPos), len),
|
||||
reason = "Mcopy fee")
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ proc returnOp(k: var VmCtx): EvmResultVoid =
|
|||
let (startPos, size) = ? k.cpt.stack.popInt(2)
|
||||
|
||||
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
||||
? k.cpt.opcodeGastCost(Return,
|
||||
? k.cpt.opcodeGasCost(Return,
|
||||
k.cpt.gasCosts[Return].m_handler(k.cpt.memory.len, pos, len),
|
||||
reason = "RETURN")
|
||||
k.cpt.memory.extend(pos, len)
|
||||
|
@ -57,7 +57,7 @@ proc revertOp(k: var VmCtx): EvmResultVoid =
|
|||
let (startPos, size) = ? k.cpt.stack.popInt(2)
|
||||
|
||||
let (pos, len) = (startPos.cleanMemRef, size.cleanMemRef)
|
||||
? k.cpt.opcodeGastCost(Revert,
|
||||
? k.cpt.opcodeGasCost(Revert,
|
||||
k.cpt.gasCosts[Revert].m_handler(k.cpt.memory.len, pos, len),
|
||||
reason = "REVERT")
|
||||
|
||||
|
@ -92,7 +92,7 @@ proc selfDestructEIP150Op(k: var VmCtx): EvmResultVoid =
|
|||
condition = not cpt.accountExists(beneficiary)
|
||||
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
||||
|
||||
? cpt.opcodeGastCost(SelfDestruct,
|
||||
? cpt.opcodeGasCost(SelfDestruct,
|
||||
gasCost, reason = "SELFDESTRUCT EIP150")
|
||||
cpt.selfDestruct(beneficiary)
|
||||
ok()
|
||||
|
@ -109,7 +109,7 @@ proc selfDestructEIP161Op(k: var VmCtx): EvmResultVoid =
|
|||
condition = isDead and not balance.isZero
|
||||
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
||||
|
||||
? cpt.opcodeGastCost(SelfDestruct,
|
||||
? cpt.opcodeGasCost(SelfDestruct,
|
||||
gasCost, reason = "SELFDESTRUCT EIP161")
|
||||
cpt.selfDestruct(beneficiary)
|
||||
ok()
|
||||
|
@ -137,7 +137,7 @@ proc selfDestructEIP2929Op(k: var VmCtx): EvmResultVoid =
|
|||
db.accessList(beneficiary)
|
||||
gasCost = gasCost + ColdAccountAccessCost
|
||||
|
||||
? cpt.opcodeGastCost(SelfDestruct,
|
||||
? cpt.opcodeGasCost(SelfDestruct,
|
||||
gasCost, reason = "SELFDESTRUCT EIP2929")
|
||||
cpt.selfDestruct(beneficiary)
|
||||
ok()
|
||||
|
|
|
@ -16,16 +16,18 @@ import
|
|||
./interpreter/utils/utils_numeric
|
||||
|
||||
type
|
||||
EvmMemoryRef* = ref object
|
||||
EvmMemory* = object
|
||||
bytes*: seq[byte]
|
||||
|
||||
func new*(_: type EvmMemoryRef): EvmMemoryRef =
|
||||
new(result)
|
||||
func init*(_: type EvmMemory): EvmMemory =
|
||||
EvmMemory(
|
||||
bytes: newSeqOfCap[byte](1024)
|
||||
)
|
||||
|
||||
func len*(memory: EvmMemoryRef): int =
|
||||
func len*(memory: EvmMemory): int =
|
||||
memory.bytes.len
|
||||
|
||||
func extend*(memory: EvmMemoryRef; startPos, size: int) =
|
||||
func extend*(memory: var EvmMemory; startPos, size: int) =
|
||||
if size <= 0:
|
||||
return
|
||||
let newSize = ceil32(startPos + size)
|
||||
|
@ -33,22 +35,22 @@ func extend*(memory: EvmMemoryRef; startPos, size: int) =
|
|||
return
|
||||
memory.bytes.setLen(newSize)
|
||||
|
||||
func new*(_: type EvmMemoryRef, size: Natural): EvmMemoryRef =
|
||||
result = EvmMemoryRef.new()
|
||||
func init*(_: type EvmMemory, size: Natural): EvmMemory =
|
||||
result = EvmMemory.init()
|
||||
result.extend(0, size)
|
||||
|
||||
template read*(memory: EvmMemoryRef, startPos, size: int): openArray[byte] =
|
||||
template read*(memory: EvmMemory, startPos, size: int): openArray[byte] =
|
||||
memory.bytes.toOpenArray(startPos, startPos + size - 1)
|
||||
|
||||
template read32Bytes*(memory: EvmMemoryRef, startPos: int): openArray[byte] =
|
||||
template read32Bytes*(memory: EvmMemory, startPos: int): openArray[byte] =
|
||||
memory.bytes.toOpenArray(startPos, startPos + 31)
|
||||
|
||||
when defined(evmc_enabled):
|
||||
func readPtr*(memory: EvmMemoryRef, startPos: Natural): ptr byte =
|
||||
func readPtr*(memory: EvmMemory, startPos: Natural): ptr byte =
|
||||
if memory.bytes.len == 0 or startPos >= memory.bytes.len: return
|
||||
result = memory.bytes[startPos].addr
|
||||
|
||||
func write*(memory: EvmMemoryRef, startPos: Natural, value: openArray[byte]): EvmResultVoid =
|
||||
func write*(memory: var EvmMemory, startPos: Natural, value: openArray[byte]): EvmResultVoid =
|
||||
let size = value.len
|
||||
if size == 0:
|
||||
return
|
||||
|
@ -58,13 +60,13 @@ func write*(memory: EvmMemoryRef, startPos: Natural, value: openArray[byte]): Ev
|
|||
assign(memory.bytes.toOpenArray(startPos, int(startPos + size) - 1), value)
|
||||
ok()
|
||||
|
||||
func write*(memory: EvmMemoryRef, startPos: Natural, value: byte): EvmResultVoid =
|
||||
func write*(memory: var EvmMemory, startPos: Natural, value: byte): EvmResultVoid =
|
||||
if startPos + 1 > memory.len:
|
||||
return err(memErr(MemoryFull))
|
||||
memory.bytes[startPos] = value
|
||||
ok()
|
||||
|
||||
func copy*(memory: EvmMemoryRef, dst, src, len: Natural) =
|
||||
func copy*(memory: var EvmMemory, dst, src, len: Natural) =
|
||||
if len <= 0: return
|
||||
memory.extend(max(dst, src), len)
|
||||
if dst == src:
|
||||
|
@ -73,7 +75,7 @@ func copy*(memory: EvmMemoryRef, dst, src, len: Natural) =
|
|||
memory.bytes.toOpenArray(dst, dst + len - 1),
|
||||
memory.bytes.toOpenArray(src, src + len - 1))
|
||||
|
||||
func writePadded*(memory: EvmMemoryRef, data: openArray[byte],
|
||||
func writePadded*(memory: var EvmMemory, data: openArray[byte],
|
||||
memPos, dataPos, len: Natural) =
|
||||
|
||||
memory.extend(memPos, len)
|
||||
|
|
|
@ -12,19 +12,20 @@
|
|||
|
||||
import
|
||||
std/[macros],
|
||||
stew/assign2,
|
||||
eth/common,
|
||||
./evm_errors,
|
||||
./interpreter/utils/utils_numeric
|
||||
|
||||
type
|
||||
EvmStackRef* = ref object
|
||||
EvmStack* = ref object
|
||||
values: seq[EvmStackElement]
|
||||
|
||||
EvmStackElement = UInt256
|
||||
EvmStackInts = uint64 | uint | int | GasInt
|
||||
EvmStackBytes32 = array[32, byte]
|
||||
|
||||
func len*(stack: EvmStackRef): int {.inline.} =
|
||||
func len*(stack: EvmStack): int {.inline.} =
|
||||
len(stack.values)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -51,7 +52,7 @@ template fromStackElem(elem: EvmStackElement, _: type UInt256): UInt256 =
|
|||
elem
|
||||
|
||||
func fromStackElem(elem: EvmStackElement, _: type EthAddress): EthAddress =
|
||||
result[0 .. ^1] = elem.toBytesBE().toOpenArray(12, 31)
|
||||
assign(result, elem.toBytesBE().toOpenArray(12, 31))
|
||||
|
||||
template fromStackElem(elem: EvmStackElement, _: type Hash256): Hash256 =
|
||||
Hash256(data: elem.toBytesBE())
|
||||
|
@ -59,24 +60,24 @@ template fromStackElem(elem: EvmStackElement, _: type Hash256): Hash256 =
|
|||
template fromStackElem(elem: EvmStackElement, _: type EvmStackBytes32): EvmStackBytes32 =
|
||||
elem.toBytesBE()
|
||||
|
||||
func pushAux[T](stack: EvmStackRef, value: T): EvmResultVoid =
|
||||
func pushAux[T](stack: var EvmStack, value: T): EvmResultVoid =
|
||||
if len(stack.values) > 1023:
|
||||
return err(stackErr(StackFull))
|
||||
stack.values.setLen(stack.values.len + 1)
|
||||
toStackElem(value, stack.values[^1])
|
||||
ok()
|
||||
|
||||
func ensurePop(stack: EvmStackRef, expected: int): EvmResultVoid =
|
||||
func ensurePop(stack: EvmStack, expected: int): EvmResultVoid =
|
||||
if stack.values.len < expected:
|
||||
return err(stackErr(StackInsufficient))
|
||||
ok()
|
||||
|
||||
func popAux(stack: EvmStackRef, T: type): EvmResult[T] =
|
||||
func popAux(stack: var EvmStack, T: type): EvmResult[T] =
|
||||
? ensurePop(stack, 1)
|
||||
result = ok(fromStackElem(stack.values[^1], T))
|
||||
stack.values.setLen(stack.values.len - 1)
|
||||
|
||||
func internalPopTuple(stack: EvmStackRef, T: type, tupleLen: static[int]): EvmResult[T] =
|
||||
func internalPopTuple(stack: var EvmStack, T: type, tupleLen: static[int]): EvmResult[T] =
|
||||
? ensurePop(stack, tupleLen)
|
||||
var
|
||||
i = 0
|
||||
|
@ -96,41 +97,42 @@ macro genTupleType(len: static[int], elemType: untyped): untyped =
|
|||
# Public functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func push*(stack: EvmStackRef,
|
||||
func push*(stack: var EvmStack,
|
||||
value: EvmStackInts | UInt256 | EthAddress | Hash256): EvmResultVoid =
|
||||
pushAux(stack, value)
|
||||
|
||||
func push*(stack: EvmStackRef, value: openArray[byte]): EvmResultVoid =
|
||||
func push*(stack: var EvmStack, value: openArray[byte]): EvmResultVoid =
|
||||
pushAux(stack, value)
|
||||
|
||||
func popInt*(stack: EvmStackRef): EvmResult[UInt256] =
|
||||
func popInt*(stack: var EvmStack): EvmResult[UInt256] =
|
||||
popAux(stack, UInt256)
|
||||
|
||||
func popSafeInt*(stack: EvmStackRef): EvmResult[int] =
|
||||
func popSafeInt*(stack: var EvmStack): EvmResult[int] =
|
||||
? ensurePop(stack, 1)
|
||||
result = ok(fromStackElem(stack.values[^1], UInt256).safeInt)
|
||||
stack.values.setLen(stack.values.len - 1)
|
||||
|
||||
func popMemRef*(stack: EvmStackRef): EvmResult[int] =
|
||||
func popMemRef*(stack: var EvmStack): EvmResult[int] =
|
||||
? ensurePop(stack, 1)
|
||||
result = ok(fromStackElem(stack.values[^1], UInt256).cleanMemRef)
|
||||
stack.values.setLen(stack.values.len - 1)
|
||||
|
||||
func popInt*(stack: EvmStackRef, numItems: static[int]): auto =
|
||||
func popInt*(stack: var EvmStack, numItems: static[int]): auto =
|
||||
type T = genTupleType(numItems, UInt256)
|
||||
stack.internalPopTuple(T, numItems)
|
||||
|
||||
func popAddress*(stack: EvmStackRef): EvmResult[EthAddress] =
|
||||
func popAddress*(stack: var EvmStack): EvmResult[EthAddress] =
|
||||
popAux(stack, EthAddress)
|
||||
|
||||
func popTopic*(stack: EvmStackRef): EvmResult[EvmStackBytes32] =
|
||||
func popTopic*(stack: var EvmStack): EvmResult[EvmStackBytes32] =
|
||||
popAux(stack, EvmStackBytes32)
|
||||
|
||||
func new*(_: type EvmStackRef): EvmStackRef =
|
||||
new(result)
|
||||
result.values = @[]
|
||||
func init*(_: type EvmStack): EvmStack =
|
||||
EvmStack(
|
||||
values: newSeqOfCap[EvmStackElement](128)
|
||||
)
|
||||
|
||||
func swap*(stack: EvmStackRef, position: int): EvmResultVoid =
|
||||
func swap*(stack: var EvmStack, position: int): EvmResultVoid =
|
||||
## Perform a SWAP operation on the stack
|
||||
let idx = position + 1
|
||||
if idx < stack.values.len + 1:
|
||||
|
@ -139,46 +141,46 @@ func swap*(stack: EvmStackRef, position: int): EvmResultVoid =
|
|||
else:
|
||||
err(stackErr(StackInsufficient))
|
||||
|
||||
func dup*(stack: EvmStackRef, position: int): EvmResultVoid =
|
||||
func dup*(stack: var EvmStack, position: int): EvmResultVoid =
|
||||
## Perform a DUP operation on the stack
|
||||
if position in 1 .. stack.len:
|
||||
stack.push(stack.values[^position])
|
||||
else:
|
||||
err(stackErr(StackInsufficient))
|
||||
|
||||
func peek*(stack: EvmStackRef): EvmResult[UInt256] =
|
||||
func peek*(stack: EvmStack): EvmResult[UInt256] =
|
||||
if stack.values.len == 0:
|
||||
return err(stackErr(StackInsufficient))
|
||||
ok(fromStackElem(stack.values[^1], UInt256))
|
||||
|
||||
func peekSafeInt*(stack: EvmStackRef): EvmResult[int] =
|
||||
func peekSafeInt*(stack: EvmStack): EvmResult[int] =
|
||||
if stack.values.len == 0:
|
||||
return err(stackErr(StackInsufficient))
|
||||
ok(fromStackElem(stack.values[^1], UInt256).safeInt)
|
||||
|
||||
func `[]`*(stack: EvmStackRef, i: BackwardsIndex, T: typedesc): EvmResult[T] =
|
||||
func `[]`*(stack: EvmStack, i: BackwardsIndex, T: typedesc): EvmResult[T] =
|
||||
? ensurePop(stack, int(i))
|
||||
ok(fromStackElem(stack.values[i], T))
|
||||
|
||||
func peekInt*(stack: EvmStackRef): EvmResult[UInt256] =
|
||||
func peekInt*(stack: EvmStack): EvmResult[UInt256] =
|
||||
? ensurePop(stack, 1)
|
||||
ok(fromStackElem(stack.values[^1], Uint256))
|
||||
|
||||
func peekAddress*(stack: EvmStackRef): EvmResult[EthAddress] =
|
||||
func peekAddress*(stack: EvmStack): EvmResult[EthAddress] =
|
||||
? ensurePop(stack, 1)
|
||||
ok(fromStackElem(stack.values[^1], EthAddress))
|
||||
|
||||
func top*(stack: EvmStackRef,
|
||||
func top*(stack: EvmStack,
|
||||
value: EvmStackInts | UInt256 | EthAddress | Hash256): EvmResultVoid =
|
||||
if stack.values.len == 0:
|
||||
return err(stackErr(StackInsufficient))
|
||||
toStackElem(value, stack.values[^1])
|
||||
ok()
|
||||
|
||||
iterator items*(stack: EvmStackRef): UInt256 =
|
||||
iterator items*(stack: EvmStack): UInt256 =
|
||||
for v in stack.values:
|
||||
yield v
|
||||
|
||||
iterator pairs*(stack: EvmStackRef): (int, UInt256) =
|
||||
iterator pairs*(stack: EvmStack): (int, UInt256) =
|
||||
for i, v in stack.values:
|
||||
yield (i, v)
|
||||
|
|
|
@ -326,9 +326,8 @@ proc captureGasCost*(vmState: BaseVMState,
|
|||
comp: Computation,
|
||||
op: Op, gasCost: GasInt, gasRemaining: GasInt,
|
||||
depth: int) =
|
||||
if vmState.tracingEnabled:
|
||||
let fixed = vmState.gasCosts[op].kind == GckFixed
|
||||
vmState.tracer.captureGasCost(comp, fixed, op, gasCost, gasRemaining, depth)
|
||||
let fixed = vmState.gasCosts[op].kind == GckFixed
|
||||
vmState.tracer.captureGasCost(comp, fixed, op, gasCost, gasRemaining, depth)
|
||||
|
||||
proc captureOpEnd*(vmState: BaseVMState, comp: Computation, pc: int,
|
||||
op: Op, gas: GasInt, refund: int64,
|
||||
|
|
|
@ -72,8 +72,8 @@ type
|
|||
# The execution computation
|
||||
vmState*: BaseVMState
|
||||
msg*: Message
|
||||
memory*: EvmMemoryRef
|
||||
stack*: EvmStackRef
|
||||
memory*: EvmMemory
|
||||
stack*: EvmStack
|
||||
returnStack*: seq[int]
|
||||
gasMeter*: GasMeter
|
||||
code*: CodeStream
|
||||
|
@ -96,7 +96,7 @@ type
|
|||
evmcStatus*: evmc_status_code
|
||||
info* : string
|
||||
burnsGas* : bool
|
||||
|
||||
|
||||
GasMeter* = object
|
||||
gasRefunded*: int64
|
||||
gasRemaining*: GasInt
|
||||
|
@ -124,7 +124,7 @@ type
|
|||
DisableStateDiff
|
||||
EnableAccount
|
||||
DisableReturnData
|
||||
|
||||
|
||||
TracerRef* = ref object of RootObj
|
||||
flags*: set[TracerFlags]
|
||||
|
||||
|
|
|
@ -57,9 +57,8 @@ type
|
|||
gasUsed*: GasInt # Gas used by the call.
|
||||
contractAddress*: EthAddress # Created account (when `isCreate`).
|
||||
output*: seq[byte] # Output data.
|
||||
logEntries*: seq[Log] # Output logs.
|
||||
stack*: EvmStackRef # EVM stack on return (for test only).
|
||||
memory*: EvmMemoryRef # EVM memory on return (for test only).
|
||||
stack*: EvmStack # EVM stack on return (for test only).
|
||||
memory*: EvmMemory # EVM memory on return (for test only).
|
||||
|
||||
func isError*(cr: CallResult): bool =
|
||||
cr.error.len > 0
|
||||
|
@ -276,7 +275,8 @@ proc calculateAndPossiblyRefundGas(host: TransactionHost, call: CallParams): Gas
|
|||
host.vmState.mutateStateDB:
|
||||
db.addBalance(call.sender, result.u256 * call.gasPrice.u256)
|
||||
|
||||
proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResult =
|
||||
proc finishRunningComputation(
|
||||
host: TransactionHost, call: CallParams, T: type): T =
|
||||
let c = host.computation
|
||||
|
||||
let gasRemaining = calculateAndPossiblyRefundGas(host, call)
|
||||
|
@ -284,17 +284,26 @@ proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResu
|
|||
let gasUsed = host.msg.gas.GasInt - gasRemaining
|
||||
host.vmState.captureEnd(c, c.output, gasUsed, c.errorOpt)
|
||||
|
||||
if c.isError:
|
||||
result.error = c.error.info
|
||||
result.gasUsed = call.gasLimit - gasRemaining
|
||||
result.output = system.move(c.output)
|
||||
result.contractAddress = if call.isCreate: c.msg.contractAddress
|
||||
else: default(HostAddress)
|
||||
result.logEntries = host.vmState.stateDB.logEntries()
|
||||
result.stack = c.stack
|
||||
result.memory = c.memory
|
||||
when T is CallResult:
|
||||
# Collecting the result can be unnecessarily expensive when (re)-processing
|
||||
# transactions
|
||||
if c.isError:
|
||||
result.error = c.error.info
|
||||
result.gasUsed = call.gasLimit - gasRemaining
|
||||
result.output = system.move(c.output)
|
||||
result.contractAddress = if call.isCreate: c.msg.contractAddress
|
||||
else: default(HostAddress)
|
||||
result.stack = move(c.stack)
|
||||
result.memory = move(c.memory)
|
||||
elif T is GasInt:
|
||||
result = call.gasLimit - gasRemaining
|
||||
elif T is string:
|
||||
if c.isError:
|
||||
result = c.error.info
|
||||
else:
|
||||
{.error: "Unknown computation output".}
|
||||
|
||||
proc runComputation*(call: CallParams): CallResult =
|
||||
proc runComputation*(call: CallParams, T: type): T =
|
||||
let host = setupHost(call)
|
||||
prepareToRunComputation(host, call)
|
||||
|
||||
|
@ -306,4 +315,4 @@ proc runComputation*(call: CallParams): CallResult =
|
|||
else:
|
||||
execComputation(host.computation)
|
||||
|
||||
finishRunningComputation(host, call)
|
||||
finishRunningComputation(host, call, T)
|
||||
|
|
|
@ -38,7 +38,7 @@ proc rpcCallEvm*(args: TransactionArgs,
|
|||
var dbTx = com.db.ctx.newTransaction()
|
||||
defer: dbTx.dispose() # always dispose state changes
|
||||
|
||||
ok(runComputation(params))
|
||||
ok(runComputation(params, CallResult))
|
||||
|
||||
proc rpcCallEvm*(args: TransactionArgs,
|
||||
header: common.BlockHeader,
|
||||
|
@ -50,7 +50,7 @@ proc rpcCallEvm*(args: TransactionArgs,
|
|||
var dbTx = com.db.ctx.newTransaction()
|
||||
defer: dbTx.dispose() # always dispose state changes
|
||||
|
||||
ok(runComputation(params))
|
||||
ok(runComputation(params, CallResult))
|
||||
|
||||
proc rpcEstimateGas*(args: TransactionArgs,
|
||||
header: common.BlockHeader,
|
||||
|
@ -125,8 +125,8 @@ proc rpcEstimateGas*(args: TransactionArgs,
|
|||
|
||||
params.gasLimit = gasLimit
|
||||
# TODO: bail out on consensus error similar to validateTransaction
|
||||
let res = runComputation(params)
|
||||
ok(res.isError)
|
||||
let res = runComputation(params, string)
|
||||
ok(res.len > 0)
|
||||
|
||||
# Execute the binary search and hone in on an executable gas limit
|
||||
while lo+1 < hi:
|
||||
|
@ -191,11 +191,10 @@ proc txCallEvm*(tx: Transaction,
|
|||
vmState: BaseVMState): GasInt =
|
||||
let
|
||||
call = callParamsForTx(tx, sender, vmState)
|
||||
res = runComputation(call)
|
||||
res.gasUsed
|
||||
runComputation(call, GasInt)
|
||||
|
||||
proc testCallEvm*(tx: Transaction,
|
||||
sender: EthAddress,
|
||||
vmState: BaseVMState): CallResult =
|
||||
let call = callParamsForTest(tx, sender, vmState)
|
||||
runComputation(call)
|
||||
runComputation(call, CallResult)
|
||||
|
|
|
@ -25,8 +25,8 @@ import
|
|||
../nimbus/transaction/call_evm
|
||||
|
||||
template testPush(value: untyped, expected: untyped): untyped =
|
||||
privateAccess(EvmStackRef)
|
||||
var stack = EvmStackRef.new()
|
||||
privateAccess(EvmStack)
|
||||
var stack = EvmStack.init()
|
||||
check stack.push(value).isOk
|
||||
check(stack.values == @[expected])
|
||||
|
||||
|
@ -44,14 +44,14 @@ proc runStackTests() =
|
|||
testPush("ves".toBytes, "ves".toBytes.bigEndianToInt)
|
||||
|
||||
test "push does not allow stack to exceed 1024":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
for z in 0 ..< 1024:
|
||||
check stack.push(z.uint).isOk
|
||||
check(stack.len == 1024)
|
||||
check stack.push(1025).error.code == EvmErrorCode.StackFull
|
||||
|
||||
test "dup does not allow stack to exceed 1024":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
check stack.push(1.u256).isOk
|
||||
for z in 0 ..< 1023:
|
||||
check stack.dup(1).isOk
|
||||
|
@ -59,14 +59,14 @@ proc runStackTests() =
|
|||
check stack.dup(1).error.code == EvmErrorCode.StackFull
|
||||
|
||||
test "pop returns latest stack item":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
for element in @[1'u, 2'u, 3'u]:
|
||||
check stack.push(element).isOk
|
||||
check(stack.popInt.get == 3.u256)
|
||||
|
||||
test "swap correct":
|
||||
privateAccess(EvmStackRef)
|
||||
var stack = EvmStackRef.new()
|
||||
privateAccess(EvmStack)
|
||||
var stack = EvmStack.init()
|
||||
for z in 0 ..< 5:
|
||||
check stack.push(z.uint).isOk
|
||||
check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256])
|
||||
|
@ -76,8 +76,8 @@ proc runStackTests() =
|
|||
check(stack.values == @[0.u256, 4.u256, 2.u256, 1.u256, 3.u256])
|
||||
|
||||
test "dup correct":
|
||||
privateAccess(EvmStackRef)
|
||||
var stack = EvmStackRef.new()
|
||||
privateAccess(EvmStack)
|
||||
var stack = EvmStack.init()
|
||||
for z in 0 ..< 5:
|
||||
check stack.push(z.uint).isOk
|
||||
check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256])
|
||||
|
@ -87,30 +87,30 @@ proc runStackTests() =
|
|||
check(stack.values == @[0.u256, 1.u256, 2.u256, 3.u256, 4.u256, 4.u256, 1.u256])
|
||||
|
||||
test "pop raises InsufficientStack appropriately":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
check stack.popInt().error.code == EvmErrorCode.StackInsufficient
|
||||
|
||||
test "swap raises InsufficientStack appropriately":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
check stack.swap(0).error.code == EvmErrorCode.StackInsufficient
|
||||
|
||||
test "dup raises InsufficientStack appropriately":
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
check stack.dup(0).error.code == EvmErrorCode.StackInsufficient
|
||||
|
||||
test "binary operations raises InsufficientStack appropriately":
|
||||
# https://github.com/status-im/nimbus/issues/31
|
||||
# ./tests/fixtures/VMTests/vmArithmeticTest/mulUnderFlow.json
|
||||
|
||||
var stack = EvmStackRef.new()
|
||||
var stack = EvmStack.init()
|
||||
check stack.push(123).isOk
|
||||
check stack.popInt(2).error.code == EvmErrorCode.StackInsufficient
|
||||
|
||||
proc memory32: EvmMemoryRef =
|
||||
result = EvmMemoryRef.new(32)
|
||||
proc memory32: EvmMemory =
|
||||
result = EvmMemory.init(32)
|
||||
|
||||
proc memory128: EvmMemoryRef =
|
||||
result = EvmMemoryRef.new(123)
|
||||
proc memory128: EvmMemory =
|
||||
result = EvmMemory.init(123)
|
||||
|
||||
proc runMemoryTests() =
|
||||
suite "Memory tests":
|
||||
|
@ -126,7 +126,7 @@ proc runMemoryTests() =
|
|||
check mem.write(startPos = 128, value = 1.byte).error.code == EvmErrorCode.MemoryFull
|
||||
|
||||
test "extends appropriately extends memory":
|
||||
var mem = EvmMemoryRef.new()
|
||||
var mem = EvmMemory.init()
|
||||
# Test extends to 32 byte array: 0 < (start_position + size) <= 32
|
||||
mem.extend(startPos = 0, size = 10)
|
||||
check(mem.bytes == repeat(0.byte, 32))
|
||||
|
|
Loading…
Reference in New Issue