gas estimation shed command
This commit is contained in:
parent
04f0af5865
commit
cde4b804e3
@ -69,6 +69,10 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
||||||
},
|
},
|
||||||
DrandIncentinet: {
|
DrandIncentinet: {
|
||||||
|
Servers: []string{
|
||||||
|
"https://dev1.drand.sh",
|
||||||
|
"https://dev2.drand.sh",
|
||||||
|
},
|
||||||
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
|
|||||||
|
|
||||||
client, err := dclient.Wrap(clients, opts...)
|
client, err := dclient.Wrap(clients, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("creating drand client")
|
return nil, xerrors.Errorf("creating drand client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lc, err := lru.New(1024)
|
lc, err := lru.New(1024)
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
@ -153,6 +154,82 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) CallAtStateAndVersion(ctx context.Context, msg *types.Message, ts *types.TipSet, stateCid cid.Cid, v network.Version) (*api.InvocResult, error) {
|
||||||
|
r := rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, sm.GetNetworkVersion)
|
||||||
|
|
||||||
|
buffStore := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync())
|
||||||
|
vmopt := &vm.VMOpts{
|
||||||
|
StateBase: stateCid,
|
||||||
|
Epoch: ts.Height() + 1,
|
||||||
|
Rand: r,
|
||||||
|
Bstore: buffStore,
|
||||||
|
Actors: sm.tsExec.NewActorRegistry(),
|
||||||
|
Syscalls: sm.Syscalls,
|
||||||
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
|
NetworkVersion: v,
|
||||||
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
|
LookbackState: LookbackStateGetterForTipset(sm, ts),
|
||||||
|
Tracing: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
vmi, err := sm.newVM(ctx, vmopt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stTree, err := state.LoadStateTree(cbor.NewCborStore(buffStore), stateCid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("loading state tree: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fromActor, err := stTree.GetActor(msg.From)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("call raw get actor: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Nonce = fromActor.Nonce
|
||||||
|
|
||||||
|
fromKey, err := sm.ResolveToKeyAddress(ctx, msg.From, ts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("could not resolve key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgApply types.ChainMsg
|
||||||
|
|
||||||
|
switch fromKey.Protocol() {
|
||||||
|
case address.BLS:
|
||||||
|
msgApply = msg
|
||||||
|
case address.SECP256K1:
|
||||||
|
msgApply = &types.SignedMessage{
|
||||||
|
Message: *msg,
|
||||||
|
Signature: crypto.Signature{
|
||||||
|
Type: crypto.SigTypeSecp256k1,
|
||||||
|
Data: make([]byte, 65),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := vmi.ApplyMessage(ctx, msgApply)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("gas estimation failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errs string
|
||||||
|
if ret.ActorErr != nil {
|
||||||
|
errs = ret.ActorErr.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.InvocResult{
|
||||||
|
MsgCid: msg.Cid(),
|
||||||
|
Msg: msg,
|
||||||
|
MsgRct: &ret.MessageReceipt,
|
||||||
|
GasCost: MakeMsgGasCost(msg, ret),
|
||||||
|
ExecutionTrace: ret.ExecutionTrace,
|
||||||
|
Error: errs,
|
||||||
|
Duration: ret.Duration,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
|
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "statemanager.CallWithGas")
|
ctx, span := trace.StartSpan(ctx, "statemanager.CallWithGas")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
153
cmd/lotus-shed/gas-estimation.go
Normal file
153
cmd/lotus-shed/gas-estimation.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/beacon"
|
||||||
|
"github.com/filecoin-project/lotus/chain/beacon/drand"
|
||||||
|
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||||
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
|
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var gasEstimationCmd = &cli.Command{
|
||||||
|
Name: "estimate-gas",
|
||||||
|
Description: "replay a message on the specified stateRoot and network version",
|
||||||
|
ArgsUsage: "[migratedStateRootCid migrationEpoch networkVersion messageHash]",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo",
|
||||||
|
Value: "~/.lotus",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
if cctx.NArg() != 4 {
|
||||||
|
return lcli.IncorrectNumArgs(cctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
stateRootCid, err := cid.Decode(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse input: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
epoch, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse input: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nv, err := strconv.ParseInt(cctx.Args().Get(2), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse input: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
messageCid, err := cid.Decode(cctx.Args().Get(3))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse input: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fsrepo, err := repo.NewFS(cctx.String("repo"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lkrepo, err := fsrepo.Lock(repo.FullNode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer lkrepo.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open blockstore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if c, ok := bs.(io.Closer); ok {
|
||||||
|
if err := c.Close(); err != nil {
|
||||||
|
log.Warnf("failed to close blockstore: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dcs := build.DrandConfigSchedule()
|
||||||
|
shd := beacon.Schedule{}
|
||||||
|
for _, dc := range dcs {
|
||||||
|
bc, err := drand.NewDrandBeacon(1598306400, build.BlockDelaySecs, nil, dc.Config)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("creating drand beacon: %w", err)
|
||||||
|
}
|
||||||
|
shd = append(shd, beacon.BeaconPoint{Start: dc.Start, Beacon: bc})
|
||||||
|
}
|
||||||
|
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
|
||||||
|
defer cs.Close() //nolint:errcheck
|
||||||
|
|
||||||
|
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), shd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := cs.GetMessage(ctx, messageCid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to block limit so message will not run out of gas
|
||||||
|
msg.GasLimit = 10_000_000_000
|
||||||
|
|
||||||
|
err = cs.Load(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
executionTs, err := cs.GetTipsetByHeight(ctx, abi.ChainEpoch(epoch), nil, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tw := tabwriter.NewWriter(os.Stdout, 2, 2, 2, ' ', 0)
|
||||||
|
res, err := sm.CallAtStateAndVersion(ctx, msg, executionTs, stateRootCid, network.Version(nv))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
printInternalExecutions(0, []types.ExecutionTrace{res.ExecutionTrace}, tw)
|
||||||
|
|
||||||
|
return tw.Flush()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func printInternalExecutions(depth int, trace []types.ExecutionTrace, tw *tabwriter.Writer) {
|
||||||
|
if depth == 0 {
|
||||||
|
_, _ = fmt.Fprintf(tw, "depth\tFrom\tTo\tValue\tMethod\tGasUsed\tExitCode\tReturn\n")
|
||||||
|
}
|
||||||
|
for _, im := range trace {
|
||||||
|
_, _ = fmt.Fprintf(tw, "%d\t%s\t%s\t%s\t%d\t%d\t%d\t%x\n", depth, im.Msg.From, im.Msg.To, im.Msg.Value, im.Msg.Method, im.MsgRct.GasUsed, im.MsgRct.ExitCode, im.MsgRct.Return)
|
||||||
|
printInternalExecutions(depth+1, im.Subcalls, tw)
|
||||||
|
}
|
||||||
|
}
|
@ -76,6 +76,7 @@ func main() {
|
|||||||
msigCmd,
|
msigCmd,
|
||||||
fip36PollCmd,
|
fip36PollCmd,
|
||||||
invariantsCmd,
|
invariantsCmd,
|
||||||
|
gasEstimationCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
app := &cli.App{
|
app := &cli.App{
|
||||||
|
Loading…
Reference in New Issue
Block a user