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

implement post-nyota verkle costs #454

Merged
merged 9 commits into from
Aug 26, 2024
Merged

Conversation

gballet
Copy link
Owner

@gballet gballet commented Jun 27, 2024

TODO

  • fix broken tests
  • check conversion works
  • check replay works
  • check it works with a custom testnet
  • check kurtosis works
  • use it in the testing framework

trie/verkle.go Outdated
Comment on lines 458 to 465
headervals, err := t.root.(*verkle.InternalNode).GetValuesAtStem(key[:31], t.FlatdbNodeResolver)
if err != nil {
return fmt.Errorf("UpdateContractCode (addr=%x) error while getting account header: %w", addr[:], err)
}
var cs [8]byte
binary.LittleEndian.PutUint64(cs[:], uint64(len(code)))
copy(headervals[utils.BasicDataLeafKey][utils.BasicDataCodeSizeOffset:], cs[5:8])
values[utils.BasicDataLeafKey] = headervals[utils.BasicDataLeafKey]
Copy link
Owner Author

Choose a reason for hiding this comment

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

This is the part I like the least: the simplicity we gained from using the basic data leaf, we recover in this particular place: now, in order to write the code size, we need to first load the leaf.

Until now, UpdateStem would go over all leaves and only overwrite the leaves that were nil. That used to be enough, because code size was in its own leaf. This is no longer the case, so the leaf has first to be fetched and then the byte range updated.

I think it can be done more efficiently, but I need to write it down. I will not merge this until I got to the bottom of the story.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, realized this in a previous comment (L173 in this file) before reaching here.

Def complicated.

params.WitnessChunkReadCost+params.WitnessChunkWriteCost+ /* code chunk #12 */
params.WitnessChunkReadCost+params.WitnessChunkWriteCost+ /* code chunk #13 */
params.WitnessChunkReadCost+params.WitnessChunkWriteCost+ /* code chunk #14 */
4844 /* execution costs */)
Copy link
Owner Author

Choose a reason for hiding this comment

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

I had always "aced" the gas costs. I think it's a better idea to break it down one by one.

I spent way too much time on this, and the execution costs - 4844 - is suspicious. But this test passes. The others don't at the moment.

leafNodeData.Values[utils.CodeSizeLeafKey] = codeSizeBytes[:]
var cs [8]byte
binary.LittleEndian.PutUint64(cs[:], codeSize)
copy(leafNodeData.Values[utils.BasicDataLeafKey][utils.BasicDataCodeSizeOffset:utils.BasicDataNonceOffset], cs[:3])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggestion: avoid magic number 3 and define a constant with the byte size.

Also, no need to put the [:utils.BasicDataNonceOffset] since copy will copy the shortest size of both parameters. So we can remove this dependency that the end should match with other field.

if createSendsValue {
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BalanceLeafKey, true)
}
gas += aw.touchAddressAndChargeGas(addr, zeroTreeIndex, utils.BasicDataLeafKey, true)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can remove the parameter createSendsValue.

Comment on lines 136 to 138
if sendsValue {
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, true)
} else {
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BalanceLeafKey, false)
aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code can be removed since we can pass sendsValue as the parameter in L134, right?

trie/verkle.go Outdated
if len(values[utils.NonceLeafKey]) > 0 {
acc.Nonce = binary.LittleEndian.Uint64(values[utils.NonceLeafKey])
if len(values[utils.BasicDataLeafKey]) > 0 {
acc.Nonce = binary.LittleEndian.Uint64(values[utils.BasicDataLeafKey][utils.BasicDataNonceOffset:])
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is debatable, but I don't like this subslicing to not have an ending mark.
I know Uint64 is 8 bytes, and the spec says that Nonce is 8 bytes... so it isn't strictly necessary, but that matching is indirectly assumed.

This doesn't mean I'm suggesting to change it -- maybe I'm being purist.

trie/verkle.go Outdated
copy(balance[:], values[utils.BalanceLeafKey])
for i := 0; i < len(balance)/2; i++ {
balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1]
copy(balance[16:], values[utils.BasicDataLeafKey][utils.BasicDataBalanceOffset:])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same-ish (annoying) comment on setting the end slice limit. Dismiss if already decided not worth it.

}

values[utils.BasicDataLeafKey] = basicData[:]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't this unintentionally erase the code-size that might be already in the basic_data field of the leaf node?

We're building a new basicData [32]byte from scratch here, and if this address is a contract that had a contract_size in the existing basicData then we'd erase it.

Maybe this is a problem since in acc we don't have that info.

LMK if I'm missing something.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see another comment you did below reg code size. But what if this method is called and not UpdateCode after? Hairy.

Copy link
Owner Author

Choose a reason for hiding this comment

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

yeah it's buggy and I'm going to rewrite it

@@ -448,6 +437,7 @@ func (t *VerkleTrie) ClearStrorageRootConversion(addr common.Address) {
t.db.ClearStorageRootConversion(addr)
}

// Note: the basic data leaf needs to have been previously created for this to work
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you know if this is a safe assumption?

trie/verkle.go Outdated
Comment on lines 458 to 465
headervals, err := t.root.(*verkle.InternalNode).GetValuesAtStem(key[:31], t.FlatdbNodeResolver)
if err != nil {
return fmt.Errorf("UpdateContractCode (addr=%x) error while getting account header: %w", addr[:], err)
}
var cs [8]byte
binary.LittleEndian.PutUint64(cs[:], uint64(len(code)))
copy(headervals[utils.BasicDataLeafKey][utils.BasicDataCodeSizeOffset:], cs[5:8])
values[utils.BasicDataLeafKey] = headervals[utils.BasicDataLeafKey]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, realized this in a previous comment (L173 in this file) before reaching here.

Def complicated.

trie/verkle.go Outdated Show resolved Hide resolved
trie/verkle.go Outdated Show resolved Hide resolved
@gballet gballet added this to the verkle-gen-devnet-7 milestone Jun 28, 2024
core/overlay/conversion.go Outdated Show resolved Hide resolved
trie/verkle.go Outdated Show resolved Hide resolved
* fixes from replaying nyota costs

Signed-off-by: Guillaume Ballet <[email protected]>

* add left-out conversion file

* fix balance endianness + set code size in UpdateAccount

* add leftover endianness change

* remove code cleanup leftover

* use 5 as the code size offset

this matches the spec, even if we have to add a weird -1 here and there

* save buffer creation for PutUint32

---------

Signed-off-by: Guillaume Ballet <[email protected]>
@gballet gballet marked this pull request as ready for review August 23, 2024 19:05
@gballet
Copy link
Owner Author

gballet commented Aug 26, 2024

haven't managed to run it in kurtosis because of the genesis testnet generator, but it works in enough other contexts that this is clearly a configuration issue on my part. Merging.

@gballet gballet merged commit df13260 into kaustinen-with-shapella Aug 26, 2024
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants