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

Get tree key storage reuse addr part #105

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rlp"
trieUtils "github.com/ethereum/go-ethereum/trie/utils"
"github.com/gballet/go-verkle"
"github.com/holiman/uint256"
)

Expand Down Expand Up @@ -72,6 +73,8 @@ type stateObject struct {
data types.StateAccount
db *StateDB

pointEval *verkle.Point

// DB error.
// State objects are used by the consensus core and VM which are
// unable to deal with database-level errors. Any error that occurs
Expand Down Expand Up @@ -134,6 +137,7 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
db: db,
address: address,
addrHash: crypto.Keccak256Hash(address[:]),
pointEval: trieUtils.EvaluateAddressPoint(address.Bytes()),
data: data,
originStorage: make(Storage),
pendingStorage: make(Storage),
Expand Down Expand Up @@ -282,9 +286,8 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
if err != nil {
return common.Hash{}
}
addr := s.Address()
loc := new(uint256.Int).SetBytes(key[:])
index := trieUtils.GetTreeKeyStorageSlot(addr[:], loc)
index := trieUtils.GetTreeKeyStorageSlotWithEvaluatedAddress(s.pointEval, loc)
if len(enc) > 0 {
s.db.Witness().SetLeafValue(index, value.Bytes())
} else {
Expand Down Expand Up @@ -391,7 +394,7 @@ func (s *stateObject) updateTrie(db Database) Trie {
var v []byte
if (value == common.Hash{}) {
if tr.IsVerkle() {
k := trieUtils.GetTreeKeyStorageSlot(s.address[:], new(uint256.Int).SetBytes(key[:]))
k := trieUtils.GetTreeKeyStorageSlotWithEvaluatedAddress(s.pointEval, new(uint256.Int).SetBytes(key[:]))
s.setError(tr.TryDelete(k))
//s.db.db.TrieDB().DiskDB().Delete(append(s.address[:], key[:]...))
} else {
Expand All @@ -404,7 +407,7 @@ func (s *stateObject) updateTrie(db Database) Trie {
if !tr.IsVerkle() {
s.setError(tr.TryUpdate(key[:], v))
} else {
k := trieUtils.GetTreeKeyStorageSlot(s.address[:], new(uint256.Int).SetBytes(key[:]))
k := trieUtils.GetTreeKeyStorageSlotWithEvaluatedAddress(s.pointEval, new(uint256.Int).SetBytes(key[:]))
// Update the trie, with v as a value
s.setError(tr.TryUpdate(k, value[:]))
}
Expand Down
11 changes: 11 additions & 0 deletions core/vm/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/gballet/go-verkle"
"github.com/holiman/uint256"
)

Expand Down Expand Up @@ -49,6 +51,7 @@ type Contract struct {
CallerAddress common.Address
caller ContractRef
self ContractRef
addressPoint *verkle.Point

jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
analysis bitvec // Locally cached result of JUMPDEST analysis
Expand Down Expand Up @@ -175,6 +178,14 @@ func (c *Contract) Address() common.Address {
return c.self.Address()
}

func (c *Contract) AddressPoint() *verkle.Point {
if c.addressPoint == nil {
c.addressPoint = utils.EvaluateAddressPoint(c.Address().Bytes())
}

return c.addressPoint
}

// Value returns the contract's value (sent to it from it's caller)
func (c *Contract) Value() *big.Int {
return c.value
Expand Down
3 changes: 1 addition & 2 deletions core/vm/gas_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,7 @@ func gasSLoad(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySiz

if evm.chainConfig.IsCancun(evm.Context.BlockNumber) {
where := stack.Back(0)
addr := contract.Address()
index := trieUtils.GetTreeKeyStorageSlot(addr[:], where)
index := trieUtils.GetTreeKeyStorageSlotWithEvaluatedAddress(contract.AddressPoint(), where)
usedGas += evm.Accesses.TouchAddressOnReadAndComputeGas(index)
}

Expand Down
3 changes: 1 addition & 2 deletions core/vm/operations_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
value := common.Hash(y.Bytes32())

if evm.chainConfig.IsCancun(evm.Context.BlockNumber) {
addr := contract.Address()
index := trieUtils.GetTreeKeyStorageSlot(addr[:], x)
index := trieUtils.GetTreeKeyStorageSlotWithEvaluatedAddress(contract.AddressPoint(), x)
cost += evm.Accesses.TouchAddressOnWriteAndComputeGas(index)
}

Expand Down
95 changes: 93 additions & 2 deletions trie/utils/verkle.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,17 @@ var (
MainStorageOffset = new(uint256.Int).Lsh(uint256.NewInt(256), 31)
VerkleNodeWidth = uint256.NewInt(256)
codeStorageDelta = uint256.NewInt(0).Sub(CodeOffset, HeaderStorageOffset)

getTreePolyIndex0Fr [1]verkle.Fr
getTreePolyIndex0Point *verkle.Point
)

func init() {
cfg, _ := verkle.GetConfig()
verkle.FromLEBytes(&getTreePolyIndex0Fr[0], []byte{2, 64})
getTreePolyIndex0Point = cfg.CommitToPoly(getTreePolyIndex0Fr[:], 1)
}

// GetTreeKey performs both the work of the spec's get_tree_key function, and that
// of pedersen_hash: it builds the polynomial in pedersen_hash without having to
// create a mostly zero-filled buffer and "type cast" it to a 128-long 16-byte
Expand All @@ -52,8 +61,7 @@ func GetTreeKey(address []byte, treeIndex *uint256.Int, subIndex byte) []byte {
}
var poly [5]fr.Element

// (2 + 256 * length) little endian, length = 64 bytes
verkle.FromLEBytes(&poly[0], []byte{2, 64})
poly[0].SetZero()

// 32-byte address, interpreted as two little endian
// 16-byte numbers.
Expand All @@ -71,6 +79,9 @@ func GetTreeKey(address []byte, treeIndex *uint256.Int, subIndex byte) []byte {
cfg, _ := verkle.GetConfig()
ret := cfg.CommitToPoly(poly[:], 0)

// add a constant point
ret.Add(ret, getTreePolyIndex0Point)

// The output of Byte() is big engian for banderwagon. This
// introduces an inbalance in the tree, because hashes are
// elements of a 253-bit field. This means more than half the
Expand Down Expand Up @@ -142,3 +153,83 @@ func GetTreeKeyStorageSlot(address []byte, storageKey *uint256.Int) []byte {
}
return GetTreeKey(address, treeIndex, subIndex)
}

func getTreeKeyWithEvaluatedAddess(evaluated *verkle.Point, treeIndex *uint256.Int, subIndex byte) []byte {
var poly [5]fr.Element

poly[0].SetZero()
poly[1].SetZero()
poly[2].SetZero()

// little-endian, 32-byte aligned treeIndex
var index [32]byte
for i, b := range treeIndex.Bytes() {
index[len(treeIndex.Bytes())-1-i] = b
}
verkle.FromLEBytes(&poly[3], index[:16])
verkle.FromLEBytes(&poly[4], index[16:])

cfg, _ := verkle.GetConfig()
ret := cfg.CommitToPoly(poly[:], 0)

// add the pre-evaluated address
ret.Add(ret, evaluated)

// The output of Byte() is big engian for banderwagon. This
// introduces an inbalance in the tree, because hashes are
// elements of a 253-bit field. This means more than half the
// tree would be empty. To avoid this problem, use a little
// endian commitment and chop the MSB.
var retb [32]byte
retb = ret.Bytes()
for i := 0; i < 16; i++ {
retb[31-i], retb[i] = retb[i], retb[31-i]
}
retb[31] = subIndex
return retb[:]

}

func EvaluateAddressPoint(address []byte) *verkle.Point {
if len(address) < 32 {
var aligned [32]byte
address = append(aligned[:32-len(address)], address...)
}
var poly [3]fr.Element

poly[0].SetZero()

// 32-byte address, interpreted as two little endian
// 16-byte numbers.
verkle.FromLEBytes(&poly[1], address[:16])
verkle.FromLEBytes(&poly[2], address[16:])

cfg, _ := verkle.GetConfig()
ret := cfg.CommitToPoly(poly[:], 0)

// add a constant point
ret.Add(ret, getTreePolyIndex0Point)

return ret
}

func GetTreeKeyStorageSlotWithEvaluatedAddress(evaluated *verkle.Point, storageKey *uint256.Int) []byte {
pos := storageKey.Clone()
if storageKey.Cmp(codeStorageDelta) < 0 {
pos.Add(HeaderStorageOffset, storageKey)
} else {
pos.Add(MainStorageOffset, storageKey)
}
treeIndex := new(uint256.Int).Div(pos, VerkleNodeWidth)
// calculate the sub_index, i.e. the index in the stem tree.
// Because the modulus is 256, it's the last byte of treeIndex
subIndexMod := new(uint256.Int).Mod(pos, VerkleNodeWidth).Bytes()
var subIndex byte
if len(subIndexMod) != 0 {
// uint256 is broken into 4 little-endian quads,
// each with native endianness. Extract the least
// significant byte.
subIndex = byte(subIndexMod[0] & 0xFF)
}
return getTreeKeyWithEvaluatedAddess(evaluated, treeIndex, subIndex)
}