Skip to content

Commit

Permalink
[factory] move SimulateExecution() out of factory interface
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie committed Nov 12, 2024
1 parent 59cebd9 commit 90a858a
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 123 deletions.
16 changes: 12 additions & 4 deletions action/protocol/execution/evm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ func SimulateExecution(
sm protocol.StateManager,
caller address.Address,
ex action.TxDataForSimulation,
opts ...protocol.SimulateOption,
) ([]byte, *action.Receipt, error) {
ctx, span := tracer.NewSpan(ctx, "evm.SimulateExecution")
defer span.End()
Expand All @@ -632,7 +633,16 @@ func SimulateExecution(
if err != nil {
return nil, nil, err
}
ctx = protocol.WithBlockCtx(
cfg := &protocol.SimulateOptionConfig{}
for _, opt := range opts {
opt(cfg)
}
if cfg.PreOpt != nil {
if err := cfg.PreOpt(sm); err != nil {
return nil, nil, err
}
}
ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(
ctx,
protocol.BlockCtx{
BlockHeight: bcCtx.Tip.Height + 1,
Expand All @@ -642,8 +652,6 @@ func SimulateExecution(
BaseFee: protocol.CalcBaseFee(g.Blockchain, &bcCtx.Tip),
ExcessBlobGas: protocol.CalcExcessBlobGas(bcCtx.Tip.ExcessBlobGas, bcCtx.Tip.BlobGasUsed),
},
)

ctx = protocol.WithFeatureCtx(ctx)
))
return ExecuteContract(ctx, sm, ex)
}
6 changes: 5 additions & 1 deletion action/protocol/execution/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,11 @@ func readExecution(
GetBlockTime: getBlockTimeForTest,
DepositGasFunc: rewarding.DepositGas,
})
return sf.SimulateExecution(ctx, addr, elp)
ws, err := sf.WorkingSetNotWritable(ctx, 0, false)
if err != nil {
return nil, nil, err
}
return evm.SimulateExecution(ctx, ws, addr, elp)
}

func (sct *SmartContractTest) runExecutions(
Expand Down
12 changes: 10 additions & 2 deletions api/coreservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -1820,7 +1820,11 @@ func (core *coreService) ReadContractStorage(ctx context.Context, addr address.A
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return core.sf.ReadContractStorage(ctx, addr, key)
ws, err := core.sf.WorkingSetNotWritable(ctx, 0, false)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return evm.ReadContractStorage(ctx, ws, addr, key)
}

func (core *coreService) ReceiveBlock(blk *block.Block) error {
Expand Down Expand Up @@ -1969,7 +1973,11 @@ func (core *coreService) simulateExecution(ctx context.Context, addr address.Add
GetBlockTime: core.getBlockTime,
DepositGasFunc: rewarding.DepositGas,
})
return core.sf.SimulateExecution(ctx, addr, elp, opts...)
ws, err := core.sf.WorkingSetNotWritable(ctx, 0, false)
if err != nil {
return nil, nil, status.Error(codes.Internal, err.Error())
}
return evm.SimulateExecution(ctx, ws, addr, elp, opts...)
}

func filterReceipts(receipts []*action.Receipt, actHash hash.Hash256) *action.Receipt {
Expand Down
6 changes: 5 additions & 1 deletion chainservice/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,11 @@ func (builder *Builder) registerRollDPoSProtocol() error {
GetBlockTime: getBlockTime,
DepositGasFunc: rewarding.DepositGas,
})
data, _, err := factory.SimulateExecution(ctx, addr, elp)
ws, err := factory.WorkingSetNotWritable(ctx, 0, false)
if err != nil {
return nil, err
}
data, _, err := evm.SimulateExecution(ctx, ws, addr, elp)
return data, err
},
candidatesutil.CandidatesFromDB,
Expand Down
7 changes: 5 additions & 2 deletions e2etest/staking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,11 @@ func TestStakingContract(t *testing.T) {
GetBlockTime: fakeGetBlockTime,
DepositGasFunc: rewarding.DepositGas,
})
data, _, err := sf.SimulateExecution(ctx, addr, elp)

ws, err := sf.WorkingSetNotWritable(ctx, 0, false)
if err != nil {
return nil, err
}
data, _, err := evm.SimulateExecution(ctx, ws, addr, elp)
return data, err
})
require.NoError(err)
Expand Down
49 changes: 13 additions & 36 deletions state/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

"github.com/iotexproject/go-pkgs/cache"
"github.com/iotexproject/go-pkgs/hash"
"github.com/iotexproject/iotex-address/address"

"github.com/iotexproject/iotex-core/v2/action"
"github.com/iotexproject/iotex-core/v2/action/protocol"
Expand Down Expand Up @@ -86,12 +85,11 @@ type (
Validate(context.Context, *block.Block) error
// NewBlockBuilder creates block builder
NewBlockBuilder(context.Context, actpool.ActPool, func(action.Envelope) (*action.SealedEnvelope, error)) (*block.Builder, error)
SimulateExecution(context.Context, address.Address, action.Envelope, ...protocol.SimulateOption) ([]byte, *action.Receipt, error)
ReadContractStorage(context.Context, address.Address, []byte) ([]byte, error)
PutBlock(context.Context, *block.Block) error
DeleteTipBlock(context.Context, *block.Block) error
StateAtHeight(uint64, interface{}, ...protocol.StateOption) error
StatesAtHeight(uint64, ...protocol.StateOption) (state.Iterator, error)
WorkingSetNotWritable(context.Context, uint64, bool) (protocol.StateManager, error)
}

// factory implements StateFactory interface, tracks changes to account/contract and batch-commits to DB
Expand Down Expand Up @@ -382,44 +380,23 @@ func (sf *factory) NewBlockBuilder(
return blkBuilder, nil
}

// SimulateExecution simulates a running of smart contract operation, this is done off the network since it does not
// cause any state change
func (sf *factory) SimulateExecution(
ctx context.Context,
caller address.Address,
elp action.Envelope,
opts ...protocol.SimulateOption,
) ([]byte, *action.Receipt, error) {
ctx, span := tracer.NewSpan(ctx, "factory.SimulateExecution")
defer span.End()

func (sf *factory) WorkingSetNotWritable(ctx context.Context, height uint64, isArchive bool) (protocol.StateManager, error) {
var (
ws *workingSet
err error
)
// TODO: make the workingset not writable, cannot call commit() to write its content to DB
sf.mutex.Lock()
ws, err := sf.newWorkingSet(ctx, sf.currentChainHeight+1)
sf.mutex.Unlock()
if err != nil {
return nil, nil, errors.Wrap(err, "failed to obtain working set from state factory")
if isArchive {
ws, err = sf.newWorkingSet(ctx, height+1)
} else {
ws, err = sf.newWorkingSet(ctx, sf.currentChainHeight+1)
}
cfg := &protocol.SimulateOptionConfig{}
for _, opt := range opts {
opt(cfg)
}
if cfg.PreOpt != nil {
if err := cfg.PreOpt(ws); err != nil {
return nil, nil, err
}
}
return evm.SimulateExecution(ctx, ws, caller, elp)
}

// ReadContractStorage reads contract's storage
func (sf *factory) ReadContractStorage(ctx context.Context, contract address.Address, key []byte) ([]byte, error) {
sf.mutex.Lock()
ws, err := sf.newWorkingSet(ctx, sf.currentChainHeight+1)
sf.mutex.Unlock()
if err != nil {
return nil, errors.Wrap(err, "failed to generate working set from state factory")
return nil, errors.Wrap(err, "failed to obtain working set from state factory")
}
return evm.ReadContractStorage(ctx, ws, contract, key)
return ws, nil
}

// PutBlock persists all changes in RunActions() into the DB
Expand Down
4 changes: 3 additions & 1 deletion state/factory/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,9 @@ func testSimulateExecution(ctx context.Context, sf Factory, t *testing.T) {
},
DepositGasFunc: rewarding.DepositGas,
})
_, _, err = sf.SimulateExecution(ctx, addr, elp)
ws, err := sf.WorkingSetNotWritable(ctx, 0, false)
require.NoError(err)
_, _, err = evm.SimulateExecution(ctx, ws, addr, elp)
require.NoError(err)
}

Expand Down
51 changes: 12 additions & 39 deletions state/factory/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (

"github.com/iotexproject/go-pkgs/cache"
"github.com/iotexproject/go-pkgs/hash"
"github.com/iotexproject/iotex-address/address"

"github.com/iotexproject/iotex-core/v2/action"
"github.com/iotexproject/iotex-core/v2/action/protocol"
Expand All @@ -30,7 +29,6 @@ import (
"github.com/iotexproject/iotex-core/v2/db/batch"
"github.com/iotexproject/iotex-core/v2/pkg/log"
"github.com/iotexproject/iotex-core/v2/pkg/prometheustimer"
"github.com/iotexproject/iotex-core/v2/pkg/tracer"
"github.com/iotexproject/iotex-core/v2/pkg/util/byteutil"
"github.com/iotexproject/iotex-core/v2/state"
)
Expand Down Expand Up @@ -261,46 +259,21 @@ func (sdb *stateDB) NewBlockBuilder(
return blkBuilder, nil
}

// SimulateExecution simulates a running of smart contract operation, this is done off the network since it does not
// cause any state change
func (sdb *stateDB) SimulateExecution(
ctx context.Context,
caller address.Address,
elp action.Envelope,
opts ...protocol.SimulateOption,
) ([]byte, *action.Receipt, error) {
ctx, span := tracer.NewSpan(ctx, "stateDB.SimulateExecution")
defer span.End()

sdb.mutex.RLock()
currHeight := sdb.currentChainHeight
sdb.mutex.RUnlock()
ws, err := sdb.newWorkingSet(ctx, currHeight+1)
if err != nil {
return nil, nil, err
}
cfg := &protocol.SimulateOptionConfig{}
for _, opt := range opts {
opt(cfg)
}
if cfg.PreOpt != nil {
if err := cfg.PreOpt(ws); err != nil {
return nil, nil, err
}
func (sdb *stateDB) WorkingSetNotWritable(ctx context.Context, height uint64, isArchive bool) (protocol.StateManager, error) {
var (
ws *workingSet
err error
)
if !isArchive {
sdb.mutex.RLock()
height = sdb.currentChainHeight
sdb.mutex.RUnlock()
}
return evm.SimulateExecution(ctx, ws, caller, elp)
}

// ReadContractStorage reads contract's storage
func (sdb *stateDB) ReadContractStorage(ctx context.Context, contract address.Address, key []byte) ([]byte, error) {
sdb.mutex.RLock()
currHeight := sdb.currentChainHeight
sdb.mutex.RUnlock()
ws, err := sdb.newWorkingSet(ctx, currHeight+1)
ws, err = sdb.newWorkingSet(ctx, height+1)
if err != nil {
return nil, errors.Wrap(err, "failed to generate working set from state db")
return nil, errors.Wrap(err, "failed to obtain working set from state factory")
}
return evm.ReadContractStorage(ctx, ws, contract, key)
return ws, nil
}

// PutBlock persists all changes in RunActions() into the DB
Expand Down
52 changes: 15 additions & 37 deletions test/mock/mock_factory/mock_factory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 90a858a

Please sign in to comment.