// Copyright 2025 go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package bintrie import ( "bytes" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" ) const ( BasicDataLeafKey = 0 CodeHashLeafKey = 1 BasicDataCodeSizeOffset = 5 BasicDataNonceOffset = 8 BasicDataBalanceOffset = 16 ) var ( zeroInt = uint256.NewInt(0) zeroHash = common.Hash{} verkleNodeWidthLog2 = 8 headerStorageOffset = uint256.NewInt(64) codeOffset = uint256.NewInt(128) codeStorageDelta = uint256.NewInt(0).Sub(codeOffset, headerStorageOffset) mainStorageOffsetLshVerkleNodeWidth = new(uint256.Int).Lsh(uint256.NewInt(1), 248-uint(verkleNodeWidthLog2)) CodeOffset = uint256.NewInt(128) VerkleNodeWidth = uint256.NewInt(256) HeaderStorageOffset = uint256.NewInt(64) VerkleNodeWidthLog2 = 8 ) func GetBinaryTreeKey(addr common.Address, key []byte) []byte { return getBinaryTreeKey(addr, key, false) } func getBinaryTreeKey(addr common.Address, offset []byte, overflow bool) []byte { hasher := newSha256() defer returnSha256(hasher) hasher.Write(zeroHash[:12]) hasher.Write(addr[:]) var buf [32]byte // 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[31] = offset[31] return k } func GetBinaryTreeKeyBasicData(addr common.Address) []byte { var k [32]byte k[31] = BasicDataLeafKey return GetBinaryTreeKey(addr, k[:]) } func GetBinaryTreeKeyCodeHash(addr common.Address) []byte { var k [32]byte k[31] = CodeHashLeafKey return GetBinaryTreeKey(addr, k[:]) } func GetBinaryTreeKeyStorageSlot(address common.Address, slotnum []byte) []byte { var offset [32]byte // Case when the key belongs to the account header if bytes.Equal(slotnum[:31], zeroHash[:31]) && slotnum[31] < 64 { offset[31] = 64 + slotnum[31] return GetBinaryTreeKey(address, offset[:]) } // Set the main storage offset offset = MAIN_STORAGE_OFFSET + slotnum // * Note that MAIN_STORAGE_OFFSET is 1 << 248, so the number // can overflow into a 33rd byte, but since the value is // shifted by one byte in getBinaryTreeKey, this only takes // note of the overflow, and the value will be added after // the shift, in order to avoid allocating an extra byte. // * 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, offset[:], overflow) } func GetBinaryTreeKeyCodeChunk(address common.Address, chunknr *uint256.Int) []byte { chunkOffset := new(uint256.Int).Add(codeOffset, chunknr).Bytes() return GetBinaryTreeKey(address, chunkOffset) } func StorageIndex(storageKey []byte) (*uint256.Int, byte) { // If the storage slot is in the header, we need to add the header offset. var key uint256.Int key.SetBytes(storageKey) if key.Cmp(codeStorageDelta) < 0 { // This addition is always safe; it can't ever overflow since pos