Merge remote-tracking branch 'origin/next' into feat/faster-v2-upgrade
This commit is contained in:
commit
8dd8892b81
@ -3,6 +3,9 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
@ -13,8 +16,10 @@ const BreezeGasTampingDuration = 0
|
|||||||
|
|
||||||
const UpgradeSmokeHeight = -1
|
const UpgradeSmokeHeight = -1
|
||||||
const UpgradeIgnitionHeight = -2
|
const UpgradeIgnitionHeight = -2
|
||||||
const UpgradeLiftoffHeight = -3
|
const UpgradeRefuelHeight = -3
|
||||||
const UpgradeActorsV2Height = 10
|
|
||||||
|
var UpgradeActorsV2Height = abi.ChainEpoch(10)
|
||||||
|
var UpgradeLiftoffHeight = abi.ChainEpoch(-4)
|
||||||
|
|
||||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
@ -25,6 +30,11 @@ func init() {
|
|||||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||||
|
|
||||||
|
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
|
||||||
|
UpgradeActorsV2Height = math.MaxInt64
|
||||||
|
UpgradeLiftoffHeight = 11
|
||||||
|
}
|
||||||
|
|
||||||
BuildType |= Build2k
|
BuildType |= Build2k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,9 @@ var (
|
|||||||
|
|
||||||
UpgradeSmokeHeight abi.ChainEpoch = -1
|
UpgradeSmokeHeight abi.ChainEpoch = -1
|
||||||
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
UpgradeIgnitionHeight abi.ChainEpoch = -2
|
||||||
UpgradeLiftoffHeight abi.ChainEpoch = -3
|
UpgradeRefuelHeight abi.ChainEpoch = -3
|
||||||
UpgradeActorsV2Height abi.ChainEpoch = 10
|
UpgradeActorsV2Height abi.ChainEpoch = 10
|
||||||
|
UpgradeLiftoffHeight abi.ChainEpoch = -4
|
||||||
|
|
||||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||||
@ -23,9 +26,9 @@ const BreezeGasTampingDuration = 120
|
|||||||
const UpgradeSmokeHeight = 51000
|
const UpgradeSmokeHeight = 51000
|
||||||
|
|
||||||
const UpgradeIgnitionHeight = 94000
|
const UpgradeIgnitionHeight = 94000
|
||||||
|
const UpgradeRefuelHeight = 130800
|
||||||
|
|
||||||
// TODO: Actual epoch needs to be filled in
|
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
|
||||||
const UpgradeActorsV2Height = 128888
|
|
||||||
|
|
||||||
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
||||||
// Miners, clients, developers, custodians all need time to prepare.
|
// Miners, clients, developers, custodians all need time to prepare.
|
||||||
@ -39,7 +42,13 @@ func init() {
|
|||||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
|
||||||
SetAddressNetwork(address.Mainnet)
|
SetAddressNetwork(address.Mainnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
|
||||||
|
UpgradeActorsV2Height = math.MaxInt64
|
||||||
|
}
|
||||||
|
|
||||||
Devnet = false
|
Devnet = false
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
var SystemActorAddr = builtin0.SystemActorAddr
|
var SystemActorAddr = builtin0.SystemActorAddr
|
||||||
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
|
var BurntFundsActorAddr = builtin0.BurntFundsActorAddr
|
||||||
var ReserveAddress = makeAddress("t090")
|
var ReserveAddress = makeAddress("t090")
|
||||||
|
var RootVerifierAddress = makeAddress("t080")
|
||||||
|
|
||||||
// TODO: Why does actors have 2 different versions of this?
|
// TODO: Why does actors have 2 different versions of this?
|
||||||
type SectorInfo = proof0.SectorInfo
|
type SectorInfo = proof0.SectorInfo
|
||||||
|
180
chain/actors/builtin/miner/diff_deadlines.go
Normal file
180
chain/actors/builtin/miner/diff_deadlines.go
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
package miner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-bitfield"
|
||||||
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeadlinesDiff map[uint64]*DeadlineDiff
|
||||||
|
|
||||||
|
func DiffDeadlines(pre, cur State) (*DeadlinesDiff, error) {
|
||||||
|
changed, err := pre.DeadlinesChanged(cur)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !changed {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
numDl, err := pre.NumDeadlines()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dlDiff := make(DeadlinesDiff, numDl)
|
||||||
|
if err := pre.ForEachDeadline(func(idx uint64, preDl Deadline) error {
|
||||||
|
curDl, err := cur.LoadDeadline(idx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
diff, err := DiffDeadline(preDl, curDl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dlDiff[idx] = diff
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &dlDiff, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeadlineDiff map[uint64]*PartitionDiff
|
||||||
|
|
||||||
|
func DiffDeadline(pre, cur Deadline) (*DeadlineDiff, error) {
|
||||||
|
changed, err := pre.PartitionsChanged(cur)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !changed {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
partDiff := make(DeadlineDiff)
|
||||||
|
if err := pre.ForEachPartition(func(idx uint64, prePart Partition) error {
|
||||||
|
// try loading current partition at this index
|
||||||
|
curPart, err := cur.LoadPartition(idx)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, exitcode.ErrNotFound) {
|
||||||
|
// TODO correctness?
|
||||||
|
return nil // the partition was removed.
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare it with the previous partition
|
||||||
|
diff, err := DiffPartition(prePart, curPart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
partDiff[idx] = diff
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// all previous partitions have been walked.
|
||||||
|
// all partitions in cur and not in prev are new... can they be faulty already?
|
||||||
|
// TODO is this correct?
|
||||||
|
if err := cur.ForEachPartition(func(idx uint64, curPart Partition) error {
|
||||||
|
if _, found := partDiff[idx]; found {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
faults, err := curPart.FaultySectors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
recovering, err := curPart.RecoveringSectors()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
partDiff[idx] = &PartitionDiff{
|
||||||
|
Removed: bitfield.New(),
|
||||||
|
Recovered: bitfield.New(),
|
||||||
|
Faulted: faults,
|
||||||
|
Recovering: recovering,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &partDiff, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PartitionDiff struct {
|
||||||
|
Removed bitfield.BitField
|
||||||
|
Recovered bitfield.BitField
|
||||||
|
Faulted bitfield.BitField
|
||||||
|
Recovering bitfield.BitField
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiffPartition(pre, cur Partition) (*PartitionDiff, error) {
|
||||||
|
prevLiveSectors, err := pre.LiveSectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
curLiveSectors, err := cur.LiveSectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
removed, err := bitfield.SubtractBitField(prevLiveSectors, curLiveSectors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prevRecoveries, err := pre.RecoveringSectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
curRecoveries, err := cur.RecoveringSectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
recovering, err := bitfield.SubtractBitField(curRecoveries, prevRecoveries)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prevFaults, err := pre.FaultySectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
curFaults, err := cur.FaultySectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
faulted, err := bitfield.SubtractBitField(curFaults, prevFaults)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// all current good sectors
|
||||||
|
curActiveSectors, err := cur.ActiveSectors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// sectors that were previously fault and are now currently active are considered recovered.
|
||||||
|
recovered, err := bitfield.IntersectBitField(prevFaults, curActiveSectors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PartitionDiff{
|
||||||
|
Removed: removed,
|
||||||
|
Recovered: recovered,
|
||||||
|
Faulted: faulted,
|
||||||
|
Recovering: recovering,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -9,8 +9,8 @@ import (
|
|||||||
type Version int
|
type Version int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version0 = 0
|
Version0 Version = 0
|
||||||
Version2 = 2
|
Version2 Version = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
// Converts a network version into an actors adt version.
|
// Converts a network version into an actors adt version.
|
||||||
|
@ -26,7 +26,6 @@ import (
|
|||||||
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -117,7 +116,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
|||||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := state.NewStateTree(cst, actors.Version0)
|
state, err := state.NewStateTree(cst, types.StateTreeVersion0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
|
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
@ -26,7 +27,7 @@ var log = logging.Logger("statetree")
|
|||||||
// StateTree stores actors state by their ID.
|
// StateTree stores actors state by their ID.
|
||||||
type StateTree struct {
|
type StateTree struct {
|
||||||
root adt.Map
|
root adt.Map
|
||||||
version actors.Version // TODO
|
version types.StateTreeVersion
|
||||||
info cid.Cid
|
info cid.Cid
|
||||||
Store cbor.IpldStore
|
Store cbor.IpldStore
|
||||||
|
|
||||||
@ -120,21 +121,41 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
|
|||||||
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
|
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateTree(cst cbor.IpldStore, version actors.Version) (*StateTree, error) {
|
// VersionForNetwork returns the state tree version for the given network
|
||||||
|
// version.
|
||||||
|
func VersionForNetwork(ver network.Version) types.StateTreeVersion {
|
||||||
|
if actors.VersionForNetwork(ver) == actors.Version0 {
|
||||||
|
return types.StateTreeVersion0
|
||||||
|
}
|
||||||
|
return types.StateTreeVersion1
|
||||||
|
}
|
||||||
|
|
||||||
|
func adtForSTVersion(ver types.StateTreeVersion) actors.Version {
|
||||||
|
switch ver {
|
||||||
|
case types.StateTreeVersion0:
|
||||||
|
return actors.Version0
|
||||||
|
case types.StateTreeVersion1:
|
||||||
|
return actors.Version2
|
||||||
|
default:
|
||||||
|
panic("unhandled state tree version")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, error) {
|
||||||
var info cid.Cid
|
var info cid.Cid
|
||||||
switch version {
|
switch ver {
|
||||||
case actors.Version0:
|
case types.StateTreeVersion0:
|
||||||
// info is undefined
|
// info is undefined
|
||||||
case actors.Version2:
|
case types.StateTreeVersion1:
|
||||||
var err error
|
var err error
|
||||||
info, err = cst.Put(context.TODO(), new(types.StateInfo))
|
info, err = cst.Put(context.TODO(), new(types.StateInfo0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unsupported state tree version: %d", version)
|
return nil, xerrors.Errorf("unsupported state tree version: %d", ver)
|
||||||
}
|
}
|
||||||
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), version)
|
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -142,7 +163,7 @@ func NewStateTree(cst cbor.IpldStore, version actors.Version) (*StateTree, error
|
|||||||
return &StateTree{
|
return &StateTree{
|
||||||
root: root,
|
root: root,
|
||||||
info: info,
|
info: info,
|
||||||
version: version,
|
version: ver,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}, nil
|
||||||
@ -154,13 +175,16 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
|||||||
if err := cst.Get(context.TODO(), c, &root); err != nil {
|
if err := cst.Get(context.TODO(), c, &root); err != nil {
|
||||||
// We failed to decode as the new version, must be an old version.
|
// We failed to decode as the new version, must be an old version.
|
||||||
root.Actors = c
|
root.Actors = c
|
||||||
root.Version = actors.Version0
|
root.Version = types.StateTreeVersion0
|
||||||
}
|
}
|
||||||
|
|
||||||
switch root.Version {
|
switch root.Version {
|
||||||
case actors.Version0, actors.Version2:
|
case types.StateTreeVersion0, types.StateTreeVersion1:
|
||||||
// Load the actual state-tree HAMT.
|
// Load the actual state-tree HAMT.
|
||||||
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), root.Actors, actors.Version(root.Version))
|
nd, err := adt.AsMap(
|
||||||
|
adt.WrapStore(context.TODO(), cst), root.Actors,
|
||||||
|
adtForSTVersion(root.Version),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("loading hamt node %s failed: %s", c, err)
|
log.Errorf("loading hamt node %s failed: %s", c, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -169,7 +193,7 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
|||||||
return &StateTree{
|
return &StateTree{
|
||||||
root: nd,
|
root: nd,
|
||||||
info: root.Info,
|
info: root.Info,
|
||||||
version: actors.Version(root.Version),
|
version: root.Version,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}, nil
|
||||||
@ -309,11 +333,11 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
|
|||||||
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
|
||||||
}
|
}
|
||||||
// If we're version 0, return a raw tree.
|
// If we're version 0, return a raw tree.
|
||||||
if st.version == actors.Version0 {
|
if st.version == types.StateTreeVersion0 {
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
// Otherwise, return a versioned tree.
|
// Otherwise, return a versioned tree.
|
||||||
return st.Store.Put(ctx, &types.StateRoot{Version: uint64(st.version), Actors: root, Info: st.info})
|
return st.Store.Put(ctx, &types.StateRoot{Version: st.version, Actors: root, Info: st.info})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *StateTree) Snapshot(ctx context.Context) error {
|
func (st *StateTree) Snapshot(ctx context.Context) error {
|
||||||
@ -400,7 +424,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Version returns the version of the StateTree data structure in use.
|
// Version returns the version of the StateTree data structure in use.
|
||||||
func (st *StateTree) Version() actors.Version {
|
func (st *StateTree) Version() types.StateTreeVersion {
|
||||||
return st.version
|
return st.version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,12 @@ import (
|
|||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkStateTreeSet(b *testing.B) {
|
func BenchmarkStateTreeSet(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -46,7 +45,7 @@ func BenchmarkStateTreeSet(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkStateTreeSetFlush(b *testing.B) {
|
func BenchmarkStateTreeSetFlush(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -76,7 +75,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -118,7 +117,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
|
|||||||
|
|
||||||
func TestSetCache(t *testing.T) {
|
func TestSetCache(t *testing.T) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -155,7 +154,7 @@ func TestSetCache(t *testing.T) {
|
|||||||
func TestSnapshots(t *testing.T) {
|
func TestSnapshots(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -239,7 +238,7 @@ func assertNotHas(t *testing.T, st *StateTree, addr address.Address) {
|
|||||||
func TestStateTreeConsistency(t *testing.T) {
|
func TestStateTreeConsistency(t *testing.T) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
// TODO: ActorUpgrade: this test tests pre actors v2
|
// TODO: ActorUpgrade: this test tests pre actors v2
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(network.Version3))
|
st, err := NewStateTree(cst, VersionForNetwork(network.Version3))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package stmgr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
@ -17,17 +18,38 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrExpensiveFork = errors.New("refusing explicit call due to state fork at epoch")
|
||||||
|
|
||||||
func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
|
func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*api.InvocResult, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "statemanager.Call")
|
ctx, span := trace.StartSpan(ctx, "statemanager.Call")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
|
// If no tipset is provided, try to find one without a fork.
|
||||||
if ts == nil {
|
if ts == nil {
|
||||||
ts = sm.cs.GetHeaviestTipSet()
|
ts = sm.cs.GetHeaviestTipSet()
|
||||||
|
|
||||||
|
// Search back till we find a height with no fork, or we reach the beginning.
|
||||||
|
for ts.Height() > 0 && sm.hasExpensiveFork(ctx, ts.Height()-1) {
|
||||||
|
var err error
|
||||||
|
ts, err = sm.cs.GetTipSetFromKey(ts.Parents())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to find a non-forking epoch: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bstate := ts.ParentState()
|
bstate := ts.ParentState()
|
||||||
bheight := ts.Height()
|
bheight := ts.Height()
|
||||||
|
|
||||||
|
// If we have to run an expensive migration, and we're not at genesis,
|
||||||
|
// return an error because the migration will take too long.
|
||||||
|
//
|
||||||
|
// We allow this at height 0 for at-genesis migrations (for testing).
|
||||||
|
if bheight-1 > 0 && sm.hasExpensiveFork(ctx, bheight-1) {
|
||||||
|
return nil, ErrExpensiveFork
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the (not expensive) migration.
|
||||||
bstate, err := sm.handleStateForks(ctx, bstate, bheight-1, nil, ts)
|
bstate, err := sm.handleStateForks(ctx, bstate, bheight-1, nil, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to handle fork: %w", err)
|
return nil, fmt.Errorf("failed to handle fork: %w", err)
|
||||||
@ -44,7 +66,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
BaseFee: types.NewInt(0),
|
BaseFee: types.NewInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
vmi, err := vm.NewVM(ctx, vmopt)
|
vmi, err := sm.newVM(ctx, vmopt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
}
|
}
|
||||||
@ -106,6 +128,24 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
|
|
||||||
if ts == nil {
|
if ts == nil {
|
||||||
ts = sm.cs.GetHeaviestTipSet()
|
ts = sm.cs.GetHeaviestTipSet()
|
||||||
|
|
||||||
|
// Search back till we find a height with no fork, or we reach the beginning.
|
||||||
|
// We need the _previous_ height to have no fork, because we'll
|
||||||
|
// run the fork logic in `sm.TipSetState`. We need the _current_
|
||||||
|
// height to have no fork, because we'll run it inside this
|
||||||
|
// function before executing the given message.
|
||||||
|
for ts.Height() > 0 && (sm.hasExpensiveFork(ctx, ts.Height()) || sm.hasExpensiveFork(ctx, ts.Height()-1)) {
|
||||||
|
var err error
|
||||||
|
ts, err = sm.cs.GetTipSetFromKey(ts.Parents())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to find a non-forking epoch: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we're not at the genesis block, make sure we don't have an expensive migration.
|
||||||
|
if ts.Height() > 0 && (sm.hasExpensiveFork(ctx, ts.Height()) || sm.hasExpensiveFork(ctx, ts.Height()-1)) {
|
||||||
|
return nil, ErrExpensiveFork
|
||||||
}
|
}
|
||||||
|
|
||||||
state, _, err := sm.TipSetState(ctx, ts)
|
state, _, err := sm.TipSetState(ctx, ts)
|
||||||
@ -138,7 +178,7 @@ func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, pri
|
|||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
}
|
}
|
||||||
vmi, err := vm.NewVM(ctx, vmopt)
|
vmi, err := sm.newVM(ctx, vmopt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
return nil, xerrors.Errorf("failed to set up vm: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"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"
|
||||||
@ -25,7 +27,6 @@ import (
|
|||||||
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
|
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
|
||||||
@ -37,11 +38,19 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/bufbstore"
|
"github.com/filecoin-project/lotus/lib/bufbstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpgradeFunc func(context.Context, *StateManager, ExecCallback, cid.Cid, *types.TipSet) (cid.Cid, error)
|
// UpgradeFunc is a migration function run at every upgrade.
|
||||||
|
//
|
||||||
|
// - The oldState is the state produced by the upgrade epoch.
|
||||||
|
// - The returned newState is the new state that will be used by the next epoch.
|
||||||
|
// - The height is the upgrade epoch height (already executed).
|
||||||
|
// - The tipset is the tipset for the last non-null block before the upgrade. Do
|
||||||
|
// not assume that ts.Height() is the upgrade height.
|
||||||
|
type UpgradeFunc func(ctx context.Context, sm *StateManager, cb ExecCallback, oldState cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (newState cid.Cid, err error)
|
||||||
|
|
||||||
type Upgrade struct {
|
type Upgrade struct {
|
||||||
Height abi.ChainEpoch
|
Height abi.ChainEpoch
|
||||||
Network network.Version
|
Network network.Version
|
||||||
|
Expensive bool
|
||||||
Migration UpgradeFunc
|
Migration UpgradeFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +59,7 @@ type UpgradeSchedule []Upgrade
|
|||||||
func DefaultUpgradeSchedule() UpgradeSchedule {
|
func DefaultUpgradeSchedule() UpgradeSchedule {
|
||||||
var us UpgradeSchedule
|
var us UpgradeSchedule
|
||||||
|
|
||||||
for _, u := range []Upgrade{{
|
updates := []Upgrade{{
|
||||||
Height: build.UpgradeBreezeHeight,
|
Height: build.UpgradeBreezeHeight,
|
||||||
Network: network.Version1,
|
Network: network.Version1,
|
||||||
Migration: UpgradeFaucetBurnRecovery,
|
Migration: UpgradeFaucetBurnRecovery,
|
||||||
@ -62,15 +71,46 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
|
|||||||
Height: build.UpgradeIgnitionHeight,
|
Height: build.UpgradeIgnitionHeight,
|
||||||
Network: network.Version3,
|
Network: network.Version3,
|
||||||
Migration: UpgradeIgnition,
|
Migration: UpgradeIgnition,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeRefuelHeight,
|
||||||
|
Network: network.Version3,
|
||||||
|
Migration: UpgradeRefuel,
|
||||||
}, {
|
}, {
|
||||||
Height: build.UpgradeActorsV2Height,
|
Height: build.UpgradeActorsV2Height,
|
||||||
Network: network.Version4,
|
Network: network.Version4,
|
||||||
|
Expensive: true,
|
||||||
Migration: UpgradeActorsV2,
|
Migration: UpgradeActorsV2,
|
||||||
}, {
|
}, {
|
||||||
Height: build.UpgradeLiftoffHeight,
|
Height: build.UpgradeLiftoffHeight,
|
||||||
Network: network.Version4,
|
Network: network.Version4,
|
||||||
Migration: UpgradeLiftoff,
|
Migration: UpgradeLiftoff,
|
||||||
}} {
|
}}
|
||||||
|
|
||||||
|
if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade
|
||||||
|
updates = []Upgrade{{
|
||||||
|
Height: build.UpgradeBreezeHeight,
|
||||||
|
Network: network.Version1,
|
||||||
|
Migration: UpgradeFaucetBurnRecovery,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeSmokeHeight,
|
||||||
|
Network: network.Version2,
|
||||||
|
Migration: nil,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeIgnitionHeight,
|
||||||
|
Network: network.Version3,
|
||||||
|
Migration: UpgradeIgnition,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeRefuelHeight,
|
||||||
|
Network: network.Version3,
|
||||||
|
Migration: UpgradeRefuel,
|
||||||
|
}, {
|
||||||
|
Height: build.UpgradeLiftoffHeight,
|
||||||
|
Network: network.Version3,
|
||||||
|
Migration: UpgradeLiftoff,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, u := range updates {
|
||||||
if u.Height < 0 {
|
if u.Height < 0 {
|
||||||
// upgrade disabled
|
// upgrade disabled
|
||||||
continue
|
continue
|
||||||
@ -112,7 +152,7 @@ func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, heig
|
|||||||
var err error
|
var err error
|
||||||
f, ok := sm.stateMigrations[height]
|
f, ok := sm.stateMigrations[height]
|
||||||
if ok {
|
if ok {
|
||||||
retCid, err = f(ctx, sm, cb, root, ts)
|
retCid, err = f(ctx, sm, cb, root, height, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return cid.Undef, err
|
||||||
}
|
}
|
||||||
@ -121,6 +161,11 @@ func (sm *StateManager) handleStateForks(ctx context.Context, root cid.Cid, heig
|
|||||||
return retCid, nil
|
return retCid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) hasExpensiveFork(ctx context.Context, height abi.ChainEpoch) bool {
|
||||||
|
_, ok := sm.expensiveUpgrades[height]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
|
func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address, amt abi.TokenAmount) error {
|
||||||
fromAct, err := tree.GetActor(from)
|
fromAct, err := tree.GetActor(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -183,7 +228,7 @@ func doTransfer(cb ExecCallback, tree types.StateTree, from, to address.Address,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
|
func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
// Some initial parameters
|
// Some initial parameters
|
||||||
FundsForMiners := types.FromFil(1_000_000)
|
FundsForMiners := types.FromFil(1_000_000)
|
||||||
LookbackEpoch := abi.ChainEpoch(32000)
|
LookbackEpoch := abi.ChainEpoch(32000)
|
||||||
@ -435,11 +480,9 @@ func UpgradeFaucetBurnRecovery(ctx context.Context, sm *StateManager, cb ExecCal
|
|||||||
return tree.Flush(ctx)
|
return tree.Flush(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
|
func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
store := sm.cs.Store(ctx)
|
store := sm.cs.Store(ctx)
|
||||||
|
|
||||||
epoch := ts.Height() - 1
|
|
||||||
|
|
||||||
if build.UpgradeLiftoffHeight <= epoch {
|
if build.UpgradeLiftoffHeight <= epoch {
|
||||||
return cid.Undef, xerrors.Errorf("liftoff height must be beyond ignition height")
|
return cid.Undef, xerrors.Errorf("liftoff height must be beyond ignition height")
|
||||||
}
|
}
|
||||||
@ -492,13 +535,42 @@ func UpgradeIgnition(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
|||||||
return tree.Flush(ctx)
|
return tree.Flush(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
|
func UpgradeRefuel(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
|
|
||||||
|
store := sm.cs.Store(ctx)
|
||||||
|
tree, err := sm.StateTree(root)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewFromString("t0122")
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("getting address: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resetMultisigVesting(ctx, store, tree, addr, 0, 0, big.Zero())
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resetMultisigVesting(ctx, store, tree, builtin.ReserveAddress, 0, 0, big.Zero())
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resetMultisigVesting(ctx, store, tree, builtin.RootVerifierAddress, 0, 0, big.Zero())
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("tweaking msig vesting: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree.Flush(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
buf := bufbstore.NewTieredBstore(sm.cs.Blockstore(), bstore.NewTemporarySync())
|
buf := bufbstore.NewTieredBstore(sm.cs.Blockstore(), bstore.NewTemporarySync())
|
||||||
store := store.ActorStore(ctx, buf)
|
store := store.ActorStore(ctx, buf)
|
||||||
|
|
||||||
epoch := ts.Height() - 1
|
info, err := store.Put(ctx, new(types.StateInfo0))
|
||||||
|
|
||||||
info, err := store.Put(ctx, new(types.StateInfo))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
|
||||||
}
|
}
|
||||||
@ -522,8 +594,7 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
|||||||
}
|
}
|
||||||
|
|
||||||
newRoot, err := store.Put(ctx, &types.StateRoot{
|
newRoot, err := store.Put(ctx, &types.StateRoot{
|
||||||
// TODO: ActorUpgrade: should be state-tree specific, not just the actors version.
|
Version: types.StateTreeVersion1,
|
||||||
Version: actors.Version2,
|
|
||||||
Actors: newHamtRoot,
|
Actors: newHamtRoot,
|
||||||
Info: info,
|
Info: info,
|
||||||
})
|
})
|
||||||
@ -554,7 +625,7 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
|||||||
return newRoot, nil
|
return newRoot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpgradeLiftoff(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
|
func UpgradeLiftoff(ctx context.Context, sm *StateManager, cb ExecCallback, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
tree, err := sm.StateTree(root)
|
tree, err := sm.StateTree(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
return cid.Undef, xerrors.Errorf("getting state tree: %w", err)
|
||||||
@ -712,6 +783,7 @@ func makeKeyAddr(splitAddr address.Address, count uint64) (address.Address, erro
|
|||||||
return addr, nil
|
return addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: After the Liftoff epoch, refactor this to use resetMultisigVesting
|
||||||
func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree, startEpoch abi.ChainEpoch) error {
|
func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store, tree *state.StateTree, startEpoch abi.ChainEpoch) error {
|
||||||
gb, err := sm.cs.GetGenesis()
|
gb, err := sm.cs.GetGenesis()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -761,3 +833,34 @@ func resetGenesisMsigs(ctx context.Context, sm *StateManager, store adt0.Store,
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resetMultisigVesting(ctx context.Context, store adt0.Store, tree *state.StateTree, addr address.Address, startEpoch abi.ChainEpoch, duration abi.ChainEpoch, balance abi.TokenAmount) error {
|
||||||
|
act, err := tree.GetActor(addr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !builtin.IsMultisigActor(act.Code) {
|
||||||
|
return xerrors.Errorf("actor wasn't msig: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var msigState multisig0.State
|
||||||
|
if err := store.Get(ctx, act.Head, &msigState); err != nil {
|
||||||
|
return xerrors.Errorf("reading multisig state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
msigState.StartEpoch = startEpoch
|
||||||
|
msigState.UnlockDuration = duration
|
||||||
|
msigState.InitialBalance = balance
|
||||||
|
|
||||||
|
act.Head, err = store.Put(ctx, &msigState)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("writing new multisig state: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tree.SetActor(addr, act); err != nil {
|
||||||
|
return xerrors.Errorf("setting multisig actor: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -10,8 +10,9 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/go-state-types/cbor"
|
"github.com/filecoin-project/go-state-types/cbor"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
||||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
@ -76,7 +77,7 @@ func (ta testActor) Exports() []interface{} {
|
|||||||
func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue {
|
func (ta *testActor) Constructor(rt runtime.Runtime, params *abi.EmptyValue) *abi.EmptyValue {
|
||||||
rt.ValidateImmediateCallerAcceptAny()
|
rt.ValidateImmediateCallerAcceptAny()
|
||||||
rt.StateCreate(&testActorState{11})
|
rt.StateCreate(&testActorState{11})
|
||||||
fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver())
|
//fmt.Println("NEW ACTOR ADDRESS IS: ", rt.Receiver())
|
||||||
|
|
||||||
return abi.Empty
|
return abi.Empty
|
||||||
}
|
}
|
||||||
@ -120,7 +121,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
Network: 1,
|
Network: 1,
|
||||||
Height: testForkHeight,
|
Height: testForkHeight,
|
||||||
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
|
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
|
||||||
root cid.Cid, ts *types.TipSet) (cid.Cid, error) {
|
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore())
|
cst := ipldcbor.NewCborStore(sm.ChainStore().Blockstore())
|
||||||
|
|
||||||
st, err := sm.StateTree(root)
|
st, err := sm.StateTree(root)
|
||||||
@ -173,7 +174,7 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
|
|
||||||
var msgs []*types.SignedMessage
|
var msgs []*types.SignedMessage
|
||||||
|
|
||||||
enc, err := actors.SerializeParams(&init_.ExecParams{CodeCID: (testActor{}).Code()})
|
enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -233,3 +234,84 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForkRefuseCall(t *testing.T) {
|
||||||
|
logging.SetAllLoggers(logging.LevelInfo)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
cg, err := gen.NewGenerator()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sm, err := NewStateManagerWithUpgradeSchedule(
|
||||||
|
cg.ChainStore(), UpgradeSchedule{{
|
||||||
|
Network: 1,
|
||||||
|
Expensive: true,
|
||||||
|
Height: testForkHeight,
|
||||||
|
Migration: func(ctx context.Context, sm *StateManager, cb ExecCallback,
|
||||||
|
root cid.Cid, height abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||||
|
return root, nil
|
||||||
|
}}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
inv := vm.NewActorRegistry()
|
||||||
|
inv.Register(nil, testActor{})
|
||||||
|
|
||||||
|
sm.SetVMConstructor(func(ctx context.Context, vmopt *vm.VMOpts) (*vm.VM, error) {
|
||||||
|
nvm, err := vm.NewVM(ctx, vmopt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nvm.SetInvoker(inv)
|
||||||
|
return nvm, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
cg.SetStateManager(sm)
|
||||||
|
|
||||||
|
enc, err := actors.SerializeParams(&init0.ExecParams{CodeCID: (testActor{}).Code()})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &types.Message{
|
||||||
|
From: cg.Banker(),
|
||||||
|
To: lotusinit.Address,
|
||||||
|
Method: builtin.MethodsInit.Exec,
|
||||||
|
Params: enc,
|
||||||
|
GasLimit: types.TestGasLimit,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
GasPremium: types.NewInt(0),
|
||||||
|
GasFeeCap: types.NewInt(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
ts, err := cg.NextTipSet()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := sm.CallWithGas(ctx, m, nil, ts.TipSet.TipSet())
|
||||||
|
switch ts.TipSet.TipSet().Height() {
|
||||||
|
case testForkHeight, testForkHeight + 1:
|
||||||
|
// If I had a fork, or I _will_ have a fork, it should fail.
|
||||||
|
require.Equal(t, ErrExpensiveFork, err)
|
||||||
|
default:
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
||||||
|
}
|
||||||
|
// Call just runs on the parent state for a tipset, so we only
|
||||||
|
// expect an error at the fork height.
|
||||||
|
ret, err = sm.Call(ctx, m, ts.TipSet.TipSet())
|
||||||
|
switch ts.TipSet.TipSet().Height() {
|
||||||
|
case testForkHeight + 1:
|
||||||
|
require.Equal(t, ErrExpensiveFork, err)
|
||||||
|
default:
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, ret.MsgRct.ExitCode.IsSuccess())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -53,6 +53,10 @@ type StateManager struct {
|
|||||||
|
|
||||||
// Maps chain epochs to upgrade functions.
|
// Maps chain epochs to upgrade functions.
|
||||||
stateMigrations map[abi.ChainEpoch]UpgradeFunc
|
stateMigrations map[abi.ChainEpoch]UpgradeFunc
|
||||||
|
// A set of potentially expensive/time consuming upgrades. Explicit
|
||||||
|
// calls for, e.g., gas estimation fail against this epoch with
|
||||||
|
// ErrExpensiveFork.
|
||||||
|
expensiveUpgrades map[abi.ChainEpoch]struct{}
|
||||||
|
|
||||||
stCache map[string][]cid.Cid
|
stCache map[string][]cid.Cid
|
||||||
compWait map[string]chan struct{}
|
compWait map[string]chan struct{}
|
||||||
@ -78,6 +82,7 @@ func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule
|
|||||||
}
|
}
|
||||||
|
|
||||||
stateMigrations := make(map[abi.ChainEpoch]UpgradeFunc, len(us))
|
stateMigrations := make(map[abi.ChainEpoch]UpgradeFunc, len(us))
|
||||||
|
expensiveUpgrades := make(map[abi.ChainEpoch]struct{}, len(us))
|
||||||
var networkVersions []versionSpec
|
var networkVersions []versionSpec
|
||||||
lastVersion := network.Version0
|
lastVersion := network.Version0
|
||||||
if len(us) > 0 {
|
if len(us) > 0 {
|
||||||
@ -87,6 +92,9 @@ func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule
|
|||||||
if upgrade.Migration != nil {
|
if upgrade.Migration != nil {
|
||||||
stateMigrations[upgrade.Height] = upgrade.Migration
|
stateMigrations[upgrade.Height] = upgrade.Migration
|
||||||
}
|
}
|
||||||
|
if upgrade.Expensive {
|
||||||
|
expensiveUpgrades[upgrade.Height] = struct{}{}
|
||||||
|
}
|
||||||
networkVersions = append(networkVersions, versionSpec{
|
networkVersions = append(networkVersions, versionSpec{
|
||||||
networkVersion: lastVersion,
|
networkVersion: lastVersion,
|
||||||
atOrBelow: upgrade.Height,
|
atOrBelow: upgrade.Height,
|
||||||
@ -102,6 +110,7 @@ func NewStateManagerWithUpgradeSchedule(cs *store.ChainStore, us UpgradeSchedule
|
|||||||
networkVersions: networkVersions,
|
networkVersions: networkVersions,
|
||||||
latestVersion: lastVersion,
|
latestVersion: lastVersion,
|
||||||
stateMigrations: stateMigrations,
|
stateMigrations: stateMigrations,
|
||||||
|
expensiveUpgrades: expensiveUpgrades,
|
||||||
newVM: vm.NewVM,
|
newVM: vm.NewVM,
|
||||||
cs: cs,
|
cs: cs,
|
||||||
stCache: make(map[string][]cid.Cid),
|
stCache: make(map[string][]cid.Cid),
|
||||||
|
@ -387,7 +387,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
|||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
}
|
}
|
||||||
vmi, err := vm.NewVM(ctx, vmopt)
|
vmi, err := sm.newVM(ctx, vmopt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, nil, err
|
return cid.Undef, nil, err
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1648,7 @@ func (t *StateRoot) MarshalCBOR(w io.Writer) error {
|
|||||||
|
|
||||||
scratch := make([]byte, 9)
|
scratch := make([]byte, 9)
|
||||||
|
|
||||||
// t.Version (uint64) (uint64)
|
// t.Version (types.StateTreeVersion) (uint64)
|
||||||
|
|
||||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1687,7 +1687,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.Version (uint64) (uint64)
|
// t.Version (types.StateTreeVersion) (uint64)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1698,7 +1698,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
if maj != cbg.MajUnsignedInt {
|
if maj != cbg.MajUnsignedInt {
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
}
|
}
|
||||||
t.Version = uint64(extra)
|
t.Version = StateTreeVersion(extra)
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.Actors (cid.Cid) (struct)
|
// t.Actors (cid.Cid) (struct)
|
||||||
@ -1728,22 +1728,22 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var lengthBufStateInfo = []byte{128}
|
var lengthBufStateInfo0 = []byte{128}
|
||||||
|
|
||||||
func (t *StateInfo) MarshalCBOR(w io.Writer) error {
|
func (t *StateInfo0) MarshalCBOR(w io.Writer) error {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write(lengthBufStateInfo); err != nil {
|
if _, err := w.Write(lengthBufStateInfo0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *StateInfo) UnmarshalCBOR(r io.Reader) error {
|
func (t *StateInfo0) UnmarshalCBOR(r io.Reader) error {
|
||||||
*t = StateInfo{}
|
*t = StateInfo0{}
|
||||||
|
|
||||||
br := cbg.GetPeeker(r)
|
br := cbg.GetPeeker(r)
|
||||||
scratch := make([]byte, 8)
|
scratch := make([]byte, 8)
|
||||||
|
@ -2,9 +2,20 @@ package types
|
|||||||
|
|
||||||
import "github.com/ipfs/go-cid"
|
import "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
// StateTreeVersion is the version of the state tree itself, independent of the
|
||||||
|
// network version or the actors version.
|
||||||
|
type StateTreeVersion uint64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateTreeVersion0 corresponds to actors < v2.
|
||||||
|
StateTreeVersion0 StateTreeVersion = iota
|
||||||
|
// StateTreeVersion1 corresponds to actors >= v2.
|
||||||
|
StateTreeVersion1
|
||||||
|
)
|
||||||
|
|
||||||
type StateRoot struct {
|
type StateRoot struct {
|
||||||
// State root version. Versioned along with actors (for now).
|
// State tree version.
|
||||||
Version uint64
|
Version StateTreeVersion
|
||||||
// Actors tree. The structure depends on the state root version.
|
// Actors tree. The structure depends on the state root version.
|
||||||
Actors cid.Cid
|
Actors cid.Cid
|
||||||
// Info. The structure depends on the state root version.
|
// Info. The structure depends on the state root version.
|
||||||
@ -12,4 +23,4 @@ type StateRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: version this.
|
// TODO: version this.
|
||||||
type StateInfo struct{}
|
type StateInfo0 struct{}
|
||||||
|
@ -70,12 +70,12 @@ func (ar *ActorRegistry) Invoke(codeCid cid.Cid, rt vmr.Runtime, method abi.Meth
|
|||||||
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver())
|
log.Errorf("no code for actor %s (Addr: %s)", codeCid, rt.Receiver())
|
||||||
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params))
|
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "no code for actor %s(%d)(%s)", codeCid, method, hex.EncodeToString(params))
|
||||||
}
|
}
|
||||||
|
if err := act.predicate(rt, act.vmActor); err != nil {
|
||||||
|
return nil, aerrors.Newf(exitcode.SysErrorIllegalActor, "unsupported actor: %s", err)
|
||||||
|
}
|
||||||
if method >= abi.MethodNum(len(act.methods)) || act.methods[method] == nil {
|
if method >= abi.MethodNum(len(act.methods)) || act.methods[method] == nil {
|
||||||
return nil, aerrors.Newf(exitcode.SysErrInvalidMethod, "no method %d on actor", method)
|
return nil, aerrors.Newf(exitcode.SysErrInvalidMethod, "no method %d on actor", method)
|
||||||
}
|
}
|
||||||
if err := act.predicate(rt, act.vmActor); err != nil {
|
|
||||||
return nil, aerrors.Newf(exitcode.SysErrInvalidMethod, "unsupported actor: %s", err)
|
|
||||||
}
|
|
||||||
return act.methods[method](rt, params)
|
return act.methods[method](rt, params)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,9 @@ func (m *Message) ValueReceived() abi.TokenAmount {
|
|||||||
return m.msg.Value
|
return m.msg.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableGasTracing, if true, outputs gas tracing in execution traces.
|
||||||
|
var EnableGasTracing = false
|
||||||
|
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
rt0.Message
|
rt0.Message
|
||||||
rt0.Syscalls
|
rt0.Syscalls
|
||||||
@ -477,7 +480,7 @@ func (rt *Runtime) stateCommit(oldh, newh cid.Cid) aerrors.ActorError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rt *Runtime) finilizeGasTracing() {
|
func (rt *Runtime) finilizeGasTracing() {
|
||||||
if enableTracing {
|
if EnableGasTracing {
|
||||||
if rt.lastGasCharge != nil {
|
if rt.lastGasCharge != nil {
|
||||||
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
|
rt.lastGasCharge.TimeTaken = time.Since(rt.lastGasChargeTime)
|
||||||
}
|
}
|
||||||
@ -509,11 +512,9 @@ func (rt *Runtime) chargeGasFunc(skip int) func(GasCharge) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var enableTracing = false
|
|
||||||
|
|
||||||
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
|
func (rt *Runtime) chargeGasInternal(gas GasCharge, skip int) aerrors.ActorError {
|
||||||
toUse := gas.Total()
|
toUse := gas.Total()
|
||||||
if enableTracing {
|
if EnableGasTracing {
|
||||||
var callers [10]uintptr
|
var callers [10]uintptr
|
||||||
|
|
||||||
cout := 0 //gruntime.Callers(2+skip, callers[:])
|
cout := 0 //gruntime.Callers(2+skip, callers[:])
|
||||||
|
@ -45,3 +45,23 @@ func TestRuntimePutErrors(t *testing.T) {
|
|||||||
rt.StorePut(&NotAVeryGoodMarshaler{})
|
rt.StorePut(&NotAVeryGoodMarshaler{})
|
||||||
t.Error("expected panic")
|
t.Error("expected panic")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkRuntime_CreateRuntimeChargeGas_TracingDisabled(b *testing.B) {
|
||||||
|
var (
|
||||||
|
cst = cbor.NewCborStore(nil)
|
||||||
|
gch = newGasCharge("foo", 1000, 1000)
|
||||||
|
)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
EnableGasTracing = false
|
||||||
|
noop := func() bool { return EnableGasTracing }
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
// flip the value and access it to make sure
|
||||||
|
// the compiler doesn't optimize away
|
||||||
|
EnableGasTracing = true
|
||||||
|
_ = noop()
|
||||||
|
EnableGasTracing = false
|
||||||
|
_ = (&Runtime{cst: cst}).chargeGasInternal(gch, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -236,7 +236,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
|
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
|
||||||
if enableTracing {
|
if EnableGasTracing {
|
||||||
rt.lastGasChargeTime = start
|
rt.lastGasChargeTime = start
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
rt.lastGasChargeTime = parent.lastGasChargeTime
|
rt.lastGasChargeTime = parent.lastGasChargeTime
|
||||||
|
69
cli/state.go
69
cli/state.go
@ -72,6 +72,7 @@ var stateCmd = &cli.Command{
|
|||||||
stateMsgCostCmd,
|
stateMsgCostCmd,
|
||||||
stateMinerInfo,
|
stateMinerInfo,
|
||||||
stateMarketCmd,
|
stateMarketCmd,
|
||||||
|
stateExecTraceCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +316,74 @@ var stateActiveSectorsCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateExecTraceCmd = &cli.Command{
|
||||||
|
Name: "exec-trace",
|
||||||
|
Usage: "Get the execution trace of a given message",
|
||||||
|
ArgsUsage: "<messageCid>",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if !cctx.Args().Present() {
|
||||||
|
return ShowHelp(cctx, fmt.Errorf("must pass message cid"))
|
||||||
|
}
|
||||||
|
|
||||||
|
mcid, err := cid.Decode(cctx.Args().First())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("message cid was invalid: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
capi, closer, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
msg, err := capi.ChainGetMessage(ctx, mcid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup, err := capi.StateSearchMsg(ctx, mcid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ts, err := capi.ChainGetTipSet(ctx, lookup.TipSet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pts, err := capi.ChainGetTipSet(ctx, ts.Parents())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cso, err := capi.StateCompute(ctx, pts.Height(), nil, pts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var trace *api.InvocResult
|
||||||
|
for _, t := range cso.Trace {
|
||||||
|
if t.Msg.From == msg.From && t.Msg.Nonce == msg.Nonce {
|
||||||
|
trace = t
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if trace == nil {
|
||||||
|
return fmt.Errorf("failed to find message in tipset trace output")
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := json.MarshalIndent(trace, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(out))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var stateReplaySetCmd = &cli.Command{
|
var stateReplaySetCmd = &cli.Command{
|
||||||
Name: "replay",
|
Name: "replay",
|
||||||
Usage: "Replay a particular message within a tipset",
|
Usage: "Replay a particular message within a tipset",
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/tools/stats"
|
"github.com/filecoin-project/lotus/tools/stats"
|
||||||
@ -342,6 +343,18 @@ var runCmd = &cli.Command{
|
|||||||
Usage: "process ProveCommitSector messages",
|
Usage: "process ProveCommitSector messages",
|
||||||
Value: true,
|
Value: true,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "windowed-post",
|
||||||
|
EnvVars: []string{"LOTUS_PCR_WINDOWED_POST"},
|
||||||
|
Usage: "process SubmitWindowedPoSt messages and refund gas fees",
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "storage-deals",
|
||||||
|
EnvVars: []string{"LOTUS_PCR_STORAGE_DEALS"},
|
||||||
|
Usage: "process PublishStorageDeals messages and refund gas fees",
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
&cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "head-delay",
|
Name: "head-delay",
|
||||||
EnvVars: []string{"LOTUS_PCR_HEAD_DELAY"},
|
EnvVars: []string{"LOTUS_PCR_HEAD_DELAY"},
|
||||||
@ -378,6 +391,18 @@ var runCmd = &cli.Command{
|
|||||||
Usage: "percent of refund to issue",
|
Usage: "percent of refund to issue",
|
||||||
Value: 110,
|
Value: 110,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pre-fee-cap-max",
|
||||||
|
EnvVars: []string{"LOTUS_PCR_PRE_FEE_CAP_MAX"},
|
||||||
|
Usage: "messages with a fee cap larger than this will be skipped when processing pre commit messages",
|
||||||
|
Value: "0.0000000001",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prove-fee-cap-max",
|
||||||
|
EnvVars: []string{"LOTUS_PCR_PROVE_FEE_CAP_MAX"},
|
||||||
|
Usage: "messages with a prove cap larger than this will be skipped when processing pre commit messages",
|
||||||
|
Value: "0.0000000001",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
go func() {
|
go func() {
|
||||||
@ -421,6 +446,8 @@ var runCmd = &cli.Command{
|
|||||||
dryRun := cctx.Bool("dry-run")
|
dryRun := cctx.Bool("dry-run")
|
||||||
preCommitEnabled := cctx.Bool("pre-commit")
|
preCommitEnabled := cctx.Bool("pre-commit")
|
||||||
proveCommitEnabled := cctx.Bool("prove-commit")
|
proveCommitEnabled := cctx.Bool("prove-commit")
|
||||||
|
windowedPoStEnabled := cctx.Bool("windowed-post")
|
||||||
|
publishStorageDealsEnabled := cctx.Bool("storage-deals")
|
||||||
aggregateTipsets := cctx.Int("aggregate-tipsets")
|
aggregateTipsets := cctx.Int("aggregate-tipsets")
|
||||||
minerRecoveryEnabled := cctx.Bool("miner-recovery")
|
minerRecoveryEnabled := cctx.Bool("miner-recovery")
|
||||||
minerRecoveryPeriod := abi.ChainEpoch(int64(cctx.Int("miner-recovery-period")))
|
minerRecoveryPeriod := abi.ChainEpoch(int64(cctx.Int("miner-recovery-period")))
|
||||||
@ -428,6 +455,16 @@ var runCmd = &cli.Command{
|
|||||||
minerRecoveryCutoff := uint64(cctx.Int("miner-recovery-cutoff"))
|
minerRecoveryCutoff := uint64(cctx.Int("miner-recovery-cutoff"))
|
||||||
minerRecoveryBonus := uint64(cctx.Int("miner-recovery-bonus"))
|
minerRecoveryBonus := uint64(cctx.Int("miner-recovery-bonus"))
|
||||||
|
|
||||||
|
preFeeCapMax, err := types.ParseFIL(cctx.String("pre-fee-cap-max"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
proveFeeCapMax, err := types.ParseFIL(cctx.String("prove-fee-cap-max"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
rf := &refunder{
|
rf := &refunder{
|
||||||
api: api,
|
api: api,
|
||||||
wallet: from,
|
wallet: from,
|
||||||
@ -438,6 +475,10 @@ var runCmd = &cli.Command{
|
|||||||
dryRun: dryRun,
|
dryRun: dryRun,
|
||||||
preCommitEnabled: preCommitEnabled,
|
preCommitEnabled: preCommitEnabled,
|
||||||
proveCommitEnabled: proveCommitEnabled,
|
proveCommitEnabled: proveCommitEnabled,
|
||||||
|
windowedPoStEnabled: windowedPoStEnabled,
|
||||||
|
publishStorageDealsEnabled: publishStorageDealsEnabled,
|
||||||
|
preFeeCapMax: types.BigInt(preFeeCapMax),
|
||||||
|
proveFeeCapMax: types.BigInt(proveFeeCapMax),
|
||||||
}
|
}
|
||||||
|
|
||||||
var refunds *MinersRefund = NewMinersRefund()
|
var refunds *MinersRefund = NewMinersRefund()
|
||||||
@ -589,7 +630,12 @@ type refunder struct {
|
|||||||
dryRun bool
|
dryRun bool
|
||||||
preCommitEnabled bool
|
preCommitEnabled bool
|
||||||
proveCommitEnabled bool
|
proveCommitEnabled bool
|
||||||
|
windowedPoStEnabled bool
|
||||||
|
publishStorageDealsEnabled bool
|
||||||
threshold big.Int
|
threshold big.Int
|
||||||
|
|
||||||
|
preFeeCapMax big.Int
|
||||||
|
proveFeeCapMax big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *refunder) FindMiners(ctx context.Context, tipset *types.TipSet, refunds *MinersRefund, owner, worker, control bool) (*MinersRefund, error) {
|
func (r *refunder) FindMiners(ctx context.Context, tipset *types.TipSet, refunds *MinersRefund, owner, worker, control bool) (*MinersRefund, error) {
|
||||||
@ -817,6 +863,147 @@ func (r *refunder) EnsureMinerMinimums(ctx context.Context, tipset *types.TipSet
|
|||||||
return refunds, nil
|
return refunds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *refunder) processTipsetStorageMarketActor(ctx context.Context, tipset *types.TipSet, msg api.Message, recp *types.MessageReceipt) (bool, string, types.BigInt, error) {
|
||||||
|
|
||||||
|
m := msg.Message
|
||||||
|
refundValue := types.NewInt(0)
|
||||||
|
var messageMethod string
|
||||||
|
|
||||||
|
switch m.Method {
|
||||||
|
case builtin0.MethodsMarket.PublishStorageDeals:
|
||||||
|
if !r.publishStorageDealsEnabled {
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMethod = "PublishStorageDeals"
|
||||||
|
|
||||||
|
if recp.ExitCode != exitcode.Ok {
|
||||||
|
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recp.ExitCode)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, messageMethod, refundValue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *refunder) processTipsetStorageMinerActor(ctx context.Context, tipset *types.TipSet, msg api.Message, recp *types.MessageReceipt) (bool, string, types.BigInt, error) {
|
||||||
|
|
||||||
|
m := msg.Message
|
||||||
|
refundValue := types.NewInt(0)
|
||||||
|
var messageMethod string
|
||||||
|
|
||||||
|
switch m.Method {
|
||||||
|
case builtin0.MethodsMiner.SubmitWindowedPoSt:
|
||||||
|
if !r.windowedPoStEnabled {
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMethod = "SubmitWindowedPoSt"
|
||||||
|
|
||||||
|
if recp.ExitCode != exitcode.Ok {
|
||||||
|
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recp.ExitCode)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
refundValue = types.BigMul(types.NewInt(uint64(recp.GasUsed)), tipset.Blocks()[0].ParentBaseFee)
|
||||||
|
case builtin0.MethodsMiner.ProveCommitSector:
|
||||||
|
if !r.proveCommitEnabled {
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMethod = "ProveCommitSector"
|
||||||
|
|
||||||
|
if recp.ExitCode != exitcode.Ok {
|
||||||
|
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recp.ExitCode)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.GasFeeCap.GreaterThan(r.proveFeeCapMax) {
|
||||||
|
log.Debugw("skipping high fee cap message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "gas_fee_cap", m.GasFeeCap, "fee_cap_max", r.proveFeeCapMax)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var sn abi.SectorNumber
|
||||||
|
|
||||||
|
var proveCommitSector miner0.ProveCommitSectorParams
|
||||||
|
if err := proveCommitSector.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil {
|
||||||
|
log.Warnw("failed to decode provecommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sn = proveCommitSector.SectorNumber
|
||||||
|
|
||||||
|
// We use the parent tipset key because precommit information is removed when ProveCommitSector is executed
|
||||||
|
precommitChainInfo, err := r.api.StateSectorPreCommitInfo(ctx, m.To, sn, tipset.Parents())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnw("failed to get precommit info for sector", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
precommitTipset, err := r.api.ChainGetTipSetByHeight(ctx, precommitChainInfo.PreCommitEpoch, tipset.Key())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("failed to lookup precommit epoch", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
collateral, err := r.api.StateMinerInitialPledgeCollateral(ctx, m.To, precommitChainInfo.Info, precommitTipset.Key())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnw("failed to get initial pledge collateral", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
collateral = big.Sub(collateral, precommitChainInfo.PreCommitDeposit)
|
||||||
|
if collateral.LessThan(big.Zero()) {
|
||||||
|
log.Debugw("skipping zero pledge collateral difference", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
refundValue = collateral
|
||||||
|
if r.refundPercent > 0 {
|
||||||
|
refundValue = types.BigMul(types.BigDiv(refundValue, types.NewInt(100)), types.NewInt(uint64(r.refundPercent)))
|
||||||
|
}
|
||||||
|
case builtin0.MethodsMiner.PreCommitSector:
|
||||||
|
if !r.preCommitEnabled {
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMethod = "PreCommitSector"
|
||||||
|
|
||||||
|
if recp.ExitCode != exitcode.Ok {
|
||||||
|
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recp.ExitCode)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.GasFeeCap.GreaterThan(r.preFeeCapMax) {
|
||||||
|
log.Debugw("skipping high fee cap message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "gas_fee_cap", m.GasFeeCap, "fee_cap_max", r.preFeeCapMax)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var precommitInfo miner.SectorPreCommitInfo
|
||||||
|
if err := precommitInfo.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil {
|
||||||
|
log.Warnw("failed to decode precommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
collateral, err := r.api.StateMinerInitialPledgeCollateral(ctx, m.To, precommitInfo, tipset.Key())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnw("failed to calculate initial pledge collateral", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", precommitInfo.SectorNumber)
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
refundValue = collateral
|
||||||
|
if r.refundPercent > 0 {
|
||||||
|
refundValue = types.BigMul(types.BigDiv(refundValue, types.NewInt(100)), types.NewInt(uint64(r.refundPercent)))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false, messageMethod, types.NewInt(0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, messageMethod, refundValue, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *refunder) ProcessTipset(ctx context.Context, tipset *types.TipSet, refunds *MinersRefund) (*MinersRefund, error) {
|
func (r *refunder) ProcessTipset(ctx context.Context, tipset *types.TipSet, refunds *MinersRefund) (*MinersRefund, error) {
|
||||||
cids := tipset.Cids()
|
cids := tipset.Cids()
|
||||||
if len(cids) == 0 {
|
if len(cids) == 0 {
|
||||||
@ -852,91 +1039,28 @@ func (r *refunder) ProcessTipset(ctx context.Context, tipset *types.TipSet, refu
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !builtin.IsStorageMinerActor(a.Code) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageMethod string
|
var messageMethod string
|
||||||
|
|
||||||
switch m.Method {
|
if m.To == market.Address {
|
||||||
case builtin0.MethodsMiner.ProveCommitSector:
|
var err error
|
||||||
if !r.proveCommitEnabled {
|
var processed bool
|
||||||
continue
|
processed, messageMethod, refundValue, err = r.processTipsetStorageMarketActor(ctx, tipset, msg, recps[i])
|
||||||
}
|
|
||||||
|
|
||||||
messageMethod = "ProveCommitSector"
|
|
||||||
|
|
||||||
if recps[i].ExitCode != exitcode.Ok {
|
|
||||||
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recps[i].ExitCode)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var sn abi.SectorNumber
|
|
||||||
|
|
||||||
var proveCommitSector miner0.ProveCommitSectorParams
|
|
||||||
if err := proveCommitSector.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil {
|
|
||||||
log.Warnw("failed to decode provecommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sn = proveCommitSector.SectorNumber
|
|
||||||
|
|
||||||
// We use the parent tipset key because precommit information is removed when ProveCommitSector is executed
|
|
||||||
precommitChainInfo, err := r.api.StateSectorPreCommitInfo(ctx, m.To, sn, tipset.Parents())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnw("failed to get precommit info for sector", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !processed {
|
||||||
precommitTipset, err := r.api.ChainGetTipSetByHeight(ctx, precommitChainInfo.PreCommitEpoch, tipset.Key())
|
continue
|
||||||
|
}
|
||||||
|
} else if builtin.IsStorageMinerActor(a.Code) {
|
||||||
|
var err error
|
||||||
|
var processed bool
|
||||||
|
processed, messageMethod, refundValue, err = r.processTipsetStorageMinerActor(ctx, tipset, msg, recps[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to lookup precommit epoch", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !processed {
|
||||||
collateral, err := r.api.StateMinerInitialPledgeCollateral(ctx, m.To, precommitChainInfo.Info, precommitTipset.Key())
|
|
||||||
if err != nil {
|
|
||||||
log.Warnw("failed to get initial pledge collateral", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
|
||||||
}
|
|
||||||
|
|
||||||
collateral = big.Sub(collateral, precommitChainInfo.PreCommitDeposit)
|
|
||||||
if collateral.LessThan(big.Zero()) {
|
|
||||||
log.Debugw("skipping zero pledge collateral difference", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", sn)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
refundValue = collateral
|
|
||||||
case builtin0.MethodsMiner.PreCommitSector:
|
|
||||||
if !r.preCommitEnabled {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
messageMethod = "PreCommitSector"
|
|
||||||
|
|
||||||
if recps[i].ExitCode != exitcode.Ok {
|
|
||||||
log.Debugw("skipping non-ok exitcode message", "method", messageMethod, "cid", msg.Cid, "miner", m.To, "exitcode", recps[i].ExitCode)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var precommitInfo miner.SectorPreCommitInfo
|
|
||||||
if err := precommitInfo.UnmarshalCBOR(bytes.NewBuffer(m.Params)); err != nil {
|
|
||||||
log.Warnw("failed to decode precommit params", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
collateral, err := r.api.StateMinerInitialPledgeCollateral(ctx, m.To, precommitInfo, tipset.Key())
|
|
||||||
if err != nil {
|
|
||||||
log.Warnw("failed to calculate initial pledge collateral", "err", err, "method", messageMethod, "cid", msg.Cid, "miner", m.To, "sector_number", precommitInfo.SectorNumber)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
refundValue = collateral
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.refundPercent > 0 {
|
|
||||||
refundValue = types.BigMul(types.BigDiv(refundValue, types.NewInt(100)), types.NewInt(uint64(r.refundPercent)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugw(
|
log.Debugw(
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/big"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -32,6 +34,10 @@ var noncefix = &cli.Command{
|
|||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "auto",
|
Name: "auto",
|
||||||
},
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "gas-fee-cap",
|
||||||
|
Usage: "specify gas fee cap for nonce filling messages",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||||
@ -84,15 +90,32 @@ var noncefix = &cli.Command{
|
|||||||
}
|
}
|
||||||
fmt.Printf("Creating %d filler messages (%d ~ %d)\n", end-start, start, end)
|
fmt.Printf("Creating %d filler messages (%d ~ %d)\n", end-start, start, end)
|
||||||
|
|
||||||
|
ts, err := api.ChainHead(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
feeCap := big.Mul(ts.Blocks()[0].ParentBaseFee, big.NewInt(2)) // default fee cap to 2 * parent base fee
|
||||||
|
if fcf := cctx.Int64("gas-fee-cap"); fcf != 0 {
|
||||||
|
feeCap = abi.NewTokenAmount(fcf)
|
||||||
|
}
|
||||||
|
|
||||||
for i := start; i < end; i++ {
|
for i := start; i < end; i++ {
|
||||||
msg := &types.Message{
|
msg := &types.Message{
|
||||||
From: addr,
|
From: addr,
|
||||||
To: addr,
|
To: addr,
|
||||||
Value: types.NewInt(1),
|
Value: types.NewInt(0),
|
||||||
Nonce: i,
|
Nonce: i,
|
||||||
|
GasLimit: 1000000,
|
||||||
|
GasFeeCap: feeCap,
|
||||||
|
GasPremium: abi.NewTokenAmount(5),
|
||||||
|
}
|
||||||
|
smsg, err := api.WalletSignMessage(ctx, addr, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = api.MpoolPushMessage(ctx, msg, nil)
|
_, err = api.MpoolPush(ctx, smsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,10 @@ const metaFile = "sectorstore.json"
|
|||||||
var storageCmd = &cli.Command{
|
var storageCmd = &cli.Command{
|
||||||
Name: "storage",
|
Name: "storage",
|
||||||
Usage: "manage sector storage",
|
Usage: "manage sector storage",
|
||||||
|
Description: `Sectors can be stored across many filesystem paths. These
|
||||||
|
commands provide ways to manage the storage the miner will used to store sectors
|
||||||
|
long term for proving (references as 'store') as well as how sectors will be
|
||||||
|
stored while moving through the sealing pipeline (references as 'seal').`,
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
storageAttachCmd,
|
storageAttachCmd,
|
||||||
storageListCmd,
|
storageListCmd,
|
||||||
@ -41,6 +45,25 @@ var storageCmd = &cli.Command{
|
|||||||
var storageAttachCmd = &cli.Command{
|
var storageAttachCmd = &cli.Command{
|
||||||
Name: "attach",
|
Name: "attach",
|
||||||
Usage: "attach local storage path",
|
Usage: "attach local storage path",
|
||||||
|
Description: `Storage can be attached to the miner using this command. The storage volume
|
||||||
|
list is stored local to the miner in $LOTUS_MINER_PATH/storage.json. We do not
|
||||||
|
recommend manually modifying this value without further understanding of the
|
||||||
|
storage system.
|
||||||
|
|
||||||
|
Each storage volume contains a configuration file which describes the
|
||||||
|
capabilities of the volume. When the '--init' flag is provided, this file will
|
||||||
|
be created using the additional flags.
|
||||||
|
|
||||||
|
Weight
|
||||||
|
A high weight value means data will be more likely to be stored in this path
|
||||||
|
|
||||||
|
Seal
|
||||||
|
Data for the sealing process will be stored here
|
||||||
|
|
||||||
|
Store
|
||||||
|
Finalized sectors that will be moved here for long term storage and be proven
|
||||||
|
over time
|
||||||
|
`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "init",
|
Name: "init",
|
||||||
|
@ -198,8 +198,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
Preroot: root,
|
Preroot: root,
|
||||||
Epoch: execTs.Height(),
|
Epoch: execTs.Height(),
|
||||||
Message: m,
|
Message: m,
|
||||||
CircSupply: &circSupplyDetail.FilCirculating,
|
CircSupply: circSupplyDetail.FilCirculating,
|
||||||
BaseFee: &basefee,
|
BaseFee: basefee,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to execute precursor message: %w", err)
|
return fmt.Errorf("failed to execute precursor message: %w", err)
|
||||||
@ -229,8 +229,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
Preroot: preroot,
|
Preroot: preroot,
|
||||||
Epoch: execTs.Height(),
|
Epoch: execTs.Height(),
|
||||||
Message: msg,
|
Message: msg,
|
||||||
CircSupply: &circSupplyDetail.FilCirculating,
|
CircSupply: circSupplyDetail.FilCirculating,
|
||||||
BaseFee: &basefee,
|
BaseFee: basefee,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to execute message: %w", err)
|
return fmt.Errorf("failed to execute message: %w", err)
|
||||||
@ -260,8 +260,8 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
|
|||||||
Preroot: preroot,
|
Preroot: preroot,
|
||||||
Epoch: execTs.Height(),
|
Epoch: execTs.Height(),
|
||||||
Message: msg,
|
Message: msg,
|
||||||
CircSupply: &circSupplyDetail.FilCirculating,
|
CircSupply: circSupplyDetail.FilCirculating,
|
||||||
BaseFee: &basefee,
|
BaseFee: basefee,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to execute message: %w", err)
|
return fmt.Errorf("failed to execute message: %w", err)
|
||||||
|
@ -2,6 +2,7 @@ package conformance
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
gobig "math/big"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||||
|
|
||||||
"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/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
"github.com/filecoin-project/test-vectors/schema"
|
"github.com/filecoin-project/test-vectors/schema"
|
||||||
@ -80,7 +82,7 @@ type ExecuteTipsetResult struct {
|
|||||||
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) {
|
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) {
|
||||||
var (
|
var (
|
||||||
syscalls = mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier))
|
syscalls = mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier))
|
||||||
vmRand = new(testRand)
|
vmRand = NewFixedRand()
|
||||||
|
|
||||||
cs = store.NewChainStore(bs, ds, syscalls)
|
cs = store.NewChainStore(bs, ds, syscalls)
|
||||||
sm = stmgr.NewStateManager(cs)
|
sm = stmgr.NewStateManager(cs)
|
||||||
@ -143,8 +145,12 @@ type ExecuteMessageParams struct {
|
|||||||
Preroot cid.Cid
|
Preroot cid.Cid
|
||||||
Epoch abi.ChainEpoch
|
Epoch abi.ChainEpoch
|
||||||
Message *types.Message
|
Message *types.Message
|
||||||
CircSupply *abi.TokenAmount
|
CircSupply abi.TokenAmount
|
||||||
BaseFee *abi.TokenAmount
|
BaseFee abi.TokenAmount
|
||||||
|
|
||||||
|
// Rand is an optional vm.Rand implementation to use. If nil, the driver
|
||||||
|
// will use a vm.Rand that returns a fixed value for all calls.
|
||||||
|
Rand vm.Rand
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecuteMessage executes a conformance test vector message in a temporary VM.
|
// ExecuteMessage executes a conformance test vector message in a temporary VM.
|
||||||
@ -155,14 +161,8 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
|
|||||||
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
|
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
|
||||||
}
|
}
|
||||||
|
|
||||||
basefee := DefaultBaseFee
|
if params.Rand == nil {
|
||||||
if params.BaseFee != nil {
|
params.Rand = NewFixedRand()
|
||||||
basefee = *params.BaseFee
|
|
||||||
}
|
|
||||||
|
|
||||||
circSupply := DefaultCirculatingSupply
|
|
||||||
if params.CircSupply != nil {
|
|
||||||
circSupply = *params.CircSupply
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy state manager; only to reference the GetNetworkVersion method,
|
// dummy state manager; only to reference the GetNetworkVersion method,
|
||||||
@ -172,13 +172,13 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
|
|||||||
vmOpts := &vm.VMOpts{
|
vmOpts := &vm.VMOpts{
|
||||||
StateBase: params.Preroot,
|
StateBase: params.Preroot,
|
||||||
Epoch: params.Epoch,
|
Epoch: params.Epoch,
|
||||||
Rand: &testRand{}, // TODO always succeeds; need more flexibility.
|
|
||||||
Bstore: bs,
|
Bstore: bs,
|
||||||
Syscalls: mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier)), // TODO always succeeds; need more flexibility.
|
Syscalls: mkFakedSigSyscalls(vm.Syscalls(ffiwrapper.ProofVerifier)), // TODO always succeeds; need more flexibility.
|
||||||
CircSupplyCalc: func(_ context.Context, _ abi.ChainEpoch, _ *state.StateTree) (abi.TokenAmount, error) {
|
CircSupplyCalc: func(_ context.Context, _ abi.ChainEpoch, _ *state.StateTree) (abi.TokenAmount, error) {
|
||||||
return circSupply, nil
|
return params.CircSupply, nil
|
||||||
},
|
},
|
||||||
BaseFee: basefee,
|
Rand: params.Rand,
|
||||||
|
BaseFee: params.BaseFee,
|
||||||
NtwkVersion: sm.GetNtwkVersion,
|
NtwkVersion: sm.GetNtwkVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,3 +231,22 @@ func toChainMsg(msg *types.Message) (ret types.ChainMsg) {
|
|||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BaseFeeOrDefault converts a basefee as passed in a test vector (go *big.Int
|
||||||
|
// type) to an abi.TokenAmount, or if nil it returns the DefaultBaseFee.
|
||||||
|
func BaseFeeOrDefault(basefee *gobig.Int) abi.TokenAmount {
|
||||||
|
if basefee == nil {
|
||||||
|
return DefaultBaseFee
|
||||||
|
}
|
||||||
|
return big.NewFromGo(basefee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CircSupplyOrDefault converts a circulating supply as passed in a test vector
|
||||||
|
// (go *big.Int type) to an abi.TokenAmount, or if nil it returns the
|
||||||
|
// DefaultCirculatingSupply.
|
||||||
|
func CircSupplyOrDefault(circSupply *gobig.Int) abi.TokenAmount {
|
||||||
|
if circSupply == nil {
|
||||||
|
return DefaultBaseFee
|
||||||
|
}
|
||||||
|
return big.NewFromGo(circSupply)
|
||||||
|
}
|
||||||
|
28
conformance/rand_fixed.go
Normal file
28
conformance/rand_fixed.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package conformance
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fixedRand struct{}
|
||||||
|
|
||||||
|
var _ vm.Rand = (*fixedRand)(nil)
|
||||||
|
|
||||||
|
// NewFixedRand creates a test vm.Rand that always returns fixed bytes value
|
||||||
|
// of utf-8 string 'i_am_random_____i_am_random_____'.
|
||||||
|
func NewFixedRand() vm.Rand {
|
||||||
|
return &fixedRand{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *fixedRand) GetChainRandomness(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
|
||||||
|
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *fixedRand) GetBeaconRandomness(_ context.Context, _ crypto.DomainSeparationTag, _ abi.ChainEpoch, _ []byte) ([]byte, error) {
|
||||||
|
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
|
||||||
|
}
|
@ -13,9 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"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/exitcode"
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
"github.com/filecoin-project/test-vectors/schema"
|
|
||||||
"github.com/ipfs/go-blockservice"
|
"github.com/ipfs/go-blockservice"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
ds "github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-datastore"
|
||||||
@ -24,6 +22,8 @@ import (
|
|||||||
"github.com/ipfs/go-merkledag"
|
"github.com/ipfs/go-merkledag"
|
||||||
"github.com/ipld/go-car"
|
"github.com/ipld/go-car"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/test-vectors/schema"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
"github.com/filecoin-project/lotus/lib/blockstore"
|
"github.com/filecoin-project/lotus/lib/blockstore"
|
||||||
@ -46,18 +46,6 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
|||||||
// Create a new Driver.
|
// Create a new Driver.
|
||||||
driver := NewDriver(ctx, vector.Selector, DriverOpts{DisableVMFlush: true})
|
driver := NewDriver(ctx, vector.Selector, DriverOpts{DisableVMFlush: true})
|
||||||
|
|
||||||
var circSupply *abi.TokenAmount
|
|
||||||
if cs := vector.Pre.CircSupply; cs != nil {
|
|
||||||
ta := big.NewFromGo(cs)
|
|
||||||
circSupply = &ta
|
|
||||||
}
|
|
||||||
|
|
||||||
var basefee *abi.TokenAmount
|
|
||||||
if bf := vector.Pre.BaseFee; bf != nil {
|
|
||||||
ta := big.NewFromGo(bf)
|
|
||||||
basefee = &ta
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply every message.
|
// Apply every message.
|
||||||
for i, m := range vector.ApplyMessages {
|
for i, m := range vector.ApplyMessages {
|
||||||
msg, err := types.DecodeMessage(m.Bytes)
|
msg, err := types.DecodeMessage(m.Bytes)
|
||||||
@ -76,8 +64,8 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
|
|||||||
Preroot: root,
|
Preroot: root,
|
||||||
Epoch: abi.ChainEpoch(epoch),
|
Epoch: abi.ChainEpoch(epoch),
|
||||||
Message: msg,
|
Message: msg,
|
||||||
CircSupply: circSupply,
|
BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee),
|
||||||
BaseFee: basefee,
|
CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatalf("fatal failure when executing message: %s", err)
|
r.Fatalf("fatal failure when executing message: %s", err)
|
||||||
|
@ -6,28 +6,16 @@ import (
|
|||||||
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/state"
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||||
|
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testRand struct{}
|
|
||||||
|
|
||||||
var _ vm.Rand = (*testRand)(nil)
|
|
||||||
|
|
||||||
func (r *testRand) GetChainRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
|
||||||
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *testRand) GetBeaconRandomness(ctx context.Context, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
|
||||||
return []byte("i_am_random_____i_am_random_____"), nil // 32 bytes.
|
|
||||||
}
|
|
||||||
|
|
||||||
type testSyscalls struct {
|
type testSyscalls struct {
|
||||||
runtime.Syscalls
|
runtime.Syscalls
|
||||||
}
|
}
|
||||||
|
5
extern/sector-storage/stores/local.go
vendored
5
extern/sector-storage/stores/local.go
vendored
@ -31,9 +31,14 @@ type StoragePath struct {
|
|||||||
// LocalStorageMeta [path]/sectorstore.json
|
// LocalStorageMeta [path]/sectorstore.json
|
||||||
type LocalStorageMeta struct {
|
type LocalStorageMeta struct {
|
||||||
ID ID
|
ID ID
|
||||||
|
|
||||||
|
// A high weight means data is more likely to be stored in this path
|
||||||
Weight uint64 // 0 = readonly
|
Weight uint64 // 0 = readonly
|
||||||
|
|
||||||
|
// Intermediate data for the sealing process will be stored here
|
||||||
CanSeal bool
|
CanSeal bool
|
||||||
|
|
||||||
|
// Finalized sectors that will be proved over time will be stored here
|
||||||
CanStore bool
|
CanStore bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
extern/test-vectors
vendored
2
extern/test-vectors
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 3a6e0b5e069b1452ce1a032aa315354d645f3ec4
|
Subproject commit 7471e2805fc3e459e4ee325775633e8ec76cb7c6
|
@ -27,7 +27,7 @@ func main() {
|
|||||||
types.ExpTipSet{},
|
types.ExpTipSet{},
|
||||||
types.BeaconEntry{},
|
types.BeaconEntry{},
|
||||||
types.StateRoot{},
|
types.StateRoot{},
|
||||||
types.StateInfo{},
|
types.StateInfo0{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -176,7 +176,8 @@
|
|||||||
"CompactPartitions",
|
"CompactPartitions",
|
||||||
"CompactSectorNumbers",
|
"CompactSectorNumbers",
|
||||||
"ConfirmUpdateWorkerKey",
|
"ConfirmUpdateWorkerKey",
|
||||||
"RepayDebt"
|
"RepayDebt",
|
||||||
|
"ChangeOwnerAddress"
|
||||||
],
|
],
|
||||||
"fil/2/storagepower": [
|
"fil/2/storagepower": [
|
||||||
"Send",
|
"Send",
|
||||||
|
@ -160,7 +160,18 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
|||||||
priorMsgs = append(priorMsgs, m)
|
priorMsgs = append(priorMsgs, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
// Try calling until we find a height with no migration.
|
||||||
|
var res *api.InvocResult
|
||||||
|
for {
|
||||||
|
res, err = a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||||
|
if err != stmgr.ErrExpensiveFork {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
|
||||||
|
if err != nil {
|
||||||
|
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, xerrors.Errorf("CallWithGas failed: %w", err)
|
return -1, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -307,12 +307,22 @@ func (a *StateAPI) StateMinerPower(ctx context.Context, addr address.Address, ts
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (*api.InvocResult, error) {
|
func (a *StateAPI) StateCall(ctx context.Context, msg *types.Message, tsk types.TipSetKey) (res *api.InvocResult, err error) {
|
||||||
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
ts, err := a.Chain.GetTipSetFromKey(tsk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||||
}
|
}
|
||||||
return a.StateManager.Call(ctx, msg, ts)
|
for {
|
||||||
|
res, err = a.StateManager.Call(ctx, msg, ts)
|
||||||
|
if err != stmgr.ErrExpensiveFork {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("getting parent tipset: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) {
|
func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid.Cid) (*api.InvocResult, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user