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

all: eip1153 #6133

Closed
wants to merge 1 commit into from
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
42 changes: 35 additions & 7 deletions core/state/intra_block_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,14 @@ type IntraBlockState struct {

// Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot.
journal *journal
validRevisions []revision
nextRevisionID int
tracer StateTracer
trace bool
accessList *accessList
balanceInc map[common.Address]*BalanceIncrease // Map of balance increases (without first reading the account)
journal *journal
validRevisions []revision
nextRevisionID int
tracer StateTracer
trace bool
accessList *accessList
transientStorage transientStorage
balanceInc map[common.Address]*BalanceIncrease // Map of balance increases (without first reading the account)
}

// Create a new state from a given trie
Expand All @@ -101,6 +102,7 @@ func New(stateReader StateReader) *IntraBlockState {
logs: map[common.Hash][]*types.Log{},
journal: newJournal(),
accessList: newAccessList(),
transientStorage: newTransientStorage(),
balanceInc: map[common.Address]*BalanceIncrease{},
}
}
Expand Down Expand Up @@ -136,6 +138,7 @@ func (sdb *IntraBlockState) Reset() {
sdb.logSize = 0
sdb.clearJournalAndRefund()
sdb.accessList = newAccessList()
sdb.transientStorage = newTransientStorage()
sdb.balanceInc = make(map[common.Address]*BalanceIncrease)
}

Expand Down Expand Up @@ -505,6 +508,30 @@ func (sdb *IntraBlockState) Suicide(addr common.Address) bool {
return true
}

func (sdb *IntraBlockState) SetTransientState(addr common.Address, key *common.Hash, value uint256.Int) {
var prev uint256.Int
sdb.GetTransientState(addr, key, &prev)
if prev == value {
return
}

sdb.journal.append(transientStorageChange{
account: &addr,
key: *key,
prevalue: value,
})

sdb.setTransientState(addr, key, value)
}

func (sdb *IntraBlockState) setTransientState(addr common.Address, key *common.Hash, value uint256.Int) {
sdb.transientStorage.Set(addr, key, value)
}

func (sdb *IntraBlockState) GetTransientState(addr common.Address, key *common.Hash, value *uint256.Int) {
sdb.transientStorage.Get(addr, key, value)
}

func (sdb *IntraBlockState) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects.
if obj := sdb.stateObjects[addr]; obj != nil {
Expand Down Expand Up @@ -813,6 +840,7 @@ func (sdb *IntraBlockState) Prepare(thash, bhash common.Hash, ti int) {
sdb.bhash = bhash
sdb.txIndex = ti
sdb.accessList = newAccessList()
sdb.transientStorage = newTransientStorage()
}

// no not lock
Expand Down
10 changes: 10 additions & 0 deletions core/state/intra_block_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
},
args: make([]int64, 2),
},
{
name: "SetTransientState",
fn: func(a testAction, s *IntraBlockState) {
var key common.Hash
binary.BigEndian.PutUint16(key[:], uint16(a.args[0]))
val := uint256.NewInt(uint64(a.args[1]))
s.SetTransientState(addr, &key, *val)
},
args: make([]int64, 2),
},
{
name: "SetCode",
fn: func(a testAction, s *IntraBlockState) {
Expand Down
13 changes: 13 additions & 0 deletions core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ type (
key common.Hash
prevalue uint256.Int
}
transientStorageChange struct {
account *common.Address
key common.Hash
prevalue uint256.Int
}
codeChange struct {
account *common.Address
prevcode []byte
Expand Down Expand Up @@ -262,6 +267,14 @@ func (ch fakeStorageChange) dirtied() *common.Address {
return ch.account
}

func (ch transientStorageChange) revert(s *IntraBlockState) {
s.setTransientState(*ch.account, &ch.key, ch.prevalue)
}

func (ch transientStorageChange) dirtied() *common.Address {
return nil
}

func (ch refundChange) revert(s *IntraBlockState) {
s.refund = ch.prev
}
Expand Down
57 changes: 57 additions & 0 deletions core/state/transient_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2022 The 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 <http://www.gnu.org/licenses/>.

package state

import (
"github.com/holiman/uint256"
"github.com/ledgerwatch/erigon/common"
)

// transientStorage is a representation of EIP-1153 "Transient Storage".
type transientStorage map[common.Address]Storage

// newTransientStorage creates a new instance of a transientStorage.
func newTransientStorage() transientStorage {
return make(transientStorage)
}

// Set sets the transient-storage `value` for `key` at the given `addr`.
func (t transientStorage) Set(addr common.Address, key *common.Hash, value uint256.Int) {
if _, ok := t[addr]; !ok {
t[addr] = make(Storage)
}
t[addr][*key] = value
}

// Get gets the transient storage for `key` at the given `addr`.
func (t transientStorage) Get(addr common.Address, key *common.Hash, value *uint256.Int) {
val, ok := t[addr]
if !ok {
*value = uint256.Int{}
} else {
*value = val[*key]
}
}

// Copy does a deep copy of the transientStorage
func (t transientStorage) Copy() transientStorage {
storage := make(transientStorage)
for key, value := range t {
storage[key] = value.Copy()
}
return storage
}
40 changes: 40 additions & 0 deletions core/vm/eips.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,46 @@ func enable3198(jt *JumpTable) {
}
}

// enable1153 applies EIP-1153 "Transient Storage"
// - Adds TLOAD that reads from transient storage
// - Adds TSTORE that writes to transient storage
func enable1153(jt *JumpTable) {
jt[TLOAD] = &operation{
execute: opTload,
constantGas: params.WarmStorageReadCostEIP2929,
minStack: minStack(1, 1),
maxStack: maxStack(1, 1),
}

jt[TSTORE] = &operation{
execute: opTstore,
constantGas: params.WarmStorageReadCostEIP2929,
minStack: minStack(2, 0),
maxStack: maxStack(2, 0),
}
}

// opTload implements TLOAD opcode
func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
loc := scope.Stack.Peek()
interpreter.hasherBuf = loc.Bytes32()
interpreter.evm.IntraBlockState().GetTransientState(scope.Contract.Address(), &interpreter.hasherBuf, loc)
return nil, nil
}

// opTstore implements TSTORE opcode
func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
loc := scope.Stack.Pop()
val := scope.Stack.Pop()
interpreter.hasherBuf = loc.Bytes32()
interpreter.evm.IntraBlockState().SetTransientState(scope.Contract.Address(), &interpreter.hasherBuf, val)

return nil, nil
}

// opBaseFee implements BASEFEE opcode
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
baseFee := interpreter.evm.Context().BaseFee
Expand Down
2 changes: 2 additions & 0 deletions core/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type IntraBlockState interface {
GetCommittedState(common.Address, *common.Hash, *uint256.Int)
GetState(address common.Address, slot *common.Hash, outValue *uint256.Int)
SetState(common.Address, *common.Hash, uint256.Int)
GetTransientState(address common.Address, slot *common.Hash, outValue *uint256.Int)
SetTransientState(common.Address, *common.Hash, uint256.Int)

Suicide(common.Address) bool
HasSuicided(common.Address) bool
Expand Down
12 changes: 12 additions & 0 deletions core/vm/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ const (
LOG4
)

// 0xb0 range.
const (
TSTORE OpCode = 0xb3
TLOAD OpCode = 0xb4
)

// unofficial opcodes used for parsing.
const (
PUSH OpCode = 0xb0 + iota
Expand Down Expand Up @@ -374,6 +380,10 @@ var opCodeToString = map[OpCode]string{
LOG3: "LOG3",
LOG4: "LOG4",

// 0xb0 range.
TLOAD: "TLOAD",
TSTORE: "TSTORE",

// 0xf0 range.
CREATE: "CREATE",
CALL: "CALL",
Expand Down Expand Up @@ -531,6 +541,8 @@ var stringToOp = map[string]OpCode{
"SWAP14": SWAP14,
"SWAP15": SWAP15,
"SWAP16": SWAP16,
"TLOAD": TLOAD,
"TSTORE": TSTORE,
"LOG0": LOG0,
"LOG1": LOG1,
"LOG2": LOG2,
Expand Down