-
Notifications
You must be signed in to change notification settings - Fork 20.5k
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
Unexpected behavior for StateDB.IntermediateRoot
and StateDB.Copy
#28176
Comments
It's because
spits out
And if you print out the iteration:
Then you'll get
|
@holiman Thanks for taking a look! I'm aware that func Test(t *testing.T) {
db := rawdb.NewMemoryDatabase()
st1, _ := state.New(types.EmptyRootHash, state.NewDatabaseWithConfig(db, &triedb.Config{Preimages: true}), nil)
addrA := common.HexToAddress("0xaaaaaaaa")
bal := new(uint256.Int)
_ = bal.SetFromHex("0xfffffffffffffffffffffff")
st1.SetBalance(addrA, bal, tracing.BalanceChangeUnspecified)
var nonceA uint64 = 0
st1.SetNonce(addrA, nonceA)
st1.SetCode(addrA, []byte{})
addrB := common.HexToAddress("0xbbbbbbbb")
var nonceB uint64 = 1
st1Root, comErr1 := st1.Commit(0, false)
if comErr1 != nil {
panic(comErr1)
}
st2, newErr1 := state.New(st1Root, st1.Database(), nil)
if newErr1 != nil {
panic(newErr1)
}
st3 := st2
st3.SetNonce(addrB, nonceB)
skipIntermediateRoot := false // Setting this to true "fixes it".
if !skipIntermediateRoot {
st3.IntermediateRoot(false)
}
var st4 *state.StateDB
skipCopy := false // Setting this to true "fixes it".
if skipCopy {
st4 = st3
} else {
st4 = st3.Copy()
}
st4Root, comErr2 := st4.Commit(0, false)
if comErr2 != nil {
panic(comErr2)
}
st5, newErr2 := state.New(st4Root, st4.Database(), nil)
if newErr2 != nil {
panic(newErr2)
}
if st5.GetNonce(addrB) != nonceB {
panic("nonce of account B does not match")
}
openTr, openErr := st5.Database().OpenTrie(st4Root)
if openErr != nil {
panic(openErr)
}
nodeIt, nodeItErr := openTr.NodeIterator(nil)
if nodeItErr != nil {
panic(nodeItErr)
}
it := trie.NewIterator(nodeIt)
foundB := false
for it.Next() {
addrHash := it.Key
fmt.Printf("addrHash: %x\n", addrHash)
addrBytes := openTr.GetKey(addrHash)
if addrBytes == nil {
continue
}
fmt.Printf("addrBytes: %x\n", addrBytes)
addr := common.BytesToAddress(addrBytes)
if addr == addrB {
foundB = true
}
}
if !foundB {
panic("account B was not found")
}
} I see the following output:
I don't understand why it fails to map the hash of the address However, I see the expected output when setting
Can you explain this difference in behavior? |
So, you can skip everything after
It will show you that the preimage for address is not present.
So it's not that account B is not found when iterating the trie (it is), it's that the hash cannot be reversed. I'm not 100% sure yet why that is. |
THe preimage for account A was stored to db during the |
@holiman Thanks for the quick reply! There is a second commit after the state update for |
System information
Geth version: v1.13.1
Expected behaviour
When I run the following code snippet, I don't expect a panic:
Actual behaviour
The code produces a panic ("account B was not found").
I don't understand why
addrB
is not found when iterating over the accounts of the final state (st5
).I found two "fixes", but I don't understand why they work: (1) setting
skipCopy
to true or alternatively (2) settingskipIntermediateRoot
to true.Is this the intended behavior?
Steps to reproduce the behaviour
Run the above code snippet with v1.13.1.
The text was updated successfully, but these errors were encountered: