integrate GeneralStateTest runner into CI with 775 running tests (#153)
* fix 32-bit issue in AppVeyor
* allow another dozen or so GeneralStateTest fixtures which work on 64-bit, but not on 32-bit platforms, to safely-fail, but demarcate them separately to facilitate debugging
* steal fa672600eb
from @coffeepots fix-int32-high-zero branch
This commit is contained in:
parent
5acd6cc049
commit
8f4e1a4445
|
@ -623,7 +623,7 @@ OK: 0/8 Fail: 8/8 Skip: 0/8
|
||||||
MSTORE_Bounds2.json Skip
|
MSTORE_Bounds2.json Skip
|
||||||
MSTORE_Bounds2a.json Skip
|
MSTORE_Bounds2a.json Skip
|
||||||
POP_Bounds.json Skip
|
POP_Bounds.json Skip
|
||||||
+ RETURN_Bounds.json OK
|
- RETURN_Bounds.json Fail
|
||||||
SLOAD_Bounds.json Skip
|
SLOAD_Bounds.json Skip
|
||||||
SSTORE_Bounds.json Skip
|
SSTORE_Bounds.json Skip
|
||||||
mload32bitBound.json Skip
|
mload32bitBound.json Skip
|
||||||
|
@ -636,7 +636,7 @@ OK: 0/8 Fail: 8/8 Skip: 0/8
|
||||||
static_CALL_Bounds2a.json Skip
|
static_CALL_Bounds2a.json Skip
|
||||||
static_CALL_Bounds3.json Skip
|
static_CALL_Bounds3.json Skip
|
||||||
```
|
```
|
||||||
OK: 5/38 Fail: 0/38 Skip: 33/38
|
OK: 4/38 Fail: 1/38 Skip: 33/38
|
||||||
## stMemoryTest
|
## stMemoryTest
|
||||||
```diff
|
```diff
|
||||||
- callDataCopyOffset.json Fail
|
- callDataCopyOffset.json Fail
|
||||||
|
|
|
@ -792,6 +792,9 @@ op selfDestruct, inline = false:
|
||||||
|
|
||||||
# Register the account to be deleted
|
# Register the account to be deleted
|
||||||
computation.registerAccountForDeletion(beneficiary)
|
computation.registerAccountForDeletion(beneficiary)
|
||||||
|
# FIXME: hook this into actual RefundSelfDestruct
|
||||||
|
let RefundSelfDestruct = 24_000
|
||||||
|
computation.gasMeter.refundGas(RefundSelfDestruct)
|
||||||
|
|
||||||
debug(
|
debug(
|
||||||
"SELFDESTRUCT",
|
"SELFDESTRUCT",
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# tests
|
# tests
|
||||||
|
|
||||||
TODO: more vm tests and fixtures!
|
TODO: more GeneralStateTest fixtures!
|
||||||
|
|
|
@ -0,0 +1,564 @@
|
||||||
|
# Nimbus
|
||||||
|
# Copyright (c) 2018 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
# XXX: when all but a relative few dozen, say, GeneralStateTests run, remove this,
|
||||||
|
# but for now, this enables some CI use before that to prevent regressions. In the
|
||||||
|
# separate file here because it would otherwise just distract. Could use all sorts
|
||||||
|
# of O(1) or O(log n) lookup structures, or be more careful to only initialize the
|
||||||
|
# table once, but notion's that it should shrink reasonable quickly and disappear,
|
||||||
|
# being mostly used for short-term regression prevention.
|
||||||
|
func allowedFailingGeneralStateTest*(folder, name: string): bool =
|
||||||
|
let allowedFailingGeneralStateTests = @[
|
||||||
|
"ContractCreationSpam.json",
|
||||||
|
"CrashingTransaction.json",
|
||||||
|
"badOpcodes.json",
|
||||||
|
"call_OOG_additionalGasCosts1.json",
|
||||||
|
"callcall_00.json",
|
||||||
|
"callcode_checkPC.json",
|
||||||
|
"callcodecallcode_11_OOGE.json",
|
||||||
|
"callcallcallcode_001.json",
|
||||||
|
"callcallcallcode_001_OOGE.json",
|
||||||
|
"callcallcallcode_001_OOGMAfter.json",
|
||||||
|
"callcallcallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcallcodecall_010_OOGMAfter.json",
|
||||||
|
"callcallcodecall_ABCB_RECURSIVE.json",
|
||||||
|
"callcallcodecallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcall_100_OOGMAfter.json",
|
||||||
|
"callcodecallcall_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcallcode_101_OOGMAfter.json",
|
||||||
|
"callcodecallcallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcodecall_110_OOGMAfter.json",
|
||||||
|
"callcodecallcodecall_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter.json",
|
||||||
|
"callcodecallcodecallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcallcallcode_001.json",
|
||||||
|
"callcallcallcode_001_OOGE.json",
|
||||||
|
"callcallcallcode_001_OOGMAfter.json",
|
||||||
|
"callcallcallcode_001_OOGMBefore.json",
|
||||||
|
"callcallcallcode_001_SuicideEnd.json",
|
||||||
|
"callcallcallcode_001_SuicideMiddle.json",
|
||||||
|
"callcallcallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcallcode_01.json",
|
||||||
|
"callcallcode_01_OOGE.json",
|
||||||
|
"callcallcode_01_SuicideEnd.json",
|
||||||
|
"callcallcodecall_010.json",
|
||||||
|
"callcallcodecall_010_OOGE.json",
|
||||||
|
"callcallcodecall_010_OOGMAfter.json",
|
||||||
|
"callcallcodecall_010_OOGMBefore.json",
|
||||||
|
"callcallcodecall_010_SuicideEnd.json",
|
||||||
|
"callcallcodecall_010_SuicideMiddle.json",
|
||||||
|
"callcallcodecall_ABCB_RECURSIVE.json",
|
||||||
|
"callcallcodecallcode_011.json",
|
||||||
|
"callcallcodecallcode_011_OOGE.json",
|
||||||
|
"callcallcodecallcode_011_OOGMAfter.json",
|
||||||
|
"callcallcodecallcode_011_OOGMBefore.json",
|
||||||
|
"callcallcodecallcode_011_SuicideEnd.json",
|
||||||
|
"callcallcodecallcode_011_SuicideMiddle.json",
|
||||||
|
"callcallcodecallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecall_10.json",
|
||||||
|
"callcodecall_10_OOGE.json",
|
||||||
|
"callcodecall_10_SuicideEnd.json",
|
||||||
|
"callcodecallcall_100.json",
|
||||||
|
"callcodecallcall_100_OOGE.json",
|
||||||
|
"callcodecallcall_100_OOGMAfter.json",
|
||||||
|
"callcodecallcall_100_OOGMBefore.json",
|
||||||
|
"callcodecallcall_100_SuicideEnd.json",
|
||||||
|
"callcodecallcall_100_SuicideMiddle.json",
|
||||||
|
"callcodecallcall_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcallcode_101.json",
|
||||||
|
"callcodecallcallcode_101_OOGE.json",
|
||||||
|
"callcodecallcallcode_101_OOGMAfter.json",
|
||||||
|
"callcodecallcallcode_101_OOGMBefore.json",
|
||||||
|
"callcodecallcallcode_101_SuicideEnd.json",
|
||||||
|
"callcodecallcallcode_101_SuicideMiddle.json",
|
||||||
|
"callcodecallcallcode_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcode_11.json",
|
||||||
|
"callcodecallcode_11_OOGE.json",
|
||||||
|
"callcodecallcode_11_SuicideEnd.json",
|
||||||
|
"callcodecallcodecall_110.json",
|
||||||
|
"callcodecallcodecall_110_OOGE.json",
|
||||||
|
"callcodecallcodecall_110_OOGMAfter.json",
|
||||||
|
"callcodecallcodecall_110_OOGMBefore.json",
|
||||||
|
"callcodecallcodecall_110_SuicideEnd.json",
|
||||||
|
"callcodecallcodecall_110_SuicideMiddle.json",
|
||||||
|
"callcodecallcodecall_ABCB_RECURSIVE.json",
|
||||||
|
"callcodecallcodecallcode_111.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGE.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMBefore.json",
|
||||||
|
"callcodecallcodecallcode_111_SuicideEnd.json",
|
||||||
|
"callcodecallcodecallcode_111_SuicideMiddle.json",
|
||||||
|
"callcodecallcodecallcode_ABCB_RECURSIVE.json",
|
||||||
|
"Call1024PreCalls.json",
|
||||||
|
"Callcode1024BalanceTooLow.json",
|
||||||
|
"callcallcall_000_OOGMAfter.json",
|
||||||
|
"callcallcallcode_001_OOGMAfter_1.json",
|
||||||
|
"callcallcallcode_001_OOGMAfter_2.json",
|
||||||
|
"callcallcallcode_001_OOGMAfter_3.json",
|
||||||
|
"callcallcodecall_010_OOGMAfter_1.json",
|
||||||
|
"callcallcodecall_010_OOGMAfter_2.json",
|
||||||
|
"callcallcodecall_010_OOGMAfter_3.json",
|
||||||
|
"callcallcodecallcode_011_OOGMAfter_1.json",
|
||||||
|
"callcallcodecallcode_011_OOGMAfter_2.json",
|
||||||
|
"callcodecallcall_100_OOGMAfter_2.json",
|
||||||
|
"callcodecallcall_100_OOGMAfter_3.json",
|
||||||
|
"callcodecallcallcode_101_OOGMAfter_1.json",
|
||||||
|
"callcodecallcallcode_101_OOGMAfter_2.json",
|
||||||
|
"callcodecallcallcode_101_OOGMAfter_3.json",
|
||||||
|
"callcodecallcodecall_110_OOGMAfter_1.json",
|
||||||
|
"callcodecallcodecall_110_OOGMAfter_2.json",
|
||||||
|
"callcodecallcodecall_110_OOGMAfter_3.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter_1.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter_2.json",
|
||||||
|
"callcodecallcodecallcode_111_OOGMAfter_3.json",
|
||||||
|
"contractCreationMakeCallThatAskMoreGasThenTransactionProvided.json",
|
||||||
|
"createInitFail_OOGduringInit.json",
|
||||||
|
"codesizeInit.json",
|
||||||
|
"codesizeOOGInvalidSize.json",
|
||||||
|
"codesizeValid.json",
|
||||||
|
"CREATE_AcreateB_BSuicide_BStore.json",
|
||||||
|
"CREATE_ContractSSTOREDuringInit.json",
|
||||||
|
"CREATE_ContractSuicideDuringInit.json",
|
||||||
|
"CREATE_ContractSuicideDuringInit_ThenStoreThenReturn.json",
|
||||||
|
"CREATE_ContractSuicideDuringInit_WithValue.json",
|
||||||
|
"CREATE_ContractSuicideDuringInit_WithValueToItself.json",
|
||||||
|
"CREATE_EContractCreateEContractInInit_Tr.json",
|
||||||
|
"CREATE_EContractCreateNEContractInInitOOG_Tr.json",
|
||||||
|
"CREATE_EContractCreateNEContractInInit_Tr.json",
|
||||||
|
"CREATE_EContract_ThenCALLToNonExistentAcc.json",
|
||||||
|
"CREATE_EmptyContract.json",
|
||||||
|
"CREATE_EmptyContractAndCallIt_0wei.json",
|
||||||
|
"CREATE_EmptyContractAndCallIt_1wei.json",
|
||||||
|
"CREATE_EmptyContractWithBalance.json",
|
||||||
|
"CREATE_EmptyContractWithStorage.json",
|
||||||
|
"CREATE_EmptyContractWithStorageAndCallIt_0wei.json",
|
||||||
|
"CREATE_EmptyContractWithStorageAndCallIt_1wei.json",
|
||||||
|
"CREATE_empty000CreateinInitCode_Transaction.json",
|
||||||
|
"CreateCollisionToEmpty.json",
|
||||||
|
"TransactionCollisionToEmpty.json",
|
||||||
|
"TransactionCollisionToEmptyButCode.json",
|
||||||
|
"TransactionCollisionToEmptyButNonce.json",
|
||||||
|
"Call1024OOG.json",
|
||||||
|
"Call1024PreCalls.json",
|
||||||
|
"CallLoseGasOOG.json",
|
||||||
|
"CallRecursiveBombPreCall.json",
|
||||||
|
"CallcodeLoseGasOOG.json",
|
||||||
|
"Delegatecall1024.json",
|
||||||
|
"Delegatecall1024OOG.json",
|
||||||
|
"callOutput1.json",
|
||||||
|
"callOutput2.json",
|
||||||
|
"callOutput3.json",
|
||||||
|
"callOutput3Fail.json",
|
||||||
|
"callOutput3partial.json",
|
||||||
|
"callOutput3partialFail.json",
|
||||||
|
"callcodeOutput1.json",
|
||||||
|
"callcodeOutput2.json",
|
||||||
|
"callcodeOutput3.json",
|
||||||
|
"callcodeOutput3Fail.json",
|
||||||
|
"callcodeOutput3partial.json",
|
||||||
|
"callcodeOutput3partialFail.json",
|
||||||
|
"deleagateCallAfterValueTransfer.json",
|
||||||
|
"delegatecallAndOOGatTxLevel.json",
|
||||||
|
"delegatecallBasic.json",
|
||||||
|
"delegatecallEmptycontract.json",
|
||||||
|
"delegatecallInInitcodeToEmptyContract.json",
|
||||||
|
"delegatecallInInitcodeToExistingContract.json",
|
||||||
|
"delegatecallInInitcodeToExistingContractOOG.json",
|
||||||
|
"delegatecallOOGinCall.json",
|
||||||
|
"delegatecallSenderCheck.json",
|
||||||
|
"delegatecallValueCheck.json",
|
||||||
|
"delegatecodeDynamicCode.json",
|
||||||
|
"delegatecodeDynamicCode2SelfCall.json",
|
||||||
|
"NewGasPriceForCodes.json",
|
||||||
|
"RawCallCodeGas.json",
|
||||||
|
"RawCallCodeGasAsk.json",
|
||||||
|
"RawCallCodeGasMemory.json",
|
||||||
|
"RawCallCodeGasMemoryAsk.json",
|
||||||
|
"RawCallCodeGasValueTransfer.json",
|
||||||
|
"RawCallCodeGasValueTransferMemory.json",
|
||||||
|
"RawCallGas.json",
|
||||||
|
"RawCallGasAsk.json",
|
||||||
|
"RawCallGasValueTransfer.json",
|
||||||
|
"RawCallGasValueTransferMemory.json",
|
||||||
|
"RawCallMemoryGas.json",
|
||||||
|
"RawCallMemoryGasAsk.json",
|
||||||
|
"RawCreateFailGasValueTransfer.json",
|
||||||
|
"RawCreateFailGasValueTransfer2.json",
|
||||||
|
"RawCreateGas.json",
|
||||||
|
"RawCreateGasMemory.json",
|
||||||
|
"RawCreateGasValueTransfer.json",
|
||||||
|
"RawCreateGasValueTransferMemory.json",
|
||||||
|
"RawDelegateCallGas.json",
|
||||||
|
"RawDelegateCallGasAsk.json",
|
||||||
|
"RawDelegateCallGasMemory.json",
|
||||||
|
"RawDelegateCallGasMemoryAsk.json",
|
||||||
|
"contractCreationOOGdontLeaveEmptyContract.json",
|
||||||
|
"contractCreationOOGdontLeaveEmptyContractViaTransaction.json",
|
||||||
|
"createContractViaContract.json",
|
||||||
|
"createContractViaContractOOGInitCode.json",
|
||||||
|
"createContractViaTransactionCost53000.json",
|
||||||
|
"CallContractToCreateContractAndCallItOOG.json",
|
||||||
|
"CallContractToCreateContractNoCash.json",
|
||||||
|
"CallContractToCreateContractOOG.json",
|
||||||
|
"CallContractToCreateContractOOGBonusGas.json",
|
||||||
|
"CallContractToCreateContractWhichWouldCreateContractIfCalled.json",
|
||||||
|
"CallContractToCreateContractWhichWouldCreateContractInInitCode.json",
|
||||||
|
"CallRecursiveContract.json",
|
||||||
|
"CallTheContractToCreateEmptyContract.json",
|
||||||
|
"OutOfGasContractCreation.json",
|
||||||
|
"OutOfGasPrefundedContractCreation.json",
|
||||||
|
"ReturnTest.json",
|
||||||
|
"ReturnTest2.json",
|
||||||
|
"StackUnderFlowContractCreation.json",
|
||||||
|
"TransactionCreateAutoSuicideContract.json",
|
||||||
|
"TransactionCreateRandomInitCode.json",
|
||||||
|
"TransactionCreateStopInInitcode.json",
|
||||||
|
"TransactionCreateSuicideInInitcode.json",
|
||||||
|
"log0_emptyMem.json",
|
||||||
|
"log0_logMemStartTooHigh.json",
|
||||||
|
"log0_logMemsizeTooHigh.json",
|
||||||
|
"log0_logMemsizeZero.json",
|
||||||
|
"log0_nonEmptyMem.json",
|
||||||
|
"log0_nonEmptyMem_logMemSize1.json",
|
||||||
|
"log0_nonEmptyMem_logMemSize1_logMemStart31.json",
|
||||||
|
"log1_Caller.json",
|
||||||
|
"log1_MaxTopic.json",
|
||||||
|
"log1_emptyMem.json",
|
||||||
|
"log1_logMemStartTooHigh.json",
|
||||||
|
"log1_logMemsizeTooHigh.json",
|
||||||
|
"log1_logMemsizeZero.json",
|
||||||
|
"log1_nonEmptyMem.json",
|
||||||
|
"log1_nonEmptyMem_logMemSize1.json",
|
||||||
|
"log1_nonEmptyMem_logMemSize1_logMemStart31.json",
|
||||||
|
"log2_Caller.json",
|
||||||
|
"log2_MaxTopic.json",
|
||||||
|
"log2_emptyMem.json",
|
||||||
|
"log2_logMemStartTooHigh.json",
|
||||||
|
"log2_logMemsizeTooHigh.json",
|
||||||
|
"log2_logMemsizeZero.json",
|
||||||
|
"log2_nonEmptyMem.json",
|
||||||
|
"log2_nonEmptyMem_logMemSize1.json",
|
||||||
|
"log2_nonEmptyMem_logMemSize1_logMemStart31.json",
|
||||||
|
"log3_Caller.json",
|
||||||
|
"log3_MaxTopic.json",
|
||||||
|
"log3_PC.json",
|
||||||
|
"log3_emptyMem.json",
|
||||||
|
"log3_logMemStartTooHigh.json",
|
||||||
|
"log3_logMemsizeTooHigh.json",
|
||||||
|
"log3_logMemsizeZero.json",
|
||||||
|
"log3_nonEmptyMem.json",
|
||||||
|
"log3_nonEmptyMem_logMemSize1.json",
|
||||||
|
"log3_nonEmptyMem_logMemSize1_logMemStart31.json",
|
||||||
|
"log4_Caller.json",
|
||||||
|
"log4_MaxTopic.json",
|
||||||
|
"log4_PC.json",
|
||||||
|
"log4_emptyMem.json",
|
||||||
|
"log4_logMemStartTooHigh.json",
|
||||||
|
"log4_logMemsizeTooHigh.json",
|
||||||
|
"log4_logMemsizeZero.json",
|
||||||
|
"log4_nonEmptyMem.json",
|
||||||
|
"log4_nonEmptyMem_logMemSize1.json",
|
||||||
|
"log4_nonEmptyMem_logMemSize1_logMemStart31.json",
|
||||||
|
"logInOOG_Call.json",
|
||||||
|
"CallAndCallcodeConsumeMoreGasThenTransactionHasWithMemExpandingCalls.json",
|
||||||
|
"CallAskMoreGasOnDepth2ThenTransactionHasWithMemExpandingCalls.json",
|
||||||
|
"CallGoesOOGOnSecondLevel2WithMemExpandingCalls.json",
|
||||||
|
"CallGoesOOGOnSecondLevelWithMemExpandingCalls.json",
|
||||||
|
"CreateAndGasInsideCreateWithMemExpandingCalls.json",
|
||||||
|
"DelegateCallOnEIPWithMemExpandingCalls.json",
|
||||||
|
"ExecuteCallThatAskMoreGasThenTransactionHasWithMemExpandingCalls.json",
|
||||||
|
"NewGasPriceForCodesWithMemExpandingCalls.json",
|
||||||
|
"RETURN_Bounds.json",
|
||||||
|
"callDataCopyOffset.json",
|
||||||
|
"codeCopyOffset.json",
|
||||||
|
"NonZeroValue_CALL.json",
|
||||||
|
"NonZeroValue_CALLCODE.json",
|
||||||
|
"NonZeroValue_CALLCODE_ToEmpty.json",
|
||||||
|
"NonZeroValue_CALLCODE_ToNonNonZeroBalance.json",
|
||||||
|
"NonZeroValue_CALLCODE_ToOneStorageKey.json",
|
||||||
|
"NonZeroValue_CALL_ToEmpty.json",
|
||||||
|
"NonZeroValue_CALL_ToNonNonZeroBalance.json",
|
||||||
|
"NonZeroValue_CALL_ToOneStorageKey.json",
|
||||||
|
"NonZeroValue_DELEGATECALL.json",
|
||||||
|
"NonZeroValue_DELEGATECALL_ToEmpty.json",
|
||||||
|
"NonZeroValue_DELEGATECALL_ToNonNonZeroBalance.json",
|
||||||
|
"NonZeroValue_DELEGATECALL_ToOneStorageKey.json",
|
||||||
|
"CALLCODEEcrecover0.json",
|
||||||
|
"CALLCODEEcrecover0_0input.json",
|
||||||
|
"CALLCODEEcrecover0_Gas2999.json",
|
||||||
|
"CALLCODEEcrecover0_NoGas.json",
|
||||||
|
"CALLCODEEcrecover0_completeReturnValue.json",
|
||||||
|
"CALLCODEEcrecover0_gas3000.json",
|
||||||
|
"CALLCODEEcrecover0_overlappingInputOutput.json",
|
||||||
|
"CALLCODEEcrecover1.json",
|
||||||
|
"CALLCODEEcrecover2.json",
|
||||||
|
"CALLCODEEcrecover3.json",
|
||||||
|
"CALLCODEEcrecover80.json",
|
||||||
|
"CALLCODEEcrecoverH_prefixed0.json",
|
||||||
|
"CALLCODEEcrecoverR_prefixed0.json",
|
||||||
|
"CALLCODEEcrecoverS_prefixed0.json",
|
||||||
|
"CALLCODEEcrecoverV_prefixed0.json",
|
||||||
|
"CALLCODEEcrecoverV_prefixedf0.json",
|
||||||
|
"CALLCODEIdentitiy_0.json",
|
||||||
|
"CALLCODEIdentitiy_1.json",
|
||||||
|
"CALLCODEIdentity_1_nonzeroValue.json",
|
||||||
|
"CALLCODEIdentity_2.json",
|
||||||
|
"CALLCODEIdentity_3.json",
|
||||||
|
"CALLCODEIdentity_4.json",
|
||||||
|
"CALLCODEIdentity_4_gas17.json",
|
||||||
|
"CALLCODEIdentity_4_gas18.json",
|
||||||
|
"CALLCODEIdentity_5.json",
|
||||||
|
"CALLCODERipemd160_0.json",
|
||||||
|
"CALLCODERipemd160_1.json",
|
||||||
|
"CALLCODERipemd160_2.json",
|
||||||
|
"CALLCODERipemd160_3.json",
|
||||||
|
"CALLCODERipemd160_3_postfixed0.json",
|
||||||
|
"CALLCODERipemd160_3_prefixed0.json",
|
||||||
|
"CALLCODERipemd160_4.json",
|
||||||
|
"CALLCODERipemd160_4_gas719.json",
|
||||||
|
"CALLCODERipemd160_5.json",
|
||||||
|
"CALLCODESha256_0.json",
|
||||||
|
"CALLCODESha256_1.json",
|
||||||
|
"CALLCODESha256_1_nonzeroValue.json",
|
||||||
|
"CALLCODESha256_2.json",
|
||||||
|
"CALLCODESha256_3.json",
|
||||||
|
"CALLCODESha256_3_postfix0.json",
|
||||||
|
"CALLCODESha256_3_prefix0.json",
|
||||||
|
"CALLCODESha256_4.json",
|
||||||
|
"CALLCODESha256_4_gas99.json",
|
||||||
|
"CALLCODESha256_5.json",
|
||||||
|
"CallEcrecover0.json",
|
||||||
|
"CallEcrecover0_0input.json",
|
||||||
|
"CallEcrecover0_Gas2999.json",
|
||||||
|
"CallEcrecover0_NoGas.json",
|
||||||
|
"CallEcrecover0_completeReturnValue.json",
|
||||||
|
"CallEcrecover0_gas3000.json",
|
||||||
|
"CallEcrecover0_overlappingInputOutput.json",
|
||||||
|
"CallEcrecover1.json",
|
||||||
|
"CallEcrecover2.json",
|
||||||
|
"CallEcrecover3.json",
|
||||||
|
"CallEcrecover80.json",
|
||||||
|
"CallEcrecoverCheckLength.json",
|
||||||
|
"CallEcrecoverCheckLengthWrongV.json",
|
||||||
|
"CallEcrecoverH_prefixed0.json",
|
||||||
|
"CallEcrecoverR_prefixed0.json",
|
||||||
|
"CallEcrecoverS_prefixed0.json",
|
||||||
|
"CallEcrecoverV_prefixed0.json",
|
||||||
|
"CallIdentitiy_0.json",
|
||||||
|
"CallIdentitiy_1.json",
|
||||||
|
"CallIdentity_1_nonzeroValue.json",
|
||||||
|
"CallIdentity_2.json",
|
||||||
|
"CallIdentity_3.json",
|
||||||
|
"CallIdentity_4.json",
|
||||||
|
"CallIdentity_4_gas17.json",
|
||||||
|
"CallIdentity_4_gas18.json",
|
||||||
|
"CallIdentity_5.json",
|
||||||
|
"CallRipemd160_0.json",
|
||||||
|
"CallRipemd160_1.json",
|
||||||
|
"CallRipemd160_2.json",
|
||||||
|
"CallRipemd160_3.json",
|
||||||
|
"CallRipemd160_3_postfixed0.json",
|
||||||
|
"CallRipemd160_3_prefixed0.json",
|
||||||
|
"CallRipemd160_4.json",
|
||||||
|
"CallRipemd160_4_gas719.json",
|
||||||
|
"CallRipemd160_5.json",
|
||||||
|
"CallSha256_0.json",
|
||||||
|
"CallSha256_1.json",
|
||||||
|
"CallSha256_1_nonzeroValue.json",
|
||||||
|
"CallSha256_2.json",
|
||||||
|
"CallSha256_3.json",
|
||||||
|
"CallSha256_3_postfix0.json",
|
||||||
|
"CallSha256_3_prefix0.json",
|
||||||
|
"CallSha256_4.json",
|
||||||
|
"CallSha256_4_gas99.json",
|
||||||
|
"CallSha256_5.json",
|
||||||
|
"randomStatetest100.json",
|
||||||
|
"randomStatetest135.json",
|
||||||
|
"randomStatetest138.json",
|
||||||
|
"randomStatetest14.json",
|
||||||
|
"randomStatetest146.json",
|
||||||
|
"randomStatetest150.json",
|
||||||
|
"randomStatetest154.json",
|
||||||
|
"randomStatetest159.json",
|
||||||
|
"randomStatetest177.json",
|
||||||
|
"randomStatetest178.json",
|
||||||
|
"randomStatetest184.json",
|
||||||
|
"randomStatetest205.json",
|
||||||
|
"randomStatetest248.json",
|
||||||
|
"randomStatetest306.json",
|
||||||
|
"randomStatetest307.json",
|
||||||
|
"randomStatetest368.json",
|
||||||
|
"randomStatetest48.json",
|
||||||
|
"randomStatetest85.json",
|
||||||
|
"randomStatetest417.json",
|
||||||
|
"randomStatetest458.json",
|
||||||
|
"randomStatetest467.json",
|
||||||
|
"randomStatetest498.json",
|
||||||
|
"randomStatetest554.json",
|
||||||
|
"randomStatetest579.json",
|
||||||
|
"randomStatetest618.json",
|
||||||
|
"randomStatetest627.json",
|
||||||
|
"randomStatetest632.json",
|
||||||
|
"randomStatetest636.json",
|
||||||
|
"randomStatetest639.json",
|
||||||
|
"randomStatetest643.json",
|
||||||
|
"randomStatetest644.json",
|
||||||
|
"randomStatetest645.json",
|
||||||
|
"randomStatetest646.json",
|
||||||
|
"recursiveCreate.json",
|
||||||
|
"recursiveCreateReturnValue.json",
|
||||||
|
"refundSuicide50procentCap.json",
|
||||||
|
"refund_CallA.json",
|
||||||
|
"refund_CallA_notEnoughGasInCall.json",
|
||||||
|
"refund_CallToSuicideNoStorage.json",
|
||||||
|
"refund_CallToSuicideStorage.json",
|
||||||
|
"refund_CallToSuicideTwice.json",
|
||||||
|
"refund_multimpleSuicide.json",
|
||||||
|
"refund_singleSuicide.json",
|
||||||
|
"call_outsize_then_create_successful_then_returndatasize.json",
|
||||||
|
"call_then_create_successful_then_returndatasize.json",
|
||||||
|
"create_callprecompile_returndatasize.json",
|
||||||
|
"returndatacopy_0_0_following_successful_create.json",
|
||||||
|
"returndatacopy_following_create.json",
|
||||||
|
"returndatacopy_following_revert_in_create.json",
|
||||||
|
"returndatacopy_following_successful_create.json",
|
||||||
|
"returndatasize_following_successful_create.json",
|
||||||
|
"LoopCallsDepthThenRevert.json",
|
||||||
|
"LoopCallsThenRevert.json",
|
||||||
|
"LoopDelegateCallsDepthThenRevert.json",
|
||||||
|
"NashatyrevSuicideRevert.json",
|
||||||
|
"RevertDepth2.json",
|
||||||
|
"RevertDepthCreateAddressCollision.json",
|
||||||
|
"RevertDepthCreateOOG.json",
|
||||||
|
"RevertInCreateInInit.json",
|
||||||
|
"RevertOpcodeCalls.json",
|
||||||
|
"RevertOpcodeCreate.json",
|
||||||
|
"RevertOpcodeDirectCall.json",
|
||||||
|
"RevertOpcodeInCallsOnNonEmptyReturnData.json",
|
||||||
|
"RevertOpcodeInCreateReturns.json",
|
||||||
|
"RevertOpcodeInInit.json",
|
||||||
|
"RevertOpcodeMultipleSubCalls.json",
|
||||||
|
"RevertOpcodeReturn.json",
|
||||||
|
"RevertOpcodeWithBigOutputInInit.json",
|
||||||
|
"RevertPrefound.json",
|
||||||
|
"RevertPrefoundCall.json",
|
||||||
|
"RevertPrefoundEmpty.json",
|
||||||
|
"RevertPrefoundEmptyCall.json",
|
||||||
|
"RevertPrefoundEmptyOOG.json",
|
||||||
|
"RevertPrefoundOOG.json",
|
||||||
|
"RevertRemoteSubCallStorageOOG.json",
|
||||||
|
"RevertRemoteSubCallStorageOOG2.json",
|
||||||
|
"TouchToEmptyAccountRevert.json",
|
||||||
|
"TouchToEmptyAccountRevert2.json",
|
||||||
|
"TouchToEmptyAccountRevert3.json",
|
||||||
|
"CallLowLevelCreatesSolidity.json",
|
||||||
|
"ContractInheritance.json",
|
||||||
|
"CreateContractFromMethod.json",
|
||||||
|
"RecursiveCreateContracts.json",
|
||||||
|
"RecursiveCreateContractsCreate4Contracts.json",
|
||||||
|
"TestContractInteraction.json",
|
||||||
|
"TestContractSuicide.json",
|
||||||
|
"TestCryptographicFunctions.json",
|
||||||
|
"FailedCreateRevertsDeletion.json",
|
||||||
|
"JUMPDEST_Attack.json",
|
||||||
|
"JUMPDEST_AttackwithJump.json",
|
||||||
|
"StackDepthLimitSEC.json",
|
||||||
|
"deploymentError.json",
|
||||||
|
"tx_e1c174e2.json",
|
||||||
|
"stackOverflowM1DUP.json",
|
||||||
|
"ABAcalls0.json",
|
||||||
|
"ABAcalls1.json",
|
||||||
|
"ABAcalls2.json",
|
||||||
|
"ABAcalls3.json",
|
||||||
|
"ABAcallsSuicide0.json",
|
||||||
|
"ABAcallsSuicide1.json",
|
||||||
|
"Call10.json",
|
||||||
|
"CallRecursiveBomb0.json",
|
||||||
|
"CallRecursiveBomb0_OOG_atMaxCallDepth.json",
|
||||||
|
"CallRecursiveBomb1.json",
|
||||||
|
"CallRecursiveBomb2.json",
|
||||||
|
"CallRecursiveBomb3.json",
|
||||||
|
"CallRecursiveBombLog.json",
|
||||||
|
"CallRecursiveBombLog2.json",
|
||||||
|
"CallToNameRegistrator0.json",
|
||||||
|
"CallToNameRegistratorAddressTooBigLeft.json",
|
||||||
|
"CallToNameRegistratorAddressTooBigRight.json",
|
||||||
|
"CallToNameRegistratorNotMuchMemory0.json",
|
||||||
|
"CallToNameRegistratorNotMuchMemory1.json",
|
||||||
|
"CallToNameRegistratorOutOfGas.json",
|
||||||
|
"CallToNameRegistratorZeorSizeMemExpansion.json",
|
||||||
|
"CallToReturn1.json",
|
||||||
|
"CalltoReturn2.json",
|
||||||
|
"CreateHashCollision.json",
|
||||||
|
"PostToReturn1.json",
|
||||||
|
"callcodeTo0.json",
|
||||||
|
"callcodeToNameRegistrator0.json",
|
||||||
|
"callcodeToNameRegistratorAddresTooBigLeft.json",
|
||||||
|
"callcodeToNameRegistratorAddresTooBigRight.json",
|
||||||
|
"callcodeToNameRegistratorZeroMemExpanion.json",
|
||||||
|
"callcodeToReturn1.json",
|
||||||
|
"createNameRegistrator.json",
|
||||||
|
"createNameRegistratorValueTooHigh.json",
|
||||||
|
"createNameRegistratorZeroMem.json",
|
||||||
|
"createNameRegistratorZeroMem2.json",
|
||||||
|
"createNameRegistratorZeroMemExpansion.json",
|
||||||
|
"createWithInvalidOpcode.json",
|
||||||
|
"suicideCoinbase.json",
|
||||||
|
"suicideSendEtherPostDeath.json",
|
||||||
|
"testRandomTest.json",
|
||||||
|
"CreateMessageReverted.json",
|
||||||
|
"CreateMessageSuccess.json",
|
||||||
|
"CreateTransactionSuccess.json",
|
||||||
|
"EmptyTransaction2.json",
|
||||||
|
"EmptyTransaction3.json",
|
||||||
|
"InternalCallHittingGasLimitSuccess.json",
|
||||||
|
"InternlCallStoreClearsOOG.json",
|
||||||
|
"InternlCallStoreClearsSucces.json",
|
||||||
|
"Opcodes_TransactionInit.json",
|
||||||
|
"StoreClearsAndInternlCallStoreClearsOOG.json",
|
||||||
|
"StoreClearsAndInternlCallStoreClearsSuccess.json",
|
||||||
|
"StoreGasOnCreate.json",
|
||||||
|
"SuicidesAndInternlCallSuicidesBonusGasAtCall.json",
|
||||||
|
"SuicidesAndInternlCallSuicidesBonusGasAtCallFailed.json",
|
||||||
|
"SuicidesAndInternlCallSuicidesSuccess.json",
|
||||||
|
"SuicidesMixingCoinbase.json",
|
||||||
|
"TransactionFromCoinbaseHittingBlockGasLimit1.json",
|
||||||
|
"TransactionSendingToEmpty.json",
|
||||||
|
"createNameRegistratorPerTxsAfter.json",
|
||||||
|
"createNameRegistratorPerTxsAt.json",
|
||||||
|
"createNameRegistratorPerTxsBefore.json",
|
||||||
|
"createNameRegistratorPerTxsNotEnoughGasAfter.json",
|
||||||
|
"createNameRegistratorPerTxsNotEnoughGasAt.json",
|
||||||
|
"createNameRegistratorPerTxsNotEnoughGasBefore.json",
|
||||||
|
"delegatecallAfterTransition.json",
|
||||||
|
"delegatecallAtTransition.json",
|
||||||
|
"delegatecallBeforeTransition.json",
|
||||||
|
"dayLimitConstruction.json",
|
||||||
|
"dayLimitConstructionPartial.json",
|
||||||
|
"multiOwnedConstructionCorrect.json",
|
||||||
|
"walletConfirm.json",
|
||||||
|
"walletConstruction.json",
|
||||||
|
"walletConstructionPartial.json",
|
||||||
|
"ZeroValue_CALL.json",
|
||||||
|
"ZeroValue_CALLCODE.json",
|
||||||
|
"ZeroValue_CALLCODE_ToEmpty.json",
|
||||||
|
"ZeroValue_CALLCODE_ToNonZeroBalance.json",
|
||||||
|
"ZeroValue_CALLCODE_ToOneStorageKey.json",
|
||||||
|
"ZeroValue_CALL_ToEmpty.json",
|
||||||
|
"ZeroValue_CALL_ToNonZeroBalance.json",
|
||||||
|
"ZeroValue_CALL_ToOneStorageKey.json",
|
||||||
|
"ZeroValue_DELEGATECALL.json",
|
||||||
|
"ZeroValue_DELEGATECALL_ToEmpty.json",
|
||||||
|
"ZeroValue_DELEGATECALL_ToNonZeroBalance.json",
|
||||||
|
"ZeroValue_DELEGATECALL_ToOneStorageKey.json",
|
||||||
|
"pairingTest.json",
|
||||||
|
"pointAdd.json",
|
||||||
|
"pointAddTrunc.json",
|
||||||
|
"pointMulAdd.json",
|
||||||
|
"pointMulAdd2.json"]
|
||||||
|
name in allowedFailingGeneralStateTests
|
|
@ -23,80 +23,20 @@ suite "generalstate json tests":
|
||||||
jsonTest("GeneralStateTests", testFixture)
|
jsonTest("GeneralStateTests", testFixture)
|
||||||
|
|
||||||
|
|
||||||
proc stringFromBytes(x: ByteRange): string =
|
proc validateTransaction(vmState: BaseVMState, transaction: Transaction, sender: EthAddress): bool =
|
||||||
result = newString(x.len)
|
|
||||||
for i in 0 ..< x.len:
|
|
||||||
result[i] = char(x[i])
|
|
||||||
|
|
||||||
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
|
||||||
# XXX: this is a terrible mess. refactor.
|
|
||||||
var fixture: JsonNode
|
|
||||||
for label, child in fixtures:
|
|
||||||
fixture = child
|
|
||||||
break
|
|
||||||
|
|
||||||
let fenv = fixture["env"]
|
|
||||||
var emptyRlpHash = keccak256.digest(rlp.encode("").toOpenArray)
|
|
||||||
let header = BlockHeader(
|
|
||||||
coinbase: fenv{"currentCoinbase"}.getStr.parseAddress,
|
|
||||||
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
|
|
||||||
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
|
|
||||||
gasLimit: fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
|
|
||||||
timestamp: fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
|
|
||||||
stateRoot: emptyRlpHash
|
|
||||||
)
|
|
||||||
|
|
||||||
let ftrans = fixture["transaction"]
|
|
||||||
let transaction = ftrans.getFixtureTransaction
|
|
||||||
let sender = ftrans.getFixtureTransactionSender
|
|
||||||
let gas_cost = transaction.gasLimit.u256 * transaction.gasPrice.u256
|
|
||||||
|
|
||||||
var memDb = newMemDB()
|
|
||||||
var vmState = newBaseVMState(header, newBaseChainDB(newMemoryDb()))
|
|
||||||
vmState.mutateStateDB:
|
|
||||||
setupStateDB(fixture{"pre"}, db)
|
|
||||||
|
|
||||||
let currentCoinbase = fenv["currentCoinbase"].getStr.ethAddressFromHex
|
|
||||||
|
|
||||||
# XXX: https://github.com/status-im/nimbus/issues/35#issuecomment-391726518
|
# XXX: https://github.com/status-im/nimbus/issues/35#issuecomment-391726518
|
||||||
# TODO: put yellow paper ref here from that link justifying the limit (1 shl 34 is stand-in)
|
# XXX: lots of avoidable u256 construction
|
||||||
# XXX: clean up lots of avoidable u256 construction
|
|
||||||
var readOnlyDB = vmState.readOnlyStateDB
|
var readOnlyDB = vmState.readOnlyStateDB
|
||||||
let limitAndValue = transaction.gasLimit.u256 + transaction.value
|
let limitAndValue = transaction.gasLimit.u256 + transaction.value
|
||||||
if transaction.gasLimit < transaction.getFixtureIntrinsicGas or
|
let gas_cost = transaction.gasLimit.u256 * transaction.gasPrice.u256
|
||||||
transaction.gasPrice > (1 shl 34) or
|
|
||||||
limitAndValue > readOnlyDB.getBalance(sender) or
|
|
||||||
#limitAndValue > header.gasLimit.u256 or
|
|
||||||
transaction.accountNonce != readOnlyDB.getNonce(sender) or
|
|
||||||
readOnlyDB.getBalance(sender) < gas_cost:
|
|
||||||
vmState.mutateStateDb:
|
|
||||||
# pre-EIP158 (e.g., Byzantium, should ensure currentCoinbase exists)
|
|
||||||
# but in later forks, don't create at all
|
|
||||||
db.addBalance(currentCoinbase, 0.u256)
|
|
||||||
|
|
||||||
# FIXME: don't repeat this code
|
transaction.gasLimit >= transaction.getFixtureIntrinsicGas and
|
||||||
# TODO: iterate over all fixture indexes
|
transaction.gasPrice <= (1 shl 34) and
|
||||||
doAssert "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii == fixture["post"]["Homestead"][0]["hash"].getStr
|
limitAndValue <= readOnlyDB.getBalance(sender) and
|
||||||
return
|
transaction.accountNonce == readOnlyDB.getNonce(sender) and
|
||||||
|
readOnlyDB.getBalance(sender) >= gas_cost
|
||||||
|
|
||||||
# This address might not have code. This is fine.
|
proc setupComputation(header: BlockHeader, vmState: var BaseVMState, transaction: Transaction, sender: EthAddress, code: seq[byte]) : BaseComputation =
|
||||||
let code = fixture["pre"].getFixtureCode(transaction.to)
|
|
||||||
|
|
||||||
# TODO: replace with cachingDb or similar approach; necessary
|
|
||||||
# when calls/subcalls/etc come in, too.
|
|
||||||
var foo = vmState.readOnlyStateDB
|
|
||||||
let storageRoot = foo.getStorageRoot(transaction.to)
|
|
||||||
|
|
||||||
vmState.mutateStateDB:
|
|
||||||
# TODO: combine some of these
|
|
||||||
# Also, in general, map out/etc the whole vmState.mutateStateDB flow set
|
|
||||||
db.setBalance(sender, db.getBalance(sender) - gas_cost)
|
|
||||||
db.setNonce(sender, db.getNonce(sender) + 1)
|
|
||||||
db.addBalance(transaction.to, transaction.value)
|
|
||||||
db.setBalance(sender, db.getBalance(sender) - transaction.value)
|
|
||||||
|
|
||||||
# build_message (Py-EVM)
|
|
||||||
# FIXME: detect contact creation address; only run if transaction.to addr has .code
|
|
||||||
let message = newMessage(
|
let message = newMessage(
|
||||||
gas = transaction.gasLimit - transaction.getFixtureIntrinsicGas,
|
gas = transaction.gasLimit - transaction.getFixtureIntrinsicGas,
|
||||||
gasPrice = transaction.gasPrice,
|
gasPrice = transaction.gasPrice,
|
||||||
|
@ -109,20 +49,53 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||||
createAddress = transaction.to))
|
createAddress = transaction.to))
|
||||||
|
|
||||||
# doAssert not message.isCreate
|
# doAssert not message.isCreate
|
||||||
|
result = newBaseComputation(vmState, header.blockNumber, message)
|
||||||
|
result.precompiles = initTable[string, Opcode]()
|
||||||
|
doAssert result.isOriginComputation
|
||||||
|
|
||||||
var computation = newBaseComputation(vmState, header.blockNumber, message)
|
proc execComputation(computation: var BaseComputation, vmState: var BaseVMState): bool =
|
||||||
computation.precompiles = initTable[string, Opcode]()
|
|
||||||
|
|
||||||
doAssert computation.isOriginComputation
|
|
||||||
|
|
||||||
# TODO: delineate here during refactoring; try block not low-hanging fruit to split
|
|
||||||
# until transactional db comes in
|
|
||||||
try:
|
try:
|
||||||
computation.executeOpcodes()
|
computation.executeOpcodes()
|
||||||
|
vmState.mutateStateDB:
|
||||||
|
for deletedAccount in computation.getAccountsForDeletion:
|
||||||
|
db.deleteAccount deletedAccount
|
||||||
|
|
||||||
let deletedAccounts = computation.getAccountsForDeletion
|
result = not computation.isError
|
||||||
computation.gasMeter.refundGas(24_000 * deletedAccounts.len)
|
except ValueError:
|
||||||
|
result = false
|
||||||
|
|
||||||
|
proc testFixtureIndexes(header: BlockHeader, pre: JsonNode, transaction: Transaction, sender: EthAddress, expectedHash: string) =
|
||||||
|
var vmState = newBaseVMState(header, newBaseChainDB(newMemoryDb()))
|
||||||
|
vmState.mutateStateDB:
|
||||||
|
setupStateDB(pre, db)
|
||||||
|
|
||||||
|
defer:
|
||||||
|
#echo vmState.readOnlyStateDB.dumpAccount("c94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
||||||
|
doAssert "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii == expectedHash
|
||||||
|
|
||||||
|
if not validateTransaction(vmState, transaction, sender):
|
||||||
|
vmState.mutateStateDB:
|
||||||
|
# pre-EIP158 (e.g., Byzantium) should ensure currentCoinbase exists
|
||||||
|
# in later forks, don't create at all
|
||||||
|
db.addBalance(header.coinbase, 0.u256)
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: replace with cachingDb or similar approach; necessary
|
||||||
|
# when calls/subcalls/etc come in, too.
|
||||||
|
var readOnly = vmState.readOnlyStateDB
|
||||||
|
let storageRoot = readOnly.getStorageRoot(transaction.to)
|
||||||
|
|
||||||
|
let gas_cost = transaction.gasLimit.u256 * transaction.gasPrice.u256
|
||||||
|
vmState.mutateStateDB:
|
||||||
|
db.setBalance(sender, db.getBalance(sender) - gas_cost)
|
||||||
|
db.setNonce(sender, db.getNonce(sender) + 1)
|
||||||
|
db.addBalance(transaction.to, transaction.value)
|
||||||
|
db.setBalance(sender, db.getBalance(sender) - transaction.value)
|
||||||
|
|
||||||
|
var computation = setupComputation(header, vmState, transaction, sender,
|
||||||
|
pre.getFixtureCode(transaction.to))
|
||||||
|
|
||||||
|
if execComputation(computation, vmState):
|
||||||
let
|
let
|
||||||
gasRemaining = computation.gasMeter.gasRemaining.u256
|
gasRemaining = computation.gasMeter.gasRemaining.u256
|
||||||
gasRefunded = computation.gasMeter.gasRefunded.u256
|
gasRefunded = computation.gasMeter.gasRefunded.u256
|
||||||
|
@ -130,39 +103,46 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||||
gasRefund = min(gasRefunded, gasUsed div 2)
|
gasRefund = min(gasRefunded, gasUsed div 2)
|
||||||
gasRefundAmount = (gasRefund + gasRemaining) * transaction.gasPrice.u256
|
gasRefundAmount = (gasRefund + gasRemaining) * transaction.gasPrice.u256
|
||||||
|
|
||||||
# TODO: investigate if these mutate blocks can be combined
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
for deletedAccount in deletedAccounts:
|
if header.coinbase notin computation.getAccountsForDeletion:
|
||||||
db.deleteAccount deletedAccount
|
db.setBalance(header.coinbase, db.getBalance(header.coinbase) - gasRefundAmount)
|
||||||
|
db.addBalance(header.coinbase, gas_cost)
|
||||||
if not computation.isError:
|
db.addBalance(sender, gasRefundAmount)
|
||||||
vmState.mutateStateDB:
|
# TODO: only here does one commit, with some nuance/caveat
|
||||||
if currentCoinbase notin deletedAccounts:
|
else:
|
||||||
db.setBalance(currentCoinbase, db.getBalance(currentCoinbase) - gasRefundAmount)
|
|
||||||
db.addBalance(currentCoinbase, gas_cost)
|
|
||||||
db.addBalance(sender, gasRefundAmount)
|
|
||||||
# TODO: only here does one commit, with some nuance/caveat
|
|
||||||
else:
|
|
||||||
# XXX: both error paths are intentionally indentical, for merging, with refactoring
|
|
||||||
# TODO: replace with transactional commit/revert state (foo.revert or implicit)
|
|
||||||
vmState.mutateStateDB:
|
|
||||||
# XXX: the coinbase has to be committed; the rest are basically reverts
|
|
||||||
db.setBalance(transaction.to, db.getBalance(transaction.to) - transaction.value)
|
|
||||||
db.addBalance(sender, transaction.value)
|
|
||||||
db.setStorageRoot(transaction.to, storageRoot)
|
|
||||||
db.addBalance(currentCoinbase, gas_cost)
|
|
||||||
except ValueError:
|
|
||||||
# TODO: replace with transactional commit/revert state (foo.revert or implicit)
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
# XXX: the coinbase has to be committed; the rest are basically reverts
|
# XXX: the coinbase has to be committed; the rest are basically reverts
|
||||||
db.setBalance(transaction.to, db.getBalance(transaction.to) - transaction.value)
|
db.setBalance(transaction.to, db.getBalance(transaction.to) - transaction.value)
|
||||||
db.addBalance(sender, transaction.value)
|
db.addBalance(sender, transaction.value)
|
||||||
db.setStorageRoot(transaction.to, storageRoot)
|
db.setStorageRoot(transaction.to, storageRoot)
|
||||||
db.addBalance(currentCoinbase, gas_cost)
|
db.addBalance(header.coinbase, gas_cost)
|
||||||
|
|
||||||
#echo vmState.readOnlyStateDB.dumpAccount("b94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
|
||||||
#echo vmState.readOnlyStateDB.dumpAccount("a94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
var fixture: JsonNode
|
||||||
#echo vmState.readOnlyStateDB.dumpAccount("c94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
for label, child in fixtures:
|
||||||
|
fixture = child
|
||||||
|
break
|
||||||
|
|
||||||
# TODO: do this right
|
let fenv = fixture["env"]
|
||||||
doAssert "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii == fixture["post"]["Homestead"][0]["hash"].getStr
|
var emptyRlpHash = keccak256.digest(rlp.encode("").toOpenArray)
|
||||||
|
let header = BlockHeader(
|
||||||
|
coinbase: fenv["currentCoinbase"].getStr.ethAddressFromHex,
|
||||||
|
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
|
||||||
|
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
|
||||||
|
gasLimit: fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
|
||||||
|
timestamp: fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
|
||||||
|
stateRoot: emptyRlpHash
|
||||||
|
)
|
||||||
|
|
||||||
|
let ftrans = fixture["transaction"]
|
||||||
|
for expectation in fixture["post"]["Homestead"]:
|
||||||
|
let
|
||||||
|
expectedHash = expectation["hash"].getStr
|
||||||
|
indexes = expectation["indexes"]
|
||||||
|
dataIndex = indexes["data"].getInt
|
||||||
|
gasIndex = indexes["gas"].getInt
|
||||||
|
valueIndex = indexes["value"].getInt
|
||||||
|
let transaction = ftrans.getFixtureTransaction(dataIndex, gasIndex, valueIndex)
|
||||||
|
let sender = ftrans.getFixtureTransactionSender
|
||||||
|
echo "testing fixture indexes dataIndex = ", dataIndex, ", gasIndex = ", gasIndex, ", and valueIndex = ", valueIndex
|
||||||
|
testFixtureIndexes(header, fixture["pre"], transaction, sender, expectedHash)
|
||||||
|
|
|
@ -11,7 +11,8 @@ import
|
||||||
../nimbus/[vm_state, constants],
|
../nimbus/[vm_state, constants],
|
||||||
../nimbus/db/[db_chain, state_db],
|
../nimbus/db/[db_chain, state_db],
|
||||||
../nimbus/transaction,
|
../nimbus/transaction,
|
||||||
../nimbus/vm/interpreter/[gas_costs, vm_forks]
|
../nimbus/vm/interpreter/[gas_costs, vm_forks],
|
||||||
|
../tests/test_generalstate_failing
|
||||||
|
|
||||||
type
|
type
|
||||||
Status* {.pure.} = enum OK, Fail, Skip
|
Status* {.pure.} = enum OK, Fail, Skip
|
||||||
|
@ -31,10 +32,29 @@ func slowTest*(folder: string, name: string): bool =
|
||||||
"CallToNameRegistratorMemOOGAndInsufficientBalance.json",
|
"CallToNameRegistratorMemOOGAndInsufficientBalance.json",
|
||||||
"CallToNameRegistratorTooMuchMemory0.json"]
|
"CallToNameRegistratorTooMuchMemory0.json"]
|
||||||
|
|
||||||
|
func failIn32Bits(folder, name: string): bool =
|
||||||
|
# XXX: maybe related to int32.high being 0 on 32-bits
|
||||||
|
return name in @[
|
||||||
|
"randomStatetest94.json",
|
||||||
|
"calldatacopy_dejavu.json",
|
||||||
|
"calldatacopy_dejavu2.json",
|
||||||
|
"codecopy_dejavu.json",
|
||||||
|
"codecopy_dejavu2.json",
|
||||||
|
"extcodecopy_dejavu.json",
|
||||||
|
"log1_dejavu.json",
|
||||||
|
"log2_dejavu.json",
|
||||||
|
"log3_dejavu.json",
|
||||||
|
"log4_dejavu.json",
|
||||||
|
"mload_dejavu.json",
|
||||||
|
"mstore_dejavu.json",
|
||||||
|
"mstroe8_dejavu.json",
|
||||||
|
"sha3_dejavu.json"]
|
||||||
|
|
||||||
func validTest*(folder: string, name: string): bool =
|
func validTest*(folder: string, name: string): bool =
|
||||||
# tests we want to skip or which segfault will be skipped here
|
# tests we want to skip or which segfault will be skipped here
|
||||||
result = (folder != "vmPerformance" or "loop" notin name) and
|
result = (folder != "vmPerformance" or "loop" notin name) and
|
||||||
(not slowTest(folder, name) and
|
(not slowTest(folder, name) and
|
||||||
|
# TODO: check whether these are still useful
|
||||||
name notin @["static_Call1024BalanceTooLow.json",
|
name notin @["static_Call1024BalanceTooLow.json",
|
||||||
"Call1024BalanceTooLow.json", "ExtCodeCopyTests.json"])
|
"Call1024BalanceTooLow.json", "ExtCodeCopyTests.json"])
|
||||||
|
|
||||||
|
@ -63,7 +83,6 @@ macro jsonTest*(s: static[string], handler: untyped): untyped =
|
||||||
name = newIdentNode"name"
|
name = newIdentNode"name"
|
||||||
formatted = newStrLitNode"{symbol[final]} {name:<64}{$final}{'\n'}"
|
formatted = newStrLitNode"{symbol[final]} {name:<64}{$final}{'\n'}"
|
||||||
result = quote:
|
result = quote:
|
||||||
var z = 0
|
|
||||||
var filenames: seq[(string, string, string)] = @[]
|
var filenames: seq[(string, string, string)] = @[]
|
||||||
var status = initOrderedTable[string, OrderedTable[string, Status]]()
|
var status = initOrderedTable[string, OrderedTable[string, Status]]()
|
||||||
for filename in walkDirRec("tests" / "fixtures" / `s`):
|
for filename in walkDirRec("tests" / "fixtures" / `s`):
|
||||||
|
@ -79,10 +98,14 @@ macro jsonTest*(s: static[string], handler: untyped): untyped =
|
||||||
test filename:
|
test filename:
|
||||||
echo folder, name
|
echo folder, name
|
||||||
status[folder][name] = Status.FAIL
|
status[folder][name] = Status.FAIL
|
||||||
`handler`(parseJSON(readFile(filename)), `testStatusIMPL`)
|
try:
|
||||||
if `testStatusIMPL` == OK:
|
`handler`(parseJSON(readFile(filename)), `testStatusIMPL`)
|
||||||
status[folder][name] = Status.OK
|
if `testStatusIMPL` == OK:
|
||||||
z += 1
|
status[folder][name] = Status.OK
|
||||||
|
except AssertionError:
|
||||||
|
status[folder][name] = Status.FAIL
|
||||||
|
if not allowedFailingGeneralStateTest(folder, name) and not failIn32Bits(folder, name):
|
||||||
|
raise
|
||||||
|
|
||||||
status.sort do (a: (string, OrderedTable[string, Status]),
|
status.sort do (a: (string, OrderedTable[string, Status]),
|
||||||
b: (string, OrderedTable[string, Status])) -> int: cmp(a[0], b[0])
|
b: (string, OrderedTable[string, Status])) -> int: cmp(a[0], b[0])
|
||||||
|
@ -113,7 +136,6 @@ macro jsonTest*(s: static[string], handler: untyped): untyped =
|
||||||
|
|
||||||
func ethAddressFromHex*(s: string): EthAddress = hexToByteArray(s, result)
|
func ethAddressFromHex*(s: string): EthAddress = hexToByteArray(s, result)
|
||||||
|
|
||||||
# XXX should probably be part of hexToSeqByte
|
|
||||||
func safeHexToSeqByte*(hexStr: string): seq[byte] =
|
func safeHexToSeqByte*(hexStr: string): seq[byte] =
|
||||||
if hexStr == "":
|
if hexStr == "":
|
||||||
@[]
|
@[]
|
||||||
|
@ -169,21 +191,18 @@ func getHexadecimalInt*(j: JsonNode): int64 =
|
||||||
data = fromHex(StUInt[64], j.getStr)
|
data = fromHex(StUInt[64], j.getStr)
|
||||||
result = cast[int64](data)
|
result = cast[int64](data)
|
||||||
|
|
||||||
proc getFixtureTransaction*(j: JsonNode): Transaction =
|
proc getFixtureTransaction*(j: JsonNode, dataIndex, gasIndex, valueIndex: int): Transaction =
|
||||||
var transaction : Transaction
|
result.accountNonce = j["nonce"].getStr.parseHexInt.AccountNonce
|
||||||
transaction.accountNonce = j["nonce"].getStr.parseHexInt.AccountNonce
|
result.gasPrice = j["gasPrice"].getStr.parseHexInt
|
||||||
transaction.gasPrice = j["gasPrice"].getStr.parseHexInt
|
result.gasLimit = j["gasLimit"][gasIndex].getStr.parseHexInt
|
||||||
transaction.gasLimit = j["gasLimit"][0].getStr.parseHexInt
|
|
||||||
|
|
||||||
# Another distinct case "" as special hex string, but at least here,
|
# Another distinct case "" as special hex string, but at least here,
|
||||||
# it has some semantic meaning in Ethereum -- contract creation. The
|
# it has some semantic meaning in Ethereum -- contract creation. The
|
||||||
# hex parsing routine tripping over this is at least the third.
|
# hex parsing routine tripping over this is at least the third.
|
||||||
let rawTo = j["to"].getStr
|
let rawTo = j["to"].getStr
|
||||||
transaction.to = (if rawTo == "": "0x" else: rawTo).parseAddress
|
result.to = (if rawTo == "": "0x" else: rawTo).parseAddress
|
||||||
transaction.value = j["value"][0].getStr.parseHexInt.u256
|
result.value = fromHex(UInt256, j["value"][valueIndex].getStr)
|
||||||
transaction.payload = j["data"][0].getStr.safeHexToSeqByte
|
result.payload = j["data"][dataIndex].getStr.safeHexToSeqByte
|
||||||
|
|
||||||
return transaction
|
|
||||||
|
|
||||||
proc getFixtureTransactionSender*(j: JsonNode): EthAddress =
|
proc getFixtureTransactionSender*(j: JsonNode): EthAddress =
|
||||||
var secretKey = j["secretKey"].getStr
|
var secretKey = j["secretKey"].getStr
|
||||||
|
@ -191,8 +210,14 @@ proc getFixtureTransactionSender*(j: JsonNode): EthAddress =
|
||||||
let privateKey = initPrivateKey(secretKey)
|
let privateKey = initPrivateKey(secretKey)
|
||||||
|
|
||||||
var pubKey: PublicKey
|
var pubKey: PublicKey
|
||||||
let transaction = j.getFixtureTransaction
|
let transaction = j.getFixtureTransaction(0, 0, 0)
|
||||||
transaction.getSender
|
if recoverSignatureKey(signMessage(privateKey, transaction.rlpEncode.toOpenArray),
|
||||||
|
transaction.txHashNoSignature.data,
|
||||||
|
pubKey) == EthKeysStatus.Success:
|
||||||
|
return pubKey.toCanonicalAddress()
|
||||||
|
else:
|
||||||
|
# XXX: appropriate failure mode; probably raise something
|
||||||
|
discard
|
||||||
|
|
||||||
func getFixtureCode*(pre: JsonNode, targetAccount: EthAddress) : seq[byte] =
|
func getFixtureCode*(pre: JsonNode, targetAccount: EthAddress) : seq[byte] =
|
||||||
# XXX: Workaround for broken setCode/getCode. Remove when feasible.
|
# XXX: Workaround for broken setCode/getCode. Remove when feasible.
|
||||||
|
|
Loading…
Reference in New Issue