handle creation nonce in journal

This commit is contained in:
Sina Mahmoodi 2024-11-26 16:46:41 +01:00
parent 6e4d14ca96
commit 553f023638
2 changed files with 37 additions and 3 deletions

View File

@ -25,6 +25,11 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
const (
CREATE = 0xf0
CREATE2 = 0xf5
)
type revision struct { type revision struct {
id int id int
journalIndex int journalIndex int
@ -33,8 +38,9 @@ type revision struct {
// journal is a state change journal to be wrapped around a tracer. // journal is a state change journal to be wrapped around a tracer.
// It will emit the state change hooks with reverse values when a call reverts. // It will emit the state change hooks with reverse values when a call reverts.
type journal struct { type journal struct {
entries []entry entries []entry
hooks *Hooks hooks *Hooks
lastCreator *common.Address // Account that initiated the last contract creation
validRevisions []revision validRevisions []revision
nextRevisionId int nextRevisionId int
@ -136,12 +142,18 @@ func (j *journal) OnTxEnd(receipt *types.Receipt, err error) {
func (j *journal) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { func (j *journal) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
j.revIds = append(j.revIds, j.snapshot()) j.revIds = append(j.revIds, j.snapshot())
if typ == CREATE || typ == CREATE2 {
j.lastCreator = &from
}
if j.hooks.OnEnter != nil { if j.hooks.OnEnter != nil {
j.hooks.OnEnter(depth, typ, from, to, input, gas, value) j.hooks.OnEnter(depth, typ, from, to, input, gas, value)
} }
} }
func (j *journal) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { func (j *journal) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
if j.lastCreator != nil {
j.lastCreator = nil
}
revId := j.revIds[len(j.revIds)-1] revId := j.revIds[len(j.revIds)-1]
j.revIds = j.revIds[:len(j.revIds)-1] j.revIds = j.revIds[:len(j.revIds)-1]
if reverted { if reverted {
@ -160,7 +172,14 @@ func (j *journal) OnBalanceChange(addr common.Address, prev, new *big.Int, reaso
} }
func (j *journal) OnNonceChange(addr common.Address, prev, new uint64) { func (j *journal) OnNonceChange(addr common.Address, prev, new uint64) {
j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new}) // When a contract is created, the nonce of the creator is incremented.
// This change is not reverted when the creation fails.
if j.lastCreator != nil && *j.lastCreator == addr {
// Skip only the first nonce change.
j.lastCreator = nil
} else {
j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new})
}
if j.hooks.OnNonceChange != nil { if j.hooks.OnNonceChange != nil {
j.hooks.OnNonceChange(addr, prev, new) j.hooks.OnNonceChange(addr, prev, new)
} }

View File

@ -142,6 +142,21 @@ func TestJournalNestedCalls(t *testing.T) {
} }
} }
func TestNonceIncOnCreate(t *testing.T) {
tr := &testTracer{}
wr, err := WrapWithJournal(&Hooks{OnNonceChange: tr.OnNonceChange})
if err != nil {
t.Fatalf("failed to wrap test tracer: %v", err)
}
addr := common.HexToAddress("0x1234")
wr.OnEnter(0, CREATE, addr, addr, nil, 1000, big.NewInt(0))
wr.OnNonceChange(addr, 0, 1)
wr.OnExit(0, nil, 100, errors.New("revert"), true)
if tr.nonce != 1 {
t.Fatalf("unexpected nonce: %v", tr.nonce)
}
}
func TestAllHooksCalled(t *testing.T) { func TestAllHooksCalled(t *testing.T) {
tracer := newTracerAllHooks() tracer := newTracerAllHooks()
hooks := tracer.hooks() hooks := tracer.hooks()