-
Notifications
You must be signed in to change notification settings - Fork 197
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
En 6597 state code pruning #1998
En 6597 state code pruning #1998
Conversation
data/state/journalEntries_test.go
Outdated
Code: []byte("newCode"), | ||
NumReferences: 1, | ||
} | ||
marsh := &mock.MarshalizerMock{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marsh sounds strange :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
} | ||
|
||
return &journalEntryCode{ | ||
codeHash: codeHash, | ||
updater: updater, | ||
oldCodeEntry: oldCodeEntry, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oldCodeEntry could be nil? If not you should check it above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oldCodeEntry could be nil in the following case: If a newCode is set to an account that had no code before, the oldCodeEntry should be nil, in case that a revert occurs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
if jea.oldCodeEntry.NumReferences == 1 { | ||
delete(jea.codeForEviction, string(jea.oldCodeHash)) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jea.oldCodeEntry.NumReferences-- ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because oldCodeEntry already has the numReferences set as before the changes. You can see in the accountDB that updateOldCodeEntry() returns unmodifiedOldCodeEntry that is used when creating a new journal entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
data/state/journalEntries.go
Outdated
return nil | ||
} | ||
|
||
if jea.oldCodeEntry.NumReferences == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<= ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
data/state/accountsDB_test.go
Outdated
@@ -940,3 +945,294 @@ func TestAccountsDB_GetAllLeaves(t *testing.T) { | |||
assert.True(t, recreateCalled) | |||
assert.True(t, getAllLeavesCalled) | |||
} | |||
|
|||
func getTestAccountsDbAndTrie(marsh marshal.Marshalizer, hsh hashing.Hasher) (*state.AccountsDB, data.Trie) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marsh sounds strange :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
data/state/accountsDB.go
Outdated
return oldAccount.GetCodeHash(), nil | ||
} | ||
|
||
func (adb *AccountsDB) saveCode(accountHandler baseAccountHandler, oldAcc AccountHandler) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accountHandler to newAcc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if jea.oldCodeEntry.NumReferences == 1 { | ||
delete(jea.codeForEviction, string(jea.oldCodeHash)) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -1665,3 +1666,146 @@ func testNodeStateCheckpointSnapshotAndPruning( | |||
assert.NotNil(t, err) | |||
} | |||
} | |||
|
|||
func TestContinuouslyAccountCodeChanges(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function too big. make a few smaller ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -20,6 +20,9 @@ type AccountsDB struct { | |||
marshalizer marshal.Marshalizer | |||
accountFactory AccountFactory | |||
|
|||
codeForEviction map[string]struct{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
codeForEviction cannot be used with current state of smart contract process, as delete function, delete smart contract is not called at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a code is updated and the old version is not used anymore, it needs to be evicted.
newCodeHash = adb.hasher.Compute(string(newCode)) | ||
} | ||
|
||
if bytes.Equal(oldCodeHash, newCodeHash) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
saveCode should be called only there is a new code. if there is something in old code - delete account / code should be called. If a code is delete the whole account is deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also sets the codeHash for the account. If a code is updated, isn't the same account used? In this case, there is something in both oldCode and newCode.
data/state/accountsDB.go
Outdated
@@ -90,7 +95,7 @@ func (adb *AccountsDB) SaveAccount(account AccountHandler) error { | |||
|
|||
baseAcc, ok := account.(baseAccountHandler) | |||
if ok { | |||
err = adb.saveCode(baseAcc) | |||
err = adb.saveCode(baseAcc, oldAccount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make a separate function to saveCode and saveDataTrie where you can handle all the cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make type assertion for oldAccount as well. for save code you need baseAccountHandler only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
newCode := accountHandler.GetCode() | ||
newCode := newAcc.GetCode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newAcc is always not nil? If not, add a check above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newAccount is always not nil. It is checked on L72, when SaveAccount() is called.
When SC code is saved to the trie, now also the number of references to the same code is saved in the same db. If the number of references to a certain code reaches 0, the trie node that contains the code is marked for eviction, and it will be pruned from the db.