Merge remote-tracking branch 'origin/master' into refactor/net-upgrade
This commit is contained in:
commit
f7934b083c
12
cli/sync.go
12
cli/sync.go
@ -249,14 +249,24 @@ func SyncWait(ctx context.Context, napi api.FullNode) error {
|
||||
|
||||
ss := state.ActiveSyncs[working]
|
||||
|
||||
var baseHeight abi.ChainEpoch
|
||||
var target []cid.Cid
|
||||
var theight abi.ChainEpoch
|
||||
var heightDiff int64
|
||||
|
||||
if ss.Base != nil {
|
||||
baseHeight = ss.Base.Height()
|
||||
heightDiff = int64(ss.Base.Height())
|
||||
}
|
||||
if ss.Target != nil {
|
||||
target = ss.Target.Cids()
|
||||
theight = ss.Target.Height()
|
||||
heightDiff = int64(ss.Target.Height()) - heightDiff
|
||||
} else {
|
||||
heightDiff = 0
|
||||
}
|
||||
|
||||
fmt.Printf("\r\x1b[2KWorker %d: Target Height: %d\tTarget: %s\tState: %s\tHeight: %d", working, theight, target, ss.Stage, ss.Height)
|
||||
fmt.Printf("\r\x1b[2KWorker %d: Base Height: %d\tTarget Height: %d\t Height diff: %d\tTarget: %s\tState: %s\tHeight: %d", working, baseHeight, theight, heightDiff, target, ss.Stage, ss.Height)
|
||||
|
||||
if time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs) {
|
||||
fmt.Println("\nDone!")
|
||||
|
286
cmd/lotus-shed/consensus.go
Normal file
286
cmd/lotus-shed/consensus.go
Normal file
@ -0,0 +1,286 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/multiformats/go-multiaddr"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var consensusCmd = &cli.Command{
|
||||
Name: "consensus",
|
||||
Usage: "tools for gathering information about consensus between nodes",
|
||||
Flags: []cli.Flag{},
|
||||
Subcommands: []*cli.Command{
|
||||
consensusCheckCmd,
|
||||
},
|
||||
}
|
||||
|
||||
type consensusItem struct {
|
||||
multiaddr multiaddr.Multiaddr
|
||||
genesisTipset *types.TipSet
|
||||
targetTipset *types.TipSet
|
||||
headTipset *types.TipSet
|
||||
peerID peer.ID
|
||||
version api.Version
|
||||
api api.FullNode
|
||||
}
|
||||
|
||||
var consensusCheckCmd = &cli.Command{
|
||||
Name: "check",
|
||||
Usage: "verify if all nodes agree upon a common tipset for a given tipset height",
|
||||
Description: `Consensus check verifies that all nodes share a common tipset for a given
|
||||
height.
|
||||
|
||||
The height flag specifies a chain height to start a comparison from. There are two special
|
||||
arguments for this flag. All other expected values should be chain tipset heights.
|
||||
|
||||
@common - Use the maximum common chain height between all nodes
|
||||
@expected - Use the current time and the genesis timestamp to determine a height
|
||||
|
||||
Examples
|
||||
|
||||
Find the highest common tipset and look back 10 tipsets
|
||||
lotus-shed consensus check --height @common --lookback 10
|
||||
|
||||
Calculate the expected tipset height and look back 10 tipsets
|
||||
lotus-shed consensus check --height @expected --lookback 10
|
||||
|
||||
Check if nodes all share a common genesis
|
||||
lotus-shed consensus check --height 0
|
||||
|
||||
Check that all nodes agree upon the tipset for 1day post genesis
|
||||
lotus-shed consensus check --height 2880 --lookback 0
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "height",
|
||||
Value: "@common",
|
||||
Usage: "height of tipset to start check from",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "lookback",
|
||||
Value: int(build.MessageConfidence * 2),
|
||||
Usage: "number of tipsets behind to look back when comparing nodes",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
filePath := cctx.Args().First()
|
||||
|
||||
var input *bufio.Reader
|
||||
if cctx.Args().Len() == 0 {
|
||||
input = bufio.NewReader(os.Stdin)
|
||||
} else {
|
||||
var err error
|
||||
inputFile, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer inputFile.Close() //nolint:errcheck
|
||||
input = bufio.NewReader(inputFile)
|
||||
}
|
||||
|
||||
var nodes []*consensusItem
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
for {
|
||||
strma, errR := input.ReadString('\n')
|
||||
strma = strings.TrimSpace(strma)
|
||||
|
||||
if len(strma) == 0 {
|
||||
if errR == io.EOF {
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
apima, err := multiaddr.NewMultiaddr(strma)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ainfo := lcli.APIInfo{Addr: apima}
|
||||
addr, err := ainfo.DialArgs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
api, closer, err := client.NewFullNodeRPC(cctx.Context, addr, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
peerID, err := api.ID(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
version, err := api.Version(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genesisTipset, err := api.ChainGetGenesis(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headTipset, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodes = append(nodes, &consensusItem{
|
||||
genesisTipset: genesisTipset,
|
||||
headTipset: headTipset,
|
||||
multiaddr: apima,
|
||||
api: api,
|
||||
peerID: peerID,
|
||||
version: version,
|
||||
})
|
||||
|
||||
if errR != nil && errR != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
if errR == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(nodes) == 0 {
|
||||
return fmt.Errorf("no nodes")
|
||||
}
|
||||
|
||||
genesisBuckets := make(map[types.TipSetKey][]*consensusItem)
|
||||
for _, node := range nodes {
|
||||
genesisBuckets[node.genesisTipset.Key()] = append(genesisBuckets[node.genesisTipset.Key()], node)
|
||||
|
||||
}
|
||||
|
||||
if len(genesisBuckets) != 1 {
|
||||
for _, nodes := range genesisBuckets {
|
||||
for _, node := range nodes {
|
||||
log.Errorw(
|
||||
"genesis do not match",
|
||||
"genesis_tipset", node.genesisTipset.Key(),
|
||||
"peer_id", node.peerID,
|
||||
"version", node.version,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("genesis does not match between all nodes")
|
||||
}
|
||||
|
||||
target := abi.ChainEpoch(0)
|
||||
|
||||
switch cctx.String("height") {
|
||||
case "@common":
|
||||
minTipset := nodes[0].headTipset
|
||||
for _, node := range nodes {
|
||||
if node.headTipset.Height() < minTipset.Height() {
|
||||
minTipset = node.headTipset
|
||||
}
|
||||
}
|
||||
|
||||
target = minTipset.Height()
|
||||
case "@expected":
|
||||
tnow := uint64(time.Now().Unix())
|
||||
tgen := nodes[0].genesisTipset.MinTimestamp()
|
||||
|
||||
target = abi.ChainEpoch((tnow - tgen) / build.BlockDelaySecs)
|
||||
default:
|
||||
h, err := strconv.Atoi(strings.TrimSpace(cctx.String("height")))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse string: %s", cctx.String("height"))
|
||||
}
|
||||
|
||||
target = abi.ChainEpoch(h)
|
||||
}
|
||||
|
||||
lookback := abi.ChainEpoch(cctx.Int("lookback"))
|
||||
if lookback > target {
|
||||
target = abi.ChainEpoch(0)
|
||||
} else {
|
||||
target = target - lookback
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
targetTipset, err := node.api.ChainGetTipSetByHeight(ctx, target, types.EmptyTSK)
|
||||
if err != nil {
|
||||
log.Errorw("error checking target", "err", err)
|
||||
node.targetTipset = nil
|
||||
} else {
|
||||
node.targetTipset = targetTipset
|
||||
}
|
||||
|
||||
}
|
||||
for _, node := range nodes {
|
||||
log.Debugw(
|
||||
"node info",
|
||||
"peer_id", node.peerID,
|
||||
"version", node.version,
|
||||
"genesis_tipset", node.genesisTipset.Key(),
|
||||
"head_tipset", node.headTipset.Key(),
|
||||
"target_tipset", node.targetTipset.Key(),
|
||||
)
|
||||
}
|
||||
|
||||
targetBuckets := make(map[types.TipSetKey][]*consensusItem)
|
||||
for _, node := range nodes {
|
||||
if node.targetTipset == nil {
|
||||
targetBuckets[types.EmptyTSK] = append(targetBuckets[types.EmptyTSK], node)
|
||||
continue
|
||||
}
|
||||
|
||||
targetBuckets[node.targetTipset.Key()] = append(targetBuckets[node.targetTipset.Key()], node)
|
||||
}
|
||||
|
||||
if nodes, ok := targetBuckets[types.EmptyTSK]; ok {
|
||||
for _, node := range nodes {
|
||||
log.Errorw(
|
||||
"targeted tipset not found",
|
||||
"peer_id", node.peerID,
|
||||
"version", node.version,
|
||||
"genesis_tipset", node.genesisTipset.Key(),
|
||||
"head_tipset", node.headTipset.Key(),
|
||||
"target_tipset", node.targetTipset.Key(),
|
||||
)
|
||||
}
|
||||
|
||||
return fmt.Errorf("targeted tipset not found")
|
||||
}
|
||||
|
||||
if len(targetBuckets) != 1 {
|
||||
for _, nodes := range targetBuckets {
|
||||
for _, node := range nodes {
|
||||
log.Errorw(
|
||||
"targeted tipset not found",
|
||||
"peer_id", node.peerID,
|
||||
"version", node.version,
|
||||
"genesis_tipset", node.genesisTipset.Key(),
|
||||
"head_tipset", node.headTipset.Key(),
|
||||
"target_tipset", node.targetTipset.Key(),
|
||||
)
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("nodes not in consensus at tipset height %d", target)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
@ -35,6 +35,7 @@ func main() {
|
||||
mathCmd,
|
||||
mpoolStatsCmd,
|
||||
exportChainCmd,
|
||||
consensusCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
@ -49,6 +50,13 @@ func main() {
|
||||
Hidden: true,
|
||||
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Value: "info",
|
||||
},
|
||||
},
|
||||
Before: func(cctx *cli.Context) error {
|
||||
return logging.SetLogLevel("lotus-shed", cctx.String("log-level"))
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,10 @@ var runCmd = &cli.Command{
|
||||
sigChan := make(chan os.Signal, 2)
|
||||
go func() {
|
||||
select {
|
||||
case <-sigChan:
|
||||
case sig := <-sigChan:
|
||||
log.Warnw("received shutdown", "signal", sig)
|
||||
case <-shutdownChan:
|
||||
log.Warn("received shutdown")
|
||||
}
|
||||
|
||||
log.Warn("Shutting down...")
|
||||
|
@ -18,7 +18,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
|
||||
)
|
||||
|
||||
var sectorsCmd = &cli.Command{
|
||||
@ -137,6 +139,12 @@ var sectorsStatusCmd = &cli.Command{
|
||||
var sectorsListCmd = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List sectors",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "show-removed",
|
||||
Usage: "show removed sectors",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
@ -193,19 +201,21 @@ var sectorsListCmd = &cli.Command{
|
||||
continue
|
||||
}
|
||||
|
||||
_, inSSet := commitedIDs[s]
|
||||
_, inASet := activeIDs[s]
|
||||
if cctx.Bool("show-removed") || st.State != api.SectorState(sealing.Removed) {
|
||||
_, inSSet := commitedIDs[s]
|
||||
_, inASet := activeIDs[s]
|
||||
|
||||
fmt.Fprintf(w, "%d: %s\tsSet: %s\tactive: %s\ttktH: %d\tseedH: %d\tdeals: %v\t toUpgrade:%t\n",
|
||||
s,
|
||||
st.State,
|
||||
yesno(inSSet),
|
||||
yesno(inASet),
|
||||
st.Ticket.Epoch,
|
||||
st.Seed.Epoch,
|
||||
st.Deals,
|
||||
st.ToUpgrade,
|
||||
)
|
||||
_, _ = fmt.Fprintf(w, "%d: %s\tsSet: %s\tactive: %s\ttktH: %d\tseedH: %d\tdeals: %v\t toUpgrade:%t\n",
|
||||
s,
|
||||
st.State,
|
||||
yesno(inSSet),
|
||||
yesno(inASet),
|
||||
st.Ticket.Epoch,
|
||||
st.Seed.Epoch,
|
||||
st.Deals,
|
||||
st.ToUpgrade,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return w.Flush()
|
||||
@ -421,6 +431,10 @@ var sectorsUpdateCmd = &cli.Command{
|
||||
return xerrors.Errorf("could not parse sector number: %w", err)
|
||||
}
|
||||
|
||||
if _, ok := sealing.ExistSectorStateList[sealing.SectorState(cctx.Args().Get(1))]; !ok {
|
||||
return xerrors.Errorf("Not existing sector state")
|
||||
}
|
||||
|
||||
return nodeApi.SectorsUpdate(ctx, abi.SectorNumber(id), api.SectorState(cctx.Args().Get(1)))
|
||||
},
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ var storageFindCmd = &cli.Command{
|
||||
}
|
||||
|
||||
fmt.Printf("In %s (%s)\n", info.id, types[:len(types)-2])
|
||||
fmt.Printf("\tSealing: %t; Storage: %t\n", info.store.CanSeal, info.store.CanSeal)
|
||||
fmt.Printf("\tSealing: %t; Storage: %t\n", info.store.CanSeal, info.store.CanStore)
|
||||
if localPath, ok := local[info.id]; ok {
|
||||
fmt.Printf("\tLocal (%s)\n", localPath)
|
||||
} else {
|
||||
|
@ -66,8 +66,10 @@ func serveRPC(a api.FullNode, stop node.StopFunc, addr multiaddr.Multiaddr, shut
|
||||
shutdownDone := make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-sigCh:
|
||||
case sig := <-sigCh:
|
||||
log.Warnw("received shutdown", "signal", sig)
|
||||
case <-shutdownCh:
|
||||
log.Warn("received shutdown")
|
||||
}
|
||||
|
||||
log.Warn("Shutting down...")
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/runtime"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
typegen "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
//go:generate go run ./gen
|
||||
@ -31,10 +29,14 @@ type Actor struct{}
|
||||
type CallerValidationBranch int64
|
||||
|
||||
const (
|
||||
// CallerValidationBranchNone causes no caller validation to take place.
|
||||
CallerValidationBranchNone CallerValidationBranch = iota
|
||||
// CallerValidationBranchTwice causes Runtime.ValidateImmediateCallerAcceptAny to be called twice.
|
||||
CallerValidationBranchTwice
|
||||
CallerValidationBranchAddrNilSet
|
||||
CallerValidationBranchTypeNilSet
|
||||
// CallerValidationBranchIsAddress causes caller validation against CallerValidationArgs.Addrs.
|
||||
CallerValidationBranchIsAddress
|
||||
// CallerValidationBranchIsType causes caller validation against CallerValidationArgs.Types.
|
||||
CallerValidationBranchIsType
|
||||
)
|
||||
|
||||
// MutateStateBranch is an enum used to select the type of state mutation to attempt.
|
||||
@ -123,23 +125,29 @@ func (a Actor) Constructor(_ runtime.Runtime, _ *abi.EmptyValue) *abi.EmptyValue
|
||||
panic("constructor should not be called; the Chaos actor is a singleton actor")
|
||||
}
|
||||
|
||||
// CallerValidationArgs are the arguments to Actor.CallerValidation.
|
||||
type CallerValidationArgs struct {
|
||||
Branch CallerValidationBranch
|
||||
Addrs []address.Address
|
||||
Types []cid.Cid
|
||||
}
|
||||
|
||||
// CallerValidation violates VM call validation constraints.
|
||||
//
|
||||
// CallerValidationBranchNone performs no validation.
|
||||
// CallerValidationBranchTwice validates twice.
|
||||
// CallerValidationBranchAddrNilSet validates against an empty caller
|
||||
// address set.
|
||||
// CallerValidationBranchTypeNilSet validates against an empty caller type set.
|
||||
func (a Actor) CallerValidation(rt runtime.Runtime, branch *typegen.CborInt) *abi.EmptyValue {
|
||||
switch CallerValidationBranch(*branch) {
|
||||
// CallerValidationBranchIsAddress validates caller against CallerValidationArgs.Addrs.
|
||||
// CallerValidationBranchIsType validates caller against CallerValidationArgs.Types.
|
||||
func (a Actor) CallerValidation(rt runtime.Runtime, args *CallerValidationArgs) *abi.EmptyValue {
|
||||
switch args.Branch {
|
||||
case CallerValidationBranchNone:
|
||||
case CallerValidationBranchTwice:
|
||||
rt.ValidateImmediateCallerAcceptAny()
|
||||
rt.ValidateImmediateCallerAcceptAny()
|
||||
case CallerValidationBranchAddrNilSet:
|
||||
rt.ValidateImmediateCallerIs()
|
||||
case CallerValidationBranchTypeNilSet:
|
||||
rt.ValidateImmediateCallerType()
|
||||
case CallerValidationBranchIsAddress:
|
||||
rt.ValidateImmediateCallerIs(args.Addrs...)
|
||||
case CallerValidationBranchIsType:
|
||||
rt.ValidateImmediateCallerType(args.Types...)
|
||||
default:
|
||||
panic("invalid branch passed to CallerValidation")
|
||||
}
|
||||
|
@ -4,11 +4,13 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/support/mock"
|
||||
atesting "github.com/filecoin-project/specs-actors/support/testing"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
func TestSingleton(t *testing.T) {
|
||||
@ -25,6 +27,86 @@ func TestSingleton(t *testing.T) {
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestCallerValidationNone(t *testing.T) {
|
||||
receiver := atesting.NewIDAddr(t, 100)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
||||
rt := builder.Build(t)
|
||||
var a Actor
|
||||
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{Branch: CallerValidationBranchNone})
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestCallerValidationIs(t *testing.T) {
|
||||
caller := atesting.NewIDAddr(t, 100)
|
||||
receiver := atesting.NewIDAddr(t, 101)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
||||
rt := builder.Build(t)
|
||||
rt.SetCaller(caller, builtin.AccountActorCodeID)
|
||||
var a Actor
|
||||
|
||||
caddrs := []address.Address{atesting.NewIDAddr(t, 101)}
|
||||
|
||||
rt.ExpectValidateCallerAddr(caddrs...)
|
||||
// FIXME: https://github.com/filecoin-project/specs-actors/pull/1155
|
||||
rt.ExpectAbort(exitcode.ErrForbidden, func() {
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{
|
||||
Branch: CallerValidationBranchIsAddress,
|
||||
Addrs: caddrs,
|
||||
})
|
||||
})
|
||||
rt.Verify()
|
||||
|
||||
rt.ExpectValidateCallerAddr(caller)
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{
|
||||
Branch: CallerValidationBranchIsAddress,
|
||||
Addrs: []address.Address{caller},
|
||||
})
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestCallerValidationType(t *testing.T) {
|
||||
caller := atesting.NewIDAddr(t, 100)
|
||||
receiver := atesting.NewIDAddr(t, 101)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
||||
rt := builder.Build(t)
|
||||
rt.SetCaller(caller, builtin.AccountActorCodeID)
|
||||
var a Actor
|
||||
|
||||
rt.ExpectValidateCallerType(builtin.CronActorCodeID)
|
||||
// FIXME: https://github.com/filecoin-project/specs-actors/pull/1155
|
||||
rt.ExpectAbort(exitcode.ErrForbidden, func() {
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{
|
||||
Branch: CallerValidationBranchIsType,
|
||||
Types: []cid.Cid{builtin.CronActorCodeID},
|
||||
})
|
||||
})
|
||||
rt.Verify()
|
||||
|
||||
rt.ExpectValidateCallerType(builtin.AccountActorCodeID)
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{
|
||||
Branch: CallerValidationBranchIsType,
|
||||
Types: []cid.Cid{builtin.AccountActorCodeID},
|
||||
})
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestCallerValidationInvalidBranch(t *testing.T) {
|
||||
receiver := atesting.NewIDAddr(t, 100)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
||||
rt := builder.Build(t)
|
||||
var a Actor
|
||||
|
||||
rt.ExpectAssertionFailure("invalid branch passed to CallerValidation", func() {
|
||||
rt.Call(a.CallerValidation, &CallerValidationArgs{Branch: -1})
|
||||
})
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestDeleteActor(t *testing.T) {
|
||||
receiver := atesting.NewIDAddr(t, 100)
|
||||
beneficiary := atesting.NewIDAddr(t, 101)
|
||||
@ -118,6 +200,20 @@ func TestMutateStateReadonly(t *testing.T) {
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestMutateStateInvalidBranch(t *testing.T) {
|
||||
receiver := atesting.NewIDAddr(t, 100)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
||||
rt := builder.Build(t)
|
||||
var a Actor
|
||||
|
||||
rt.ExpectValidateCallerAny()
|
||||
rt.ExpectAssertionFailure("unknown mutation type", func() {
|
||||
rt.Call(a.MutateState, &MutateStateArgs{Branch: -1})
|
||||
})
|
||||
rt.Verify()
|
||||
}
|
||||
|
||||
func TestAbortWith(t *testing.T) {
|
||||
receiver := atesting.NewIDAddr(t, 100)
|
||||
builder := mock.NewBuilder(context.Background(), receiver)
|
||||
|
@ -6,8 +6,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
address "github.com/filecoin-project/go-address"
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
exitcode "github.com/filecoin-project/go-state-types/exitcode"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
@ -115,6 +117,163 @@ func (t *State) UnmarshalCBOR(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufCallerValidationArgs = []byte{131}
|
||||
|
||||
func (t *CallerValidationArgs) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(lengthBufCallerValidationArgs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scratch := make([]byte, 9)
|
||||
|
||||
// t.Branch (chaos.CallerValidationBranch) (int64)
|
||||
if t.Branch >= 0 {
|
||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Branch)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajNegativeInt, uint64(-t.Branch-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Addrs ([]address.Address) (slice)
|
||||
if len(t.Addrs) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Addrs was too long")
|
||||
}
|
||||
|
||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Addrs))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Addrs {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Types ([]cid.Cid) (slice)
|
||||
if len(t.Types) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Types was too long")
|
||||
}
|
||||
|
||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajArray, uint64(len(t.Types))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Types {
|
||||
if err := cbg.WriteCidBuf(scratch, w, v); err != nil {
|
||||
return xerrors.Errorf("failed writing cid field t.Types: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *CallerValidationArgs) UnmarshalCBOR(r io.Reader) error {
|
||||
*t = CallerValidationArgs{}
|
||||
|
||||
br := cbg.GetPeeker(r)
|
||||
scratch := make([]byte, 8)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Branch (chaos.CallerValidationBranch) (int64)
|
||||
{
|
||||
maj, extra, err := cbg.CborReadHeaderBuf(br, scratch)
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.Branch = CallerValidationBranch(extraI)
|
||||
}
|
||||
// t.Addrs ([]address.Address) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Addrs: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Addrs = make([]address.Address, extra)
|
||||
}
|
||||
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v address.Address
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Addrs[i] = v
|
||||
}
|
||||
|
||||
// t.Types ([]cid.Cid) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeaderBuf(br, scratch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Types: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Types = make([]cid.Cid, extra)
|
||||
}
|
||||
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
c, err := cbg.ReadCid(br)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("reading cid field t.Types failed: %w", err)
|
||||
}
|
||||
t.Types[i] = c
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufCreateActorArgs = []byte{132}
|
||||
|
||||
func (t *CreateActorArgs) MarshalCBOR(w io.Writer) error {
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
func main() {
|
||||
if err := gen.WriteTupleEncodersToFile("./cbor_gen.go", "chaos",
|
||||
chaos.State{},
|
||||
chaos.CallerValidationArgs{},
|
||||
chaos.CreateActorArgs{},
|
||||
chaos.ResolveAddressResponse{},
|
||||
chaos.SendArgs{},
|
||||
|
32
extern/storage-sealing/sector_state.go
vendored
32
extern/storage-sealing/sector_state.go
vendored
@ -2,6 +2,38 @@ package sealing
|
||||
|
||||
type SectorState string
|
||||
|
||||
var ExistSectorStateList = map[SectorState]struct{}{
|
||||
Empty: {},
|
||||
WaitDeals: {},
|
||||
Packing: {},
|
||||
PreCommit1: {},
|
||||
PreCommit2: {},
|
||||
PreCommitting: {},
|
||||
PreCommitWait: {},
|
||||
WaitSeed: {},
|
||||
Committing: {},
|
||||
SubmitCommit: {},
|
||||
CommitWait: {},
|
||||
FinalizeSector: {},
|
||||
Proving: {},
|
||||
FailedUnrecoverable: {},
|
||||
SealPreCommit1Failed: {},
|
||||
SealPreCommit2Failed: {},
|
||||
PreCommitFailed: {},
|
||||
ComputeProofFailed: {},
|
||||
CommitFailed: {},
|
||||
PackingFailed: {},
|
||||
FinalizeFailed: {},
|
||||
DealsExpired: {},
|
||||
RecoverDealIDs: {},
|
||||
Faulty: {},
|
||||
FaultReported: {},
|
||||
FaultedFinal: {},
|
||||
Removing: {},
|
||||
RemoveFailed: {},
|
||||
Removed: {},
|
||||
}
|
||||
|
||||
const (
|
||||
UndefinedSectorState SectorState = ""
|
||||
|
||||
|
2
extern/test-vectors
vendored
2
extern/test-vectors
vendored
@ -1 +1 @@
|
||||
Subproject commit 7d3becbeb5b932baed419c43390595b5e5cece12
|
||||
Subproject commit 6bea015edddde116001a4251dce3c4a9966c25d9
|
@ -2,7 +2,7 @@
|
||||
Description=Lotus Miner
|
||||
After=network.target
|
||||
After=lotus-daemon.service
|
||||
Requires=lotus-daemon.service
|
||||
Wants=lotus-daemon.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/lotus-miner run
|
||||
|
Loading…
Reference in New Issue
Block a user