implement aleth/geth/parity compatibility mode -- 100% pass test
This commit is contained in:
parent
4a786d8cf7
commit
2fbabd25a4
|
@ -796,7 +796,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
|||
+ CreateMessageRevertedOOGInInit.json OK
|
||||
+ RevertDepthCreate2OOG.json OK
|
||||
+ RevertDepthCreateAddressCollision.json OK
|
||||
RevertInCreateInInitCreate2.json Skip
|
||||
+ RevertInCreateInInitCreate2.json OK
|
||||
+ RevertOpcodeCreate.json OK
|
||||
+ RevertOpcodeInCreateReturnsCreate2.json OK
|
||||
+ call_outsize_then_create2_successful_then_returndatasize.json OK
|
||||
|
@ -822,7 +822,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
|||
+ returndatacopy_following_successful_create.json OK
|
||||
+ returndatasize_following_successful_create.json OK
|
||||
```
|
||||
OK: 42/44 Fail: 0/44 Skip: 2/44
|
||||
OK: 43/44 Fail: 0/44 Skip: 1/44
|
||||
## stCreateTest
|
||||
```diff
|
||||
+ CREATE_AcreateB_BSuicide_BStore.json OK
|
||||
|
@ -2074,7 +2074,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
|||
+ RevertDepthCreateAddressCollision.json OK
|
||||
+ RevertDepthCreateOOG.json OK
|
||||
+ RevertInCallCode.json OK
|
||||
RevertInCreateInInit.json Skip
|
||||
+ RevertInCreateInInit.json OK
|
||||
+ RevertInDelegateCall.json OK
|
||||
+ RevertInStaticCall.json OK
|
||||
+ RevertOnEmptyStack.json OK
|
||||
|
@ -2109,7 +2109,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
|||
+ TouchToEmptyAccountRevert2.json OK
|
||||
+ TouchToEmptyAccountRevert3.json OK
|
||||
```
|
||||
OK: 39/45 Fail: 0/45 Skip: 6/45
|
||||
OK: 40/45 Fail: 0/45 Skip: 5/45
|
||||
## stSLoadTest
|
||||
```diff
|
||||
+ sloadGasCost.json OK
|
||||
|
@ -2117,7 +2117,7 @@ OK: 39/45 Fail: 0/45 Skip: 6/45
|
|||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||
## stSStoreTest
|
||||
```diff
|
||||
InitCollision.json Skip
|
||||
+ InitCollision.json OK
|
||||
+ InitCollisionNonZeroNonce.json OK
|
||||
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
||||
+ sstore_0to0.json OK
|
||||
|
@ -2145,7 +2145,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
|||
+ sstore_changeFromExternalCallInInitCode.json OK
|
||||
+ sstore_gasLeft.json OK
|
||||
```
|
||||
OK: 26/27 Fail: 0/27 Skip: 1/27
|
||||
OK: 27/27 Fail: 0/27 Skip: 0/27
|
||||
## stSelfBalance
|
||||
```diff
|
||||
+ selfBalance.json OK
|
||||
|
@ -3028,4 +3028,4 @@ OK: 133/133 Fail: 0/133 Skip: 0/133
|
|||
OK: 130/130 Fail: 0/130 Skip: 0/130
|
||||
|
||||
---TOTAL---
|
||||
OK: 2622/2730 Fail: 0/2730 Skip: 108/2730
|
||||
OK: 2625/2730 Fail: 0/2730 Skip: 105/2730
|
||||
|
|
|
@ -393,7 +393,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
|||
+ CreateMessageRevertedOOGInInit.json OK
|
||||
+ RevertDepthCreate2OOG.json OK
|
||||
+ RevertDepthCreateAddressCollision.json OK
|
||||
RevertInCreateInInitCreate2.json Skip
|
||||
+ RevertInCreateInInitCreate2.json OK
|
||||
+ RevertOpcodeCreate.json OK
|
||||
+ RevertOpcodeInCreateReturnsCreate2.json OK
|
||||
+ call_outsize_then_create2_successful_then_returndatasize.json OK
|
||||
|
@ -419,7 +419,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
|||
+ returndatacopy_following_successful_create.json OK
|
||||
+ returndatasize_following_successful_create.json OK
|
||||
```
|
||||
OK: 42/44 Fail: 0/44 Skip: 2/44
|
||||
OK: 43/44 Fail: 0/44 Skip: 1/44
|
||||
## stCreateTest
|
||||
```diff
|
||||
+ CREATE_AcreateB_BSuicide_BStore.json OK
|
||||
|
@ -1671,7 +1671,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
|||
+ RevertDepthCreateAddressCollision.json OK
|
||||
+ RevertDepthCreateOOG.json OK
|
||||
+ RevertInCallCode.json OK
|
||||
RevertInCreateInInit.json Skip
|
||||
+ RevertInCreateInInit.json OK
|
||||
+ RevertInDelegateCall.json OK
|
||||
+ RevertInStaticCall.json OK
|
||||
+ RevertOnEmptyStack.json OK
|
||||
|
@ -1706,7 +1706,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
|||
+ TouchToEmptyAccountRevert2.json OK
|
||||
+ TouchToEmptyAccountRevert3.json OK
|
||||
```
|
||||
OK: 39/45 Fail: 0/45 Skip: 6/45
|
||||
OK: 40/45 Fail: 0/45 Skip: 5/45
|
||||
## stSLoadTest
|
||||
```diff
|
||||
+ sloadGasCost.json OK
|
||||
|
@ -1714,7 +1714,7 @@ OK: 39/45 Fail: 0/45 Skip: 6/45
|
|||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||
## stSStoreTest
|
||||
```diff
|
||||
InitCollision.json Skip
|
||||
+ InitCollision.json OK
|
||||
+ InitCollisionNonZeroNonce.json OK
|
||||
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
||||
+ sstore_0to0.json OK
|
||||
|
@ -1742,7 +1742,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
|||
+ sstore_changeFromExternalCallInInitCode.json OK
|
||||
+ sstore_gasLeft.json OK
|
||||
```
|
||||
OK: 26/27 Fail: 0/27 Skip: 1/27
|
||||
OK: 27/27 Fail: 0/27 Skip: 0/27
|
||||
## stSelfBalance
|
||||
```diff
|
||||
+ selfBalance.json OK
|
||||
|
@ -2625,4 +2625,4 @@ OK: 133/133 Fail: 0/133 Skip: 0/133
|
|||
OK: 130/130 Fail: 0/130 Skip: 0/130
|
||||
|
||||
---TOTAL---
|
||||
OK: 2305/2411 Fail: 0/2411 Skip: 106/2411
|
||||
OK: 2308/2411 Fail: 0/2411 Skip: 103/2411
|
||||
|
|
|
@ -8,16 +8,49 @@
|
|||
import
|
||||
strformat,
|
||||
chronicles, eth/[common, rlp], eth/trie/[hexary, db, trie_defs],
|
||||
../constants, ../utils, storage_types
|
||||
../constants, ../utils, storage_types, sets
|
||||
|
||||
logScope:
|
||||
topics = "state_db"
|
||||
|
||||
# aleth/geth/parity compatibility mode:
|
||||
#
|
||||
# affected test cases both in GST and BCT:
|
||||
# - stSStoreTest\InitCollision.json
|
||||
# - stRevertTest\RevertInCreateInInit.json
|
||||
# - stCreate2\RevertInCreateInInitCreate2.json
|
||||
#
|
||||
# pyEVM sided with original Nimbus EVM
|
||||
#
|
||||
# implementation difference:
|
||||
# Aleth/geth/parity using accounts cache.
|
||||
# When contract creation happened on an existing
|
||||
# but 'empty' account with non empty storage will
|
||||
# get new empty storage root.
|
||||
# Aleth cs. only clear the storage cache while both pyEVM
|
||||
# and Nimbus will modify the state trie.
|
||||
# During the next SSTORE call, aleth cs. calculate
|
||||
# gas used based on this cached 'original storage value'.
|
||||
# In other hand pyEVM and Nimbus will fetch
|
||||
# 'original storage value' from state trie.
|
||||
#
|
||||
# Both Yellow Paper and EIP2200 are not clear about this
|
||||
# situation but since aleth/geth/and parity implement this
|
||||
# behaviour, we perhaps also need to implement it.
|
||||
#
|
||||
# TODO: should this compatibility mode enabled via
|
||||
# compile time switch, runtime switch, or just hard coded
|
||||
# it?
|
||||
const
|
||||
aleth_compat = true
|
||||
|
||||
type
|
||||
AccountStateDB* = ref object
|
||||
trie: SecureHexaryTrie
|
||||
originalRoot: KeccakHash # will be updated for every transaction
|
||||
transactionID: TransactionID
|
||||
when aleth_compat:
|
||||
cleared: HashSet[EthAddress]
|
||||
|
||||
ReadOnlyStateDB* = distinct AccountStateDB
|
||||
|
||||
|
@ -36,6 +69,8 @@ proc newAccountStateDB*(backingStore: TrieDatabaseRef,
|
|||
result.trie = initSecureHexaryTrie(backingStore, root, pruneTrie)
|
||||
result.originalRoot = root
|
||||
result.transactionID = backingStore.getTransactionID()
|
||||
when aleth_compat:
|
||||
result.cleared = initHashSet[EthAddress]()
|
||||
|
||||
template createRangeFromAddress(address: EthAddress): ByteRange =
|
||||
## XXX: The name of this proc is intentionally long, because it
|
||||
|
@ -97,6 +132,8 @@ proc clearStorage*(db: var AccountStateDB, address: EthAddress) =
|
|||
var account = db.getAccount(address)
|
||||
account.storageRoot = emptyRlpHash
|
||||
db.setAccount(address, account)
|
||||
when aleth_compat:
|
||||
db.cleared.incl address
|
||||
|
||||
proc getStorageRoot*(db: AccountStateDB, address: EthAddress): Hash256 =
|
||||
var account = db.getAccount(address)
|
||||
|
@ -216,9 +253,15 @@ proc isDeadAccount*(db: AccountStateDB, address: EthAddress): bool =
|
|||
proc getCommittedStorage*(db: AccountStateDB, address: EthAddress, slot: UInt256): UInt256 =
|
||||
let tmpHash = db.rootHash
|
||||
db.rootHash = db.originalRoot
|
||||
var exists: bool
|
||||
shortTimeReadOnly(trieDB(db), db.transactionID):
|
||||
(result, exists) = db.getStorage(address, slot)
|
||||
when aleth_compat:
|
||||
if address in db.cleared:
|
||||
debug "Forced contract creation on existing account detected", address
|
||||
result = 0.u256
|
||||
else:
|
||||
result = db.getStorage(address, slot)[0]
|
||||
else:
|
||||
result = db.getStorage(address, slot)[0]
|
||||
db.rootHash = tmpHash
|
||||
|
||||
proc updateOriginalRoot*(db: AccountStateDB) =
|
||||
|
@ -228,6 +271,9 @@ proc updateOriginalRoot*(db: AccountStateDB) =
|
|||
# transactionID, it will be handled elsewhere
|
||||
db.transactionID = trieDB(db).getTransactionID()
|
||||
|
||||
when aleth_compat:
|
||||
db.cleared.clear()
|
||||
|
||||
proc rootHash*(db: ReadOnlyStateDB): KeccakHash {.borrow.}
|
||||
proc getAccount*(db: ReadOnlyStateDB, address: EthAddress): Account {.borrow.}
|
||||
proc getCodeHash*(db: ReadOnlyStateDB, address: EthAddress): Hash256 {.borrow.}
|
||||
|
|
|
@ -98,14 +98,6 @@ func skipNewGSTTests*(folder: string, name: string): bool =
|
|||
if skipGSTTests(folder, name):
|
||||
return true
|
||||
|
||||
name in @[
|
||||
# py-evm claims these tests are incorrect
|
||||
# nimbus also agree
|
||||
"RevertInCreateInInit.json",
|
||||
"RevertInCreateInInitCreate2.json",
|
||||
"InitCollision.json"
|
||||
]
|
||||
|
||||
func skipVMTests*(folder: string, name: string): bool =
|
||||
result = (folder == "vmPerformance" and "loop" in name)
|
||||
|
||||
|
@ -126,13 +118,6 @@ func skipNewBCTests*(folder: string, name: string): bool =
|
|||
return true
|
||||
|
||||
name in @[
|
||||
# Istanbul bc tests
|
||||
# py-evm claims these tests are incorrect
|
||||
# nimbus also agree
|
||||
"RevertInCreateInInit.json",
|
||||
"RevertInCreateInInitCreate2.json",
|
||||
"InitCollision.json",
|
||||
|
||||
# BC huge memory consumption
|
||||
"randomStatetest94.json",
|
||||
"DelegateCallSpam.json"
|
||||
|
|
Loading…
Reference in New Issue