fix storage clearing

This commit is contained in:
Sina Mahmoodi 2023-08-03 16:20:17 +02:00
parent c5e33fac0e
commit d4e332e268
3 changed files with 129 additions and 0 deletions

View file

@ -418,6 +418,15 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
return stateObject
}
// clearStorageCache clears the various storage caches
// belonging to the state object.
// It is only used for RPC.
func (s *stateObject) clearStorageCache() {
s.dirtyStorage = make(Storage)
s.originStorage = make(Storage)
s.pendingStorage = make(Storage)
}
//
// Attribute accessors
//

View file

@ -448,6 +448,9 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
// to a previous incarnation of the object.
s.stateObjectsDestruct[addr] = struct{}{}
stateObject := s.GetOrNewStateObject(addr)
// If object was already in memory, it might have cached
// storage slots. These should be cleared.
stateObject.clearStorageCache()
for k, v := range storage {
stateObject.SetState(s.db, k, v)
}

View file

@ -640,6 +640,7 @@ func TestMulticallV1(t *testing.T) {
genBlocks = 10
signer = types.HomesteadSigner{}
cac = common.HexToAddress("0x0000000000000000000000000000000000000cac")
bab = common.HexToAddress("0x0000000000000000000000000000000000000bab")
coinbase = "0x000000000000000000000000000000000000ffff"
genesis = &core.Genesis{
Config: params.TestChainConfig,
@ -655,6 +656,30 @@ func TestMulticallV1(t *testing.T) {
// }
// }
cac: {Balance: big.NewInt(params.Ether), Code: common.Hex2Bytes("610dad80ff")},
bab: {
Balance: big.NewInt(1),
// object "Test" {
// code {
// let value1 := sload(1)
// let value2 := sload(2)
//
// // Shift value1 by 128 bits to the left by multiplying it with 2^128
// value1 := mul(value1, 0x100000000000000000000000000000000)
//
// // Concatenate value1 and value2
// let concatenatedValue := add(value1, value2)
//
// // Store the result in memory and return it
// mstore(0, concatenatedValue)
// return(0, 0x20)
// }
// }
Code: common.FromHex("0x600154600254700100000000000000000000000000000000820291508082018060005260206000f3"),
Storage: map[common.Hash]common.Hash{
common.BigToHash(big.NewInt(1)): common.BigToHash(big.NewInt(10)),
common.BigToHash(big.NewInt(2)): common.BigToHash(big.NewInt(12)),
},
},
},
}
n10hash = crypto.Keccak256Hash([]byte{0xa}).Hex()
@ -1195,6 +1220,11 @@ func TestMulticallV1(t *testing.T) {
// }
Input: hex2Bytes("610cac610dad600082311115601357600080fd5b6000823b1115602157600080fd5b6000813103602e57600080fd5b5050"),
}},
}, {
Calls: []TransactionArgs{{
From: &accounts[0].addr,
Input: hex2Bytes("610cac610dad600082311115601357600080fd5b6000823b1115602157600080fd5b6000813103602e57600080fd5b5050"),
}},
}},
want: []blockRes{{
Number: "0xa",
@ -1213,6 +1243,18 @@ func TestMulticallV1(t *testing.T) {
Logs: []types.Log{},
Status: "0x1",
}},
}, {
Number: "0xa",
Hash: n10hash,
GasLimit: "0x47e7c4",
GasUsed: "0xe6d9",
FeeRecipient: coinbase,
Calls: []callRes{{
ReturnValue: "0x",
GasUsed: "0xe6d9",
Logs: []types.Log{},
Status: "0x1",
}},
}},
},
// Enable validation checks.
@ -1242,6 +1284,76 @@ func TestMulticallV1(t *testing.T) {
}},
}},
},
// Clear storage.
{
name: "clear-storage",
tag: latest,
blocks: []CallBatch{{
StateOverrides: &StateOverride{
randomAccounts[2].addr: {
Code: newBytes(genesis.Alloc[bab].Code),
StateDiff: &map[common.Hash]common.Hash{
common.BigToHash(big.NewInt(1)): common.BigToHash(big.NewInt(2)),
common.BigToHash(big.NewInt(2)): common.BigToHash(big.NewInt(3)),
},
},
bab: {
State: &map[common.Hash]common.Hash{
common.BigToHash(big.NewInt(1)): common.BigToHash(big.NewInt(1)),
},
},
},
Calls: []TransactionArgs{{
From: &accounts[0].addr,
To: &randomAccounts[2].addr,
}, {
From: &accounts[0].addr,
To: &bab,
}},
}, {
StateOverrides: &StateOverride{
randomAccounts[2].addr: {
State: &map[common.Hash]common.Hash{
common.BigToHash(big.NewInt(1)): common.BigToHash(big.NewInt(5)),
},
},
},
Calls: []TransactionArgs{{
From: &accounts[0].addr,
To: &randomAccounts[2].addr,
}},
}},
want: []blockRes{{
Number: "0xa",
Hash: n10hash,
GasLimit: "0x47e7c4",
GasUsed: "0xc542",
FeeRecipient: coinbase,
Calls: []callRes{{
ReturnValue: "0x0000000000000000000000000000000200000000000000000000000000000003",
GasUsed: "0x62a1",
Logs: []types.Log{},
Status: "0x1",
}, {
ReturnValue: "0x0000000000000000000000000000000100000000000000000000000000000000",
GasUsed: "0x62a1",
Logs: []types.Log{},
Status: "0x1",
}},
}, {
Number: "0xa",
Hash: n10hash,
GasLimit: "0x47e7c4",
GasUsed: "0x62a1",
FeeRecipient: coinbase,
Calls: []callRes{{
ReturnValue: "0x0000000000000000000000000000000500000000000000000000000000000000",
GasUsed: "0x62a1",
Logs: []types.Log{},
Status: "0x1",
}},
}},
},
}
for _, tc := range testSuite {
@ -1318,6 +1430,11 @@ func newUint64(v uint64) *hexutil.Uint64 {
return &rpcUint64
}
func newBytes(b []byte) *hexutil.Bytes {
rpcBytes := hexutil.Bytes(b)
return &rpcBytes
}
// testHasher is the helper tool for transaction/receipt list hashing.
// The original hasher is trie, in order to get rid of import cycle,
// use the testing hasher instead.