mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-06 06:58:39 +00:00
trie/bintrie: fix overflow management in slot key computation (#33951)
The computation of `MAIN_STORAGE_OFFSET` was incorrect, causing the last byte of the stem to be dropped. This means that there would be a collision in the hash computation (at the preimage level, not a hash collision of course) if two keys were only differing at byte 31.
This commit is contained in:
parent
344ce84a43
commit
a0fb8102fe
2 changed files with 35 additions and 17 deletions
|
|
@ -308,7 +308,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := common.FromHex("b94812c1674dcf4f2bc98f4503d15f4cc674265135bcf3be6e4417b60881042a")
|
expected := common.FromHex("1fd154971d9a386c4ec75fe7138c17efb569bfc2962e46e94a376ba997e3fadc")
|
||||||
got := genesis.ToBlock().Root().Bytes()
|
got := genesis.ToBlock().Root().Bytes()
|
||||||
if !bytes.Equal(got, expected) {
|
if !bytes.Equal(got, expected) {
|
||||||
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
|
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, got)
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,26 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetBinaryTreeKey(addr common.Address, key []byte) []byte {
|
func GetBinaryTreeKey(addr common.Address, key []byte) []byte {
|
||||||
|
return getBinaryTreeKey(addr, key, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBinaryTreeKey(addr common.Address, offset []byte, overflow bool) []byte {
|
||||||
hasher := sha256.New()
|
hasher := sha256.New()
|
||||||
hasher.Write(zeroHash[:12])
|
hasher.Write(zeroHash[:12])
|
||||||
hasher.Write(addr[:])
|
hasher.Write(addr[:])
|
||||||
hasher.Write(key[:31])
|
var buf [32]byte
|
||||||
hasher.Write([]byte{0})
|
// key is big endian, hashed value is little endian
|
||||||
|
for i := range offset[:31] {
|
||||||
|
buf[i] = offset[30-i]
|
||||||
|
}
|
||||||
|
if overflow {
|
||||||
|
// Overflow detected when adding MAIN_STORAGE_OFFSET,
|
||||||
|
// reporting it in the shifter 32 byte value.
|
||||||
|
buf[31] = 1
|
||||||
|
}
|
||||||
|
hasher.Write(buf[:])
|
||||||
k := hasher.Sum(nil)
|
k := hasher.Sum(nil)
|
||||||
k[31] = key[31]
|
k[31] = offset[31]
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,24 +82,29 @@ func GetBinaryTreeKeyCodeHash(addr common.Address) []byte {
|
||||||
return GetBinaryTreeKey(addr, k[:])
|
return GetBinaryTreeKey(addr, k[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBinaryTreeKeyStorageSlot(address common.Address, key []byte) []byte {
|
func GetBinaryTreeKeyStorageSlot(address common.Address, slotnum []byte) []byte {
|
||||||
var k [32]byte
|
var offset [32]byte
|
||||||
|
|
||||||
// Case when the key belongs to the account header
|
// Case when the key belongs to the account header
|
||||||
if bytes.Equal(key[:31], zeroHash[:31]) && key[31] < 64 {
|
if bytes.Equal(slotnum[:31], zeroHash[:31]) && slotnum[31] < 64 {
|
||||||
k[31] = 64 + key[31]
|
offset[31] = 64 + slotnum[31]
|
||||||
return GetBinaryTreeKey(address, k[:])
|
return GetBinaryTreeKey(address, offset[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the main storage offset
|
// Set the main storage offset offset = MAIN_STORAGE_OFFSET + slotnum
|
||||||
// note that the first 64 bytes of the main offset storage
|
// * Note that MAIN_STORAGE_OFFSET is 1 << 248, so the number
|
||||||
// are unreachable, which is consistent with the spec and
|
// can overflow into a 33rd byte, but since the value is
|
||||||
// what verkle does.
|
// shifted by one byte in getBinaryTreeKey, this only takes
|
||||||
k[0] = 1 // 1 << 248
|
// note of the overflow, and the value will be added after
|
||||||
copy(k[1:], key[:31])
|
// the shift, in order to avoid allocating an extra byte.
|
||||||
k[31] = key[31]
|
// * Note that the first 64 bytes of the main offset storage
|
||||||
|
// are unreachable, which is consistent with the spec.
|
||||||
|
// * Note that `slotnum` is big-endian
|
||||||
|
overflow := slotnum[0] == 255
|
||||||
|
copy(offset[:], slotnum)
|
||||||
|
offset[0] += 1 // 1 << 248, handle overflow out of band
|
||||||
|
|
||||||
return GetBinaryTreeKey(address, k[:])
|
return getBinaryTreeKey(address, offset[:], overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBinaryTreeKeyCodeChunk(address common.Address, chunknr *uint256.Int) []byte {
|
func GetBinaryTreeKeyCodeChunk(address common.Address, chunknr *uint256.Int) []byte {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue