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

(WIP) Call fixes precompiles #168

Merged
merged 28 commits into from
Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
62968bf
Initial support for precompiles with ecRecover
coffeepots Oct 2, 2018
e2087f0
Remove precompile hash table
coffeepots Oct 2, 2018
36270ff
Fixes for Call gas usage, Calls use precompiles, pass down their opCode
coffeepots Oct 2, 2018
fcffd94
Support different endians
coffeepots Oct 2, 2018
3deb09b
Add SHA256, RIPEMD160 and Identity precompiles
coffeepots Oct 3, 2018
3249c3e
Add precompile costs
coffeepots Oct 3, 2018
6a4cd4e
Update precompile gas costs case (cosmetic change)
coffeepots Oct 3, 2018
9318ea9
Added nim-bncurve dependency.
cheatfate Oct 5, 2018
38b4d54
Add modExp precompile + gas costs
mratsim Oct 5, 2018
0494e2a
Support short inputs with missing bytes
mratsim Oct 5, 2018
bb6e1e1
modExp precompiles: fix padding and static evaluation
mratsim Oct 10, 2018
2ee9861
Precompile test data
coffeepots Oct 10, 2018
7c77886
Allow simpler json files to be processed, add dir sep for echo
coffeepots Oct 10, 2018
e53222c
Test suite for precompiles
coffeepots Oct 10, 2018
6cd1964
Merge branch 'call-fixes-precompiles' of https://github.com/status-im…
coffeepots Oct 10, 2018
67df44e
Fix ecrecover, pad ripemd result and use sha256 vs keccak256
coffeepots Oct 10, 2018
4ca4a85
Remove bogus sha256 tests
coffeepots Oct 10, 2018
6e4616e
Precompiles now executed if called from vm_state_transactions
coffeepots Oct 12, 2018
0b15b86
Fix ecMul, ecPairing, ecAdd.
cheatfate Oct 16, 2018
826ce4f
Current test output
coffeepots Oct 16, 2018
434edcc
Fix incorrect message parameters (had sender and destination swapped)
coffeepots Oct 18, 2018
7ba1cfa
Remove endian code, precompiles should now run. Removed raise as case…
coffeepots Oct 19, 2018
6b1e989
Add initial gas cost for CREATE
coffeepots Nov 8, 2018
492d2ae
Debug message for new messages
coffeepots Nov 8, 2018
6eb430f
Fix CREATE op code gas costs, more debug output, call transactions
coffeepots Nov 8, 2018
1cead76
Add note about cyclic dep
coffeepots Nov 8, 2018
4c6a686
Current general tests state
coffeepots Nov 8, 2018
0366dd4
Remove irrelevant comments
coffeepots Nov 8, 2018
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
72 changes: 36 additions & 36 deletions GeneralStateTests.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,14 @@ OK: 0/30 Fail: 22/30 Skip: 8/30
- delegatecallEmptycontract.json Fail
- delegatecallInInitcodeToEmptyContract.json Fail
- delegatecallInInitcodeToExistingContract.json Fail
- delegatecallInInitcodeToExistingContractOOG.json Fail
+ delegatecallInInitcodeToExistingContractOOG.json OK
- delegatecallOOGinCall.json Fail
- delegatecallSenderCheck.json Fail
- delegatecallValueCheck.json Fail
- delegatecodeDynamicCode.json Fail
- delegatecodeDynamicCode2SelfCall.json Fail
```
OK: 3/34 Fail: 30/34 Skip: 1/34
OK: 4/34 Fail: 29/34 Skip: 1/34
## stEIP150Specific
```diff
CallAndCallcodeConsumeMoreGasThenTransactionHas.json Skip
Expand Down Expand Up @@ -718,10 +718,10 @@ OK: 65/67 Fail: 2/67 Skip: 0/67
- NonZeroValue_CALL_ToEmpty.json Fail
- NonZeroValue_CALL_ToNonNonZeroBalance.json Fail
- NonZeroValue_CALL_ToOneStorageKey.json Fail
- NonZeroValue_DELEGATECALL.json Fail
- NonZeroValue_DELEGATECALL_ToEmpty.json Fail
- NonZeroValue_DELEGATECALL_ToNonNonZeroBalance.json Fail
- NonZeroValue_DELEGATECALL_ToOneStorageKey.json Fail
+ NonZeroValue_DELEGATECALL.json OK
+ NonZeroValue_DELEGATECALL_ToEmpty.json OK
+ NonZeroValue_DELEGATECALL_ToNonNonZeroBalance.json OK
+ NonZeroValue_DELEGATECALL_ToOneStorageKey.json OK
+ NonZeroValue_SUICIDE.json OK
+ NonZeroValue_SUICIDE_ToEmpty.json OK
+ NonZeroValue_SUICIDE_ToNonNonZeroBalance.json OK
Expand All @@ -735,7 +735,7 @@ OK: 65/67 Fail: 2/67 Skip: 0/67
+ NonZeroValue_TransactionCALLwithData_ToNonNonZeroBalance.json OK
+ NonZeroValue_TransactionCALLwithData_ToOneStorageKey.json OK
```
OK: 12/24 Fail: 12/24 Skip: 0/24
OK: 16/24 Fail: 8/24 Skip: 0/24
## stPreCompiledContracts
```diff
identity_to_bigger.json Skip
Expand Down Expand Up @@ -1033,7 +1033,7 @@ OK: 0/16 Fail: 0/16 Skip: 16/16
+ randomStatetest174.json OK
+ randomStatetest175.json OK
+ randomStatetest176.json OK
- randomStatetest177.json Fail
+ randomStatetest177.json OK
- randomStatetest178.json Fail
+ randomStatetest179.json OK
+ randomStatetest18.json OK
Expand Down Expand Up @@ -1284,7 +1284,7 @@ OK: 0/16 Fail: 0/16 Skip: 16/16
+ randomStatetest97.json OK
+ randomStatetest98.json OK
```
OK: 305/327 Fail: 18/327 Skip: 4/327
OK: 306/327 Fail: 17/327 Skip: 4/327
## stRandom2
```diff
+ 201503110226PYTHON_DUP6.json OK
Expand Down Expand Up @@ -1508,14 +1508,14 @@ OK: 305/327 Fail: 18/327 Skip: 4/327
- randomStatetest639.json Fail
+ randomStatetest640.json OK
+ randomStatetest641.json OK
+ randomStatetest642.json OK
- randomStatetest642.json Fail
- randomStatetest643.json Fail
- randomStatetest644.json Fail
- randomStatetest645.json Fail
- randomStatetest646.json Fail
randomStatetest647.json Skip
```
OK: 208/227 Fail: 15/227 Skip: 4/227
OK: 207/227 Fail: 16/227 Skip: 4/227
## stRecursiveCreate
```diff
- recursiveCreate.json Fail
Expand Down Expand Up @@ -1551,9 +1551,9 @@ OK: 11/19 Fail: 8/19 Skip: 0/19
+ call_outsize_then_create_successful_then_returndatasize.json OK
+ call_then_call_value_fail_then_returndatasize.json OK
+ call_then_create_successful_then_returndatasize.json OK
- create_callprecompile_returndatasize.json Fail
+ create_callprecompile_returndatasize.json OK
modexp_modsize0_returndatasize.json Skip
- returndatacopy_0_0_following_successful_create.json Fail
+ returndatacopy_0_0_following_successful_create.json OK
returndatacopy_afterFailing_create.json Skip
+ returndatacopy_after_failing_callcode.json OK
+ returndatacopy_after_failing_delegatecall.json OK
Expand All @@ -1563,11 +1563,11 @@ OK: 11/19 Fail: 8/19 Skip: 0/19
+ returndatacopy_after_successful_delegatecall.json OK
+ returndatacopy_after_successful_staticcall.json OK
+ returndatacopy_following_call.json OK
- returndatacopy_following_create.json Fail
+ returndatacopy_following_create.json OK
+ returndatacopy_following_failing_call.json OK
+ returndatacopy_following_revert.json OK
- returndatacopy_following_revert_in_create.json Fail
- returndatacopy_following_successful_create.json Fail
+ returndatacopy_following_revert_in_create.json OK
+ returndatacopy_following_successful_create.json OK
+ returndatacopy_following_too_big_transfer.json OK
+ returndatacopy_initial.json OK
+ returndatacopy_initial_256.json OK
Expand All @@ -1581,11 +1581,11 @@ OK: 11/19 Fail: 8/19 Skip: 0/19
+ returndatasize_after_successful_delegatecall.json OK
+ returndatasize_after_successful_staticcall.json OK
+ returndatasize_bug.json OK
- returndatasize_following_successful_create.json Fail
+ returndatasize_following_successful_create.json OK
+ returndatasize_initial.json OK
+ returndatasize_initial_zero_read.json OK
```
OK: 28/37 Fail: 6/37 Skip: 3/37
OK: 34/37 Fail: 0/37 Skip: 3/37
## stRevertTest
```diff
+ LoopCallsDepthThenRevert.json OK
Expand All @@ -1608,7 +1608,7 @@ OK: 28/37 Fail: 6/37 Skip: 3/37
- RevertOpcodeCreate.json Fail
- RevertOpcodeDirectCall.json Fail
- RevertOpcodeInCallsOnNonEmptyReturnData.json Fail
- RevertOpcodeInCreateReturns.json Fail
+ RevertOpcodeInCreateReturns.json OK
- RevertOpcodeInInit.json Fail
- RevertOpcodeMultipleSubCalls.json Fail
- RevertOpcodeReturn.json Fail
Expand All @@ -1632,7 +1632,7 @@ OK: 28/37 Fail: 6/37 Skip: 3/37
- TouchToEmptyAccountRevert2.json Fail
- TouchToEmptyAccountRevert3.json Fail
```
OK: 15/43 Fail: 23/43 Skip: 5/43
OK: 16/43 Fail: 22/43 Skip: 5/43
## stShift
```diff
sar00.json Skip
Expand Down Expand Up @@ -2058,7 +2058,7 @@ OK: 0/284 Fail: 0/284 Skip: 284/284
+ callerAccountBalance.json OK
- createNameRegistrator.json Fail
+ createNameRegistratorOOG_MemExpansionOOV.json OK
+ createNameRegistratorOutOfMemoryBonds0.json OK
- createNameRegistratorOutOfMemoryBonds0.json Fail
+ createNameRegistratorOutOfMemoryBonds1.json OK
- createNameRegistratorValueTooHigh.json Fail
- createNameRegistratorZeroMem.json Fail
Expand All @@ -2083,12 +2083,12 @@ OK: 0/284 Fail: 0/284 Skip: 284/284
+ suicideSendEtherToMe.json OK
- testRandomTest.json Fail
```
OK: 26/67 Fail: 39/67 Skip: 2/67
OK: 25/67 Fail: 40/67 Skip: 2/67
## stTransactionTest
```diff
+ ContractStoreClearsOOG.json OK
+ ContractStoreClearsSuccess.json OK
- CreateMessageReverted.json Fail
+ CreateMessageReverted.json OK
- CreateMessageSuccess.json Fail
+ CreateTransactionReverted.json OK
+ CreateTransactionSuccess.json OK
Expand Down Expand Up @@ -2131,7 +2131,7 @@ OK: 26/67 Fail: 39/67 Skip: 2/67
+ UserTransactionZeroCost.json OK
+ UserTransactionZeroCostWithData.json OK
```
OK: 27/44 Fail: 17/44 Skip: 0/44
OK: 28/44 Fail: 16/44 Skip: 0/44
## stTransitionTest
```diff
- createNameRegistratorPerTxsAfter.json Fail
Expand Down Expand Up @@ -2222,17 +2222,17 @@ OK: 0/24 Fail: 0/24 Skip: 24/24
## stZeroCallsTest
```diff
- ZeroValue_CALL.json Fail
- ZeroValue_CALLCODE.json Fail
- ZeroValue_CALLCODE_ToEmpty.json Fail
- ZeroValue_CALLCODE_ToNonZeroBalance.json Fail
- ZeroValue_CALLCODE_ToOneStorageKey.json Fail
- ZeroValue_CALL_ToEmpty.json Fail
- ZeroValue_CALL_ToNonZeroBalance.json Fail
- ZeroValue_CALL_ToOneStorageKey.json Fail
- ZeroValue_DELEGATECALL.json Fail
- ZeroValue_DELEGATECALL_ToEmpty.json Fail
- ZeroValue_DELEGATECALL_ToNonZeroBalance.json Fail
- ZeroValue_DELEGATECALL_ToOneStorageKey.json Fail
+ ZeroValue_CALLCODE.json OK
+ ZeroValue_CALLCODE_ToEmpty.json OK
+ ZeroValue_CALLCODE_ToNonZeroBalance.json OK
+ ZeroValue_CALLCODE_ToOneStorageKey.json OK
+ ZeroValue_CALL_ToEmpty.json OK
+ ZeroValue_CALL_ToNonZeroBalance.json OK
+ ZeroValue_CALL_ToOneStorageKey.json OK
+ ZeroValue_DELEGATECALL.json OK
+ ZeroValue_DELEGATECALL_ToEmpty.json OK
+ ZeroValue_DELEGATECALL_ToNonZeroBalance.json OK
+ ZeroValue_DELEGATECALL_ToOneStorageKey.json OK
+ ZeroValue_SUICIDE.json OK
+ ZeroValue_SUICIDE_ToEmpty.json OK
+ ZeroValue_SUICIDE_ToNonZeroBalance.json OK
Expand All @@ -2246,7 +2246,7 @@ OK: 0/24 Fail: 0/24 Skip: 24/24
+ ZeroValue_TransactionCALLwithData_ToNonZeroBalance.json OK
+ ZeroValue_TransactionCALLwithData_ToOneStorageKey.json OK
```
OK: 12/24 Fail: 12/24 Skip: 0/24
OK: 23/24 Fail: 1/24 Skip: 0/24
## stZeroKnowledge
```diff
ecmul_1-2_2_28000_128.json Skip
Expand Down
14 changes: 14 additions & 0 deletions PrecompileTests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
PrecompileTests
===
## PrecompileTests
```diff
+ bn256Add.json OK
+ bn256mul.json OK
+ ecrecover.json OK
+ identity.json OK
- modexp.json Fail
+ pairing.json OK
+ ripemd160.json OK
+ sha256.json OK
```
OK: 7/8 Fail: 1/8 Skip: 0/8
3 changes: 2 additions & 1 deletion nimbus.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ requires "nim >= 0.18.1",
"asyncdispatch2",
"eth_p2p",
"eth_keyfile",
"eth_keys"
"eth_keys",
"https://github.com/status-im/nim-bncurve >= 1.0.1"

proc buildBinary(name: string, srcDir = ".", lang = "c") =
if not dirExists "build": mkDir "build"
Expand Down
76 changes: 58 additions & 18 deletions nimbus/vm/computation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import
../constants, ../errors, ../validation, ../vm_state, ../vm_types,
./interpreter/[opcode_values, gas_meter, gas_costs, vm_forks],
./code_stream, ./memory, ./message, ./stack, ../db/[state_db, db_chain],
../utils/header, byteutils, ranges
../utils/header, byteutils, ranges, eth_keys, precompiles

logScope:
topics = "vm computation"
Expand Down Expand Up @@ -78,14 +78,14 @@ proc prepareChildMessage*(
result = newMessage(
gas,
c.msg.gasPrice,
c.msg.origin,
to,
c.msg.origin,
value,
data,
code,
childOptions)

proc applyMessage(computation: var BaseComputation) =
proc applyMessage(computation: var BaseComputation, opCode: static[Op]) =
Copy link
Contributor

Choose a reason for hiding this comment

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

If this proc is generic now (due to the static param), it would make sense to extract the parts of it that don't depend on the opCode param in helper procs (the goal would be the reduce the overall code size).

var transaction = computation.vmState.beginTransaction()
defer: transaction.dispose()

Expand All @@ -97,28 +97,68 @@ proc applyMessage(computation: var BaseComputation) =
computation.vmState.chainDb.getStateDb(
computation.vmState.blockHeader.hash, false).
getBalance(computation.msg.sender)
var newBalance = senderBalance

if sender_balance < computation.msg.value:
raise newException(InsufficientFunds,
&"Insufficient funds: {senderBalance} < {computation.msg.value}"
)

computation.vmState.mutateStateDb:
db.setBalance(computation.msg.sender, db.getBalance(computation.msg.sender) - computation.msg.value)
db.addBalance(computation.msg.storage_address, computation.msg.value)
when opCode in {Call, CallCode}:
let
insufficientFunds = senderBalance < computation.msg.value
stackTooDeep = computation.msg.depth >= MaxCallDepth

if insufficientFunds or stackTooDeep:
computation.returnData = @[]
var errMessage: string
if insufficientFunds:
errMessage = &"Insufficient Funds: have: {$senderBalance} need: {$computation.msg.value}"
elif stackTooDeep:
errMessage = "Stack Limit Reached"
else:
raise newException(VMError, "Invariant: Unreachable code path")

debug "Computation failure", msg = errMessage
computation.gasMeter.returnGas(computation.msg.gas)
push: 0
return

newBalance = senderBalance - computation.msg.value
computation.vmState.mutateStateDb:
db.setBalance(computation.msg.sender, newBalance)
db.addBalance(computation.msg.storage_address, computation.msg.value)

debug "Value transferred",
source = computation.msg.sender,
dest = computation.msg.storage_address,
value = computation.msg.value,
oldSenderBalance = senderBalance,
newSenderBalance = newBalance,
gasPrice = computation.msg.gasPrice,
gas = computation.msg.gas

debug "Apply message",
value = computation.msg.value,
senderBalance = newBalance,
sender = computation.msg.sender.toHex,
address = computation.msg.storage_address.toHex
address = computation.msg.storage_address.toHex,
gasPrice = computation.msg.gasPrice,
gas = computation.msg.gas

computation.opcodeExec(computation)
# Run code
# We cannot use the normal dispatching function `executeOpcodes`
# within `interpreter_dispatch.nim` due to a cyclic dependency.
if not computation.execPrecompiles:
computation.opcodeExec(computation)

if not computation.isError:
debug "Computation committed"
transaction.commit()
else:
debug "Computation rolled back due to error"

proc applyCreateMessage(fork: Fork, computation: var BaseComputation) =
computation.applyMessage()
proc applyCreateMessage(fork: Fork, computation: var BaseComputation, opCode: static[Op]) =
computation.applyMessage(opCode)

var transaction: DbTransaction
defer: transaction.safeDispose()
Expand Down Expand Up @@ -157,25 +197,25 @@ proc applyCreateMessage(fork: Fork, computation: var BaseComputation) =
else:
# Different from Frontier:
# Reverts state on gas failure while writing contract code.
# TODO: Revert snapshot
# Transaction are reverted automatically by safeDispose.
discard
else:
if transaction != nil:
transaction.commit()

proc generateChildComputation*(fork: Fork, computation: BaseComputation, childMsg: Message): BaseComputation =
proc generateChildComputation*(fork: Fork, computation: BaseComputation, childMsg: Message, opCode: static[Op]): BaseComputation =
var childComp = newBaseComputation(
computation.vmState,
computation.vmState.blockHeader.blockNumber,
childMsg)

# Copy the fork op code executor proc (assumes child computation is in the same fork)
childComp.opCodeExec = computation.opCodeExec

if childMsg.isCreate:
fork.applyCreateMessage(childComp)
fork.applyCreateMessage(childComp, opCode)
else:
applyMessage(childComp)
applyMessage(childComp, opCode)
return childComp

proc addChildComputation(fork: Fork, computation: BaseComputation, child: BaseComputation) =
Expand All @@ -193,10 +233,10 @@ proc addChildComputation(fork: Fork, computation: BaseComputation, child: BaseCo
computation.returnData = child.output
computation.children.add(child)

proc applyChildComputation*(computation: BaseComputation, childMsg: Message): BaseComputation =
proc applyChildComputation*(computation: BaseComputation, childMsg: Message, opCode: static[Op]): BaseComputation =
## Apply the vm message childMsg as a child computation.
let fork = computation.vmState.blockHeader.blockNumber.toFork
result = fork.generateChildComputation(computation, childMsg)
result = fork.generateChildComputation(computation, childMsg, opCode)
fork.addChildComputation(computation, result)

proc registerAccountForDeletion*(c: var BaseComputation, beneficiary: EthAddress) =
Expand Down
Loading