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

fix *uint256 reuse issue #17

Merged
merged 1 commit into from
Oct 30, 2024
Merged

fix *uint256 reuse issue #17

merged 1 commit into from
Oct 30, 2024

Conversation

qizhou
Copy link

@qizhou qizhou commented Oct 28, 2024

This fixes a weird issue that was found in fault proof.

The key problem is that the returned balance is a pointer that can be modified by callers. In most cases, the balance is not reused. However, in some cases that balances is zero, statedb returns a cached zero uint256 (see

return common.U2560
). If the cache zero uint256 is modified, geth will result in some unexpected behavior such as account overflow issue.

Test:

Before

1, fault proof will fail after verifying a SGT tx
2, dump the state, and find an account 0xfffffffffffffffffffffffffffffffffffffffe has a negative balance.

After

1, pass fault proof via make verify-devnet
2, 0xfffffffffffffffffffffffffffffffffffffffe has zero balance

@blockchaindevsh
Copy link
Collaborator

Looks like no only when zero, even if non-zero , GetBalance will return a reference to the balance field of state object. This is dangerous and makes it possible to change balance skipping the SetBalance. Do you plan to fix the issue in GetBalance and upstream it instead?

@qizhou
Copy link
Author

qizhou commented Oct 29, 2024

Looks like no only when zero, even if non-zero , GetBalance will return a reference to the balance field of state object. This is dangerous and makes it possible to change balance skipping the SetBalance. Do you plan to fix the issue in GetBalance and upstream it instead?

I feel like this behavior is intentional in geth - I guess that it is good for performance, and it is the caller's responsibility to not reuse the object.

@blockchaindevsh
Copy link
Collaborator

Looks like no only when zero, even if non-zero , GetBalance will return a reference to the balance field of state object. This is dangerous and makes it possible to change balance skipping the SetBalance. Do you plan to fix the issue in GetBalance and upstream it instead?

I feel like this behavior is intentional in geth - I guess that it is good for performance, and it is the caller's responsibility to not reuse the object.

Gotcha, maybe we should follow geth's convention and change all places that reuse balance to create a new value instead of clone?

@qizhou
Copy link
Author

qizhou commented Oct 29, 2024

Looks like no only when zero, even if non-zero , GetBalance will return a reference to the balance field of state object. This is dangerous and makes it possible to change balance skipping the SetBalance. Do you plan to fix the issue in GetBalance and upstream it instead?

I feel like this behavior is intentional in geth - I guess that it is good for performance, and it is the caller's responsibility to not reuse the object.

Gotcha, maybe we should follow geth's convention and change all places that reuse balance to create a new value instead of clone?

The simple fix will always return a new *uint256 in GetGasBalances - because all other methods will rely on this method, we will not have such an issue. The key here is that we don't care the perf at the moment, but we can optimize it later if profiling tells so - in fact, I am not a big fun of early optimization.

@qzhodl
Copy link

qzhodl commented Oct 30, 2024

It’s really hard to find the root cause. I’m curious - what tool are you using to dump and diff the entire state? Is there any documentation or instruction for it?

@qizhou
Copy link
Author

qizhou commented Oct 30, 2024

It’s really hard to find the root cause. I’m curious - what tool are you using to dump and diff the entire state? Is there any documentation or instruction for it?

geth dump --datadir ./db $bn will work. In addition, in the code, you can call statedb.Dump() to return the state in json.

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.

None yet

3 participants