From a28f06a8257e1fa21475525170ecaa0a1c3966d8 Mon Sep 17 00:00:00 2001 From: andri lim Date: Wed, 6 Feb 2019 14:46:09 +0700 Subject: [PATCH] fixes CALL opcode --- nimbus/vm/computation.nim | 14 +++++++---- nimbus/vm/interpreter/gas_costs.nim | 32 +++++++++++++------------ nimbus/vm/interpreter/opcodes_impl.nim | 33 +++++++++++++++++--------- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index cbb0f04bc..f1a1caa44 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -131,11 +131,11 @@ proc applyMessage(computation: var BaseComputation, opCode: static[Op]) = newBalance = senderBalance - computation.msg.value computation.vmState.mutateStateDb: db.setBalance(computation.msg.sender, newBalance) - db.addBalance(computation.msg.storage_address, computation.msg.value) + db.addBalance(computation.msg.storageAddress, computation.msg.value) trace "Value transferred", source = computation.msg.sender, - dest = computation.msg.storage_address, + dest = computation.msg.storageAddress, value = computation.msg.value, oldSenderBalance = senderBalance, newSenderBalance = newBalance, @@ -146,9 +146,15 @@ proc applyMessage(computation: var BaseComputation, opCode: static[Op]) = value = computation.msg.value, senderBalance = newBalance, sender = computation.msg.sender.toHex, - address = computation.msg.storage_address.toHex, + address = computation.msg.storageAddress.toHex, gasPrice = computation.msg.gasPrice, gas = computation.msg.gas + else: + # even though the value is zero, the account + # should be exist. + when opCode in {Call, CallCode}: + computation.vmState.mutateStateDb: + db.addBalance(computation.msg.storageAddress, computation.msg.value) # Run code # We cannot use the normal dispatching function `executeOpcodes` @@ -184,7 +190,7 @@ proc applyCreateMessage(fork: Fork, computation: var BaseComputation, opCode: st computation.gasCosts[Create].m_handler(0, 0, contractCode.len), reason = "Write contract code for CREATE") - let storageAddr = computation.msg.storage_address + let storageAddr = computation.msg.storageAddress trace "SETTING CODE", address = storageAddr.toHex, length = len(contract_code), diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 8e0a688cc..f866466a1 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -126,10 +126,10 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = # M(currentMemSize, f, l) = currentMemSize let - prev_words: int64 = currentMemSize.wordCount - new_words: int64 = (memOffset + memLength).wordCount + prevWords: int64 = currentMemSize.wordCount + newWords: int64 = (memOffset + memLength).wordCount - if memLength == 0 or new_words <= prev_words: + if memLength == 0 or newWords <= prevWords: # Special subcase of memory-expansion cost # currentMemSize - currentMemSize = 0 # "Referencing a zero length range ... does not require memory to be extended @@ -141,13 +141,13 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = return 0 let - prev_cost = prev_words * static(FeeSchedule[GasMemory]) + - (prev_words ^ 2) shr 9 # div 512 - new_cost = new_words * static(FeeSchedule[GasMemory]) + - (new_words ^ 2) shr 9 # div 512 + prevCost = prevWords * static(FeeSchedule[GasMemory]) + + (prevWords ^ 2) shr 9 # div 512 + newCost = newWords * static(FeeSchedule[GasMemory]) + + (newWords ^ 2) shr 9 # div 512 # TODO: add logging - result = max(new_cost - prev_cost, 0) + result = max(newCost - prevCost, 0) func `prefix all_but_one_64th`(gas: GasInt): GasInt {.inline.} = ## Computes all but 1/64th @@ -169,7 +169,7 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = result += static(FeeSchedule[GasExpByte]) * (1 + log256(value)) func `prefix gasCreate`(currentMemSize, memOffset, memLength: Natural): GasInt {.nimcall.} = - result = + result = static(FeeSchedule[GasCreate]) + static(FeeSchedule[GasCodeDeposit]) * memLength @@ -202,10 +202,10 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = gSreset = FeeSchedule[GasSreset] # Gas cost - literal translation of Yellow Paper - result.gasCost = if value.isZero.not and gasParams.s_isStorageEmpty: - gSet - else: - gSreset + result.gasCost = if value.isZero.not and gasParams.s_isStorageEmpty: + gSet + else: + gSreset # Refund if value.isZero and not gasParams.s_isStorageEmpty: @@ -319,10 +319,12 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = if gasParams.c_gasBalance >= result.gasCost: min( `prefix all_but_one_64th`(gasParams.c_gasBalance - result.gasCost), - gasParams.c_contract_gas + gasParams.c_contractGas ) else: - gasParams.c_contract_gas + gasParams.c_contractGas + else: + result.gasCost += gasParams.c_contractGas # Ccallgas - Gas sent to the child message result.gasRefund = result.gasCost diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index 67751d224..07c5e471e 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - strformat, times, ranges, sequtils, + strformat, times, ranges, sequtils, options, chronicles, stint, nimcrypto, ranges/typedranges, eth/common, ./utils/[macros_procs_opcodes, utils_numeric], ./gas_meter, ./gas_costs, ./opcode_values, ./vm_forks, @@ -599,7 +599,7 @@ proc callParams(computation: var BaseComputation): (UInt256, UInt256, EthAddress memoryInputStartPosition, memoryInputSize, memoryOutputStartPosition, memoryOutputSize) = computation.stack.popInt(5) - let to = computation.msg.storageAddress + let to = codeAddress let sender = computation.msg.storageAddress result = (gas, @@ -689,18 +689,29 @@ template genCall(callName: untyped, opCode: Op): untyped = let (memInPos, memInLen, memOutPos, memOutLen) = (memoryInputStartPosition.cleanMemRef, memoryInputSize.cleanMemRef, memoryOutputStartPosition.cleanMemRef, memoryOutputSize.cleanMemRef) - let (gasCost, childMsgGas) = computation.gasCosts[opCode].c_handler( + let isNewAccount = if getFork(computation) >= FkSpurious: + computation.vmState.readOnlyStateDb.isDeadAccount(to) + else: + not computation.vmState.readOnlyStateDb.accountExists(to) + + let (memOffset, memLength) = if memInPos + memInLen > memOutPos + memOutLen: + (memInPos, memInLen) + else: + (memOutPos, memOutLen) + + let (childGasFee, childGasLimit) = computation.gasCosts[opCode].c_handler( value, GasParams(kind: Call, - c_isNewAccount: true, # TODO stub - c_gasBalance: 0, - c_contractGas: 0, + c_isNewAccount: isNewAccount, + c_gasBalance: computation.gasMeter.gasRemaining, + c_contractGas: gas.truncate(GasInt), c_currentMemSize: computation.memory.len, - c_memOffset: 0, # TODO make sure if we pass the largest mem requested - c_memLength: 0 # or an addition of mem requested + c_memOffset: memOffset, + c_memLength: memLength )) - trace "Call (" & callName.astToStr & ")", gasCost = gasCost, childCost = childMsgGas - computation.gasMeter.consumeGas(gasCost, reason = $opCode) + + trace "Call (" & callName.astToStr & ")", childGasLimit, childGasFee + computation.gasMeter.consumeGas(childGasFee, reason = $opCode) computation.memory.extend(memInPos, memInLen) computation.memory.extend(memOutPos, memOutLen) @@ -715,7 +726,7 @@ template genCall(callName: untyped, opCode: Op): untyped = var childMsg = prepareChildMessage( computation, - childMsgGas, + childGasLimit, to, value, callData,