Merge branch 'master' into asr/merge-release-into-master
This commit is contained in:
commit
65ac5669a9
@ -417,71 +417,6 @@ jobs:
|
||||
golangci-lint run -v --timeout 10m \
|
||||
--concurrency 4 << parameters.args >>
|
||||
|
||||
publish:
|
||||
description: publish binary artifacts
|
||||
executor: ubuntu
|
||||
parameters:
|
||||
linux:
|
||||
default: false
|
||||
description: publish linux binaries?
|
||||
type: boolean
|
||||
appimage:
|
||||
default: false
|
||||
description: publish appimage binaries?
|
||||
type: boolean
|
||||
steps:
|
||||
- run:
|
||||
name: Install git jq curl
|
||||
command: apt update && apt install -y git jq curl sudo
|
||||
- checkout
|
||||
- git_fetch_all_tags
|
||||
- install_ipfs
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- when:
|
||||
condition: << parameters.linux >>
|
||||
steps:
|
||||
- run: ./scripts/build-arch-bundle.sh linux
|
||||
- run: ./scripts/publish-arch-release.sh linux
|
||||
- when:
|
||||
condition: << parameters.appimage >>
|
||||
steps:
|
||||
- run: ./scripts/build-appimage-bundle.sh
|
||||
- run: ./scripts/publish-arch-release.sh appimage
|
||||
|
||||
publish-snapcraft:
|
||||
description: build and push snapcraft
|
||||
machine:
|
||||
image: ubuntu-2004:202104-01
|
||||
resource_class: 2xlarge
|
||||
parameters:
|
||||
channel:
|
||||
type: string
|
||||
default: "edge"
|
||||
description: snapcraft channel
|
||||
snap-name:
|
||||
type: string
|
||||
default: 'lotus-filecoin'
|
||||
description: name of snap in snap store
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install snapcraft
|
||||
command: sudo snap install snapcraft --classic
|
||||
- run:
|
||||
name: Build << parameters.snap-name >> snap
|
||||
command: |
|
||||
if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then
|
||||
cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml
|
||||
mv edited-snapcraft.yaml snap/snapcraft.yaml
|
||||
fi
|
||||
|
||||
snapcraft --use-lxd --debug
|
||||
- run:
|
||||
name: Publish snap to << parameters.channel >> channel
|
||||
shell: /bin/bash -o pipefail
|
||||
command: |
|
||||
snapcraft upload *.snap --release << parameters.channel >>
|
||||
build-docker:
|
||||
description: >
|
||||
Publish to Dockerhub
|
||||
@ -737,9 +672,10 @@ workflows:
|
||||
target: "./itests/eth_balance_test.go"
|
||||
- test:
|
||||
name: test-itest-eth_block_hash
|
||||
requires:
|
||||
- build
|
||||
suite: itest-eth_block_hash
|
||||
target: "./itests/eth_block_hash_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_deploy
|
||||
requires:
|
||||
@ -754,9 +690,10 @@ workflows:
|
||||
target: "./itests/eth_filter_test.go"
|
||||
- test:
|
||||
name: test-itest-eth_hash_lookup
|
||||
requires:
|
||||
- build
|
||||
suite: itest-eth_hash_lookup
|
||||
target: "./itests/eth_hash_lookup_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_transactions
|
||||
requires:
|
||||
|
@ -417,71 +417,6 @@ jobs:
|
||||
golangci-lint run -v --timeout 10m \
|
||||
--concurrency 4 << parameters.args >>
|
||||
|
||||
publish:
|
||||
description: publish binary artifacts
|
||||
executor: ubuntu
|
||||
parameters:
|
||||
linux:
|
||||
default: false
|
||||
description: publish linux binaries?
|
||||
type: boolean
|
||||
appimage:
|
||||
default: false
|
||||
description: publish appimage binaries?
|
||||
type: boolean
|
||||
steps:
|
||||
- run:
|
||||
name: Install git jq curl
|
||||
command: apt update && apt install -y git jq curl sudo
|
||||
- checkout
|
||||
- git_fetch_all_tags
|
||||
- install_ipfs
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- when:
|
||||
condition: << parameters.linux >>
|
||||
steps:
|
||||
- run: ./scripts/build-arch-bundle.sh linux
|
||||
- run: ./scripts/publish-arch-release.sh linux
|
||||
- when:
|
||||
condition: << parameters.appimage >>
|
||||
steps:
|
||||
- run: ./scripts/build-appimage-bundle.sh
|
||||
- run: ./scripts/publish-arch-release.sh appimage
|
||||
|
||||
publish-snapcraft:
|
||||
description: build and push snapcraft
|
||||
machine:
|
||||
image: ubuntu-2004:202104-01
|
||||
resource_class: 2xlarge
|
||||
parameters:
|
||||
channel:
|
||||
type: string
|
||||
default: "edge"
|
||||
description: snapcraft channel
|
||||
snap-name:
|
||||
type: string
|
||||
default: 'lotus-filecoin'
|
||||
description: name of snap in snap store
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install snapcraft
|
||||
command: sudo snap install snapcraft --classic
|
||||
- run:
|
||||
name: Build << parameters.snap-name >> snap
|
||||
command: |
|
||||
if [ "<< parameters.snap-name >>" != 'lotus-filecoin' ]; then
|
||||
cat snap/snapcraft.yaml | sed 's/lotus-filecoin/lotus/' > edited-snapcraft.yaml
|
||||
mv edited-snapcraft.yaml snap/snapcraft.yaml
|
||||
fi
|
||||
|
||||
snapcraft --use-lxd --debug
|
||||
- run:
|
||||
name: Publish snap to << parameters.channel >> channel
|
||||
shell: /bin/bash -o pipefail
|
||||
command: |
|
||||
snapcraft upload *.snap --release << parameters.channel >>
|
||||
build-docker:
|
||||
description: >
|
||||
Publish to Dockerhub
|
||||
|
10
cli/state.go
10
cli/state.go
@ -252,10 +252,16 @@ func ParseTipSetString(ts string) ([]cid.Cid, error) {
|
||||
return cids, nil
|
||||
}
|
||||
|
||||
type TipSetResolver interface {
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainGetTipSetByHeight(context.Context, abi.ChainEpoch, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
|
||||
}
|
||||
|
||||
// LoadTipSet gets the tipset from the context, or the head from the API.
|
||||
//
|
||||
// It always gets the head from the API so commands use a consistent tipset even if time pases.
|
||||
func LoadTipSet(ctx context.Context, cctx *cli.Context, api v0api.FullNode) (*types.TipSet, error) {
|
||||
func LoadTipSet(ctx context.Context, cctx *cli.Context, api TipSetResolver) (*types.TipSet, error) {
|
||||
tss := cctx.String("tipset")
|
||||
if tss == "" {
|
||||
return api.ChainHead(ctx)
|
||||
@ -264,7 +270,7 @@ func LoadTipSet(ctx context.Context, cctx *cli.Context, api v0api.FullNode) (*ty
|
||||
return ParseTipSetRef(ctx, api, tss)
|
||||
}
|
||||
|
||||
func ParseTipSetRef(ctx context.Context, api v0api.FullNode, tss string) (*types.TipSet, error) {
|
||||
func ParseTipSetRef(ctx context.Context, api TipSetResolver, tss string) (*types.TipSet, error) {
|
||||
if tss[0] == '@' {
|
||||
if tss == "@head" {
|
||||
return api.ChainHead(ctx)
|
||||
|
@ -51,7 +51,6 @@ var sectorsCmd = &cli.Command{
|
||||
sectorPreCommitsCmd,
|
||||
sectorsCheckExpireCmd,
|
||||
sectorsExpiredCmd,
|
||||
sectorsRenewCmd,
|
||||
sectorsExtendCmd,
|
||||
sectorsTerminateCmd,
|
||||
sectorsRemoveCmd,
|
||||
@ -743,14 +742,14 @@ func ArrayToString(array []uint64) string {
|
||||
return strings.Join(sarray, ",")
|
||||
}
|
||||
|
||||
func getSectorsFromFile(filePath string) ([]uint64, error) {
|
||||
func getSectorsFromFile(filePath string) ([]abi.SectorNumber, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
sectors := make([]uint64, 0)
|
||||
sectors := make([]abi.SectorNumber, 0)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
@ -760,7 +759,7 @@ func getSectorsFromFile(filePath string) ([]uint64, error) {
|
||||
return nil, xerrors.Errorf("could not parse %s as sector id: %s", line, err)
|
||||
}
|
||||
|
||||
sectors = append(sectors, id)
|
||||
sectors = append(sectors, abi.SectorNumber(id))
|
||||
}
|
||||
|
||||
if err = file.Close(); err != nil {
|
||||
@ -770,9 +769,19 @@ func getSectorsFromFile(filePath string) ([]uint64, error) {
|
||||
return sectors, nil
|
||||
}
|
||||
|
||||
var sectorsRenewCmd = &cli.Command{
|
||||
Name: "renew",
|
||||
Usage: "Renew expiring sectors while not exceeding each sector's max life",
|
||||
func SectorNumsToBitfield(sectors []abi.SectorNumber) bitfield.BitField {
|
||||
var numbers []uint64
|
||||
for sector := range sectors {
|
||||
numbers = append(numbers, uint64(sector))
|
||||
}
|
||||
|
||||
return bitfield.NewFromSet(numbers)
|
||||
}
|
||||
|
||||
var sectorsExtendCmd = &cli.Command{
|
||||
Name: "extend",
|
||||
Usage: "Extend expiring sectors while not exceeding each sector's max life",
|
||||
ArgsUsage: "<sectorNumbers...(optional)>",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Int64Flag{
|
||||
Name: "from",
|
||||
@ -819,7 +828,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "pass this flag to really renew sectors, otherwise will only print out json representation of parameters",
|
||||
Usage: "pass this flag to really extend sectors, otherwise will only print out json representation of parameters",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
@ -896,8 +905,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
excludeSet := make(map[uint64]struct{})
|
||||
|
||||
excludeSet := make(map[abi.SectorNumber]struct{})
|
||||
if cctx.IsSet("exclude") {
|
||||
excludeSectors, err := getSectorsFromFile(cctx.String("exclude"))
|
||||
if err != nil {
|
||||
@ -909,29 +917,25 @@ var sectorsRenewCmd = &cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
var sis []*miner.SectorOnChainInfo
|
||||
|
||||
var sectors []abi.SectorNumber
|
||||
if cctx.Args().Present() {
|
||||
if cctx.IsSet("sector-file") {
|
||||
sectors, err := getSectorsFromFile(cctx.String("sector-file"))
|
||||
return xerrors.Errorf("sector-file specified along with command line params")
|
||||
}
|
||||
|
||||
for i, s := range cctx.Args().Slice() {
|
||||
id, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not parse sector %d: %w", i, err)
|
||||
}
|
||||
|
||||
sectors = append(sectors, abi.SectorNumber(id))
|
||||
}
|
||||
} else if cctx.IsSet("sector-file") {
|
||||
sectors, err = getSectorsFromFile(cctx.String("sector-file"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, id := range sectors {
|
||||
if _, exclude := excludeSet[id]; exclude {
|
||||
continue
|
||||
}
|
||||
|
||||
si, found := activeSectorsInfo[abi.SectorNumber(id)]
|
||||
if !found {
|
||||
return xerrors.Errorf("sector %d is not active", id)
|
||||
}
|
||||
if len(si.DealIDs) > 0 && cctx.Bool("only-cc") {
|
||||
continue
|
||||
}
|
||||
|
||||
sis = append(sis, si)
|
||||
}
|
||||
} else {
|
||||
from := currEpoch + 120
|
||||
to := currEpoch + 92160
|
||||
@ -945,19 +949,28 @@ var sectorsRenewCmd = &cli.Command{
|
||||
}
|
||||
|
||||
for _, si := range activeSet {
|
||||
if si.Expiration >= from && si.Expiration <= to {
|
||||
sectors = append(sectors, si.SectorNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sis []*miner.SectorOnChainInfo
|
||||
for _, id := range sectors {
|
||||
if _, exclude := excludeSet[id]; exclude {
|
||||
continue
|
||||
}
|
||||
|
||||
si, found := activeSectorsInfo[id]
|
||||
if !found {
|
||||
return xerrors.Errorf("sector %d is not active", id)
|
||||
}
|
||||
if len(si.DealIDs) > 0 && cctx.Bool("only-cc") {
|
||||
continue
|
||||
}
|
||||
|
||||
if si.Expiration >= from && si.Expiration <= to {
|
||||
if _, exclude := excludeSet[uint64(si.SectorNumber)]; !exclude {
|
||||
sis = append(sis, si)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extensions := map[lminer.SectorLocation]map[abi.ChainEpoch][]uint64{}
|
||||
|
||||
withinTolerance := func(a, b abi.ChainEpoch) bool {
|
||||
diff := a - b
|
||||
@ -968,6 +981,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
return diff <= abi.ChainEpoch(cctx.Int64("tolerance"))
|
||||
}
|
||||
|
||||
extensions := map[lminer.SectorLocation]map[abi.ChainEpoch][]abi.SectorNumber{}
|
||||
for _, si := range sis {
|
||||
extension := abi.ChainEpoch(cctx.Int64("extension"))
|
||||
newExp := si.Expiration + extension
|
||||
@ -997,21 +1011,21 @@ var sectorsRenewCmd = &cli.Command{
|
||||
|
||||
es, found := extensions[*l]
|
||||
if !found {
|
||||
ne := make(map[abi.ChainEpoch][]uint64)
|
||||
ne[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||
ne := make(map[abi.ChainEpoch][]abi.SectorNumber)
|
||||
ne[newExp] = []abi.SectorNumber{si.SectorNumber}
|
||||
extensions[*l] = ne
|
||||
} else {
|
||||
added := false
|
||||
for exp := range es {
|
||||
if withinTolerance(newExp, exp) {
|
||||
es[exp] = append(es[exp], uint64(si.SectorNumber))
|
||||
es[exp] = append(es[exp], si.SectorNumber)
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !added {
|
||||
es[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||
es[newExp] = []abi.SectorNumber{si.SectorNumber}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1051,7 +1065,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
p.Extensions = append(p.Extensions, miner.ExpirationExtension{
|
||||
Deadline: l.Deadline,
|
||||
Partition: l.Partition,
|
||||
Sectors: bitfield.NewFromSet(numbers),
|
||||
Sectors: SectorNumsToBitfield(numbers),
|
||||
NewExpiration: newExp,
|
||||
})
|
||||
}
|
||||
@ -1083,7 +1097,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
}
|
||||
scount += int(count)
|
||||
}
|
||||
fmt.Printf("Renewing %d sectors: ", scount)
|
||||
fmt.Printf("Extending %d sectors: ", scount)
|
||||
stotal += scount
|
||||
|
||||
if !cctx.Bool("really-do-it") {
|
||||
@ -1097,8 +1111,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println(string(data))
|
||||
fmt.Println("\n", string(data))
|
||||
continue
|
||||
}
|
||||
|
||||
@ -1121,252 +1134,7 @@ var sectorsRenewCmd = &cli.Command{
|
||||
fmt.Println(smsg.Cid())
|
||||
}
|
||||
|
||||
fmt.Printf("%d sectors renewed\n", stotal)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var sectorsExtendCmd = &cli.Command{
|
||||
Name: "extend",
|
||||
Usage: "Extend sector expiration",
|
||||
ArgsUsage: "<sectorNumbers...>",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Int64Flag{
|
||||
Name: "new-expiration",
|
||||
Usage: "new expiration epoch",
|
||||
Required: false,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "v1-sectors",
|
||||
Usage: "renews all v1 sectors up to the maximum possible lifetime",
|
||||
Required: false,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "tolerance",
|
||||
Value: 20160,
|
||||
Usage: "when extending v1 sectors, don't try to extend sectors by fewer than this number of epochs",
|
||||
Required: false,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "expiration-ignore",
|
||||
Value: 120,
|
||||
Usage: "when extending v1 sectors, skip sectors whose current expiration is less than <ignore> epochs from now",
|
||||
Required: false,
|
||||
},
|
||||
&cli.Int64Flag{
|
||||
Name: "expiration-cutoff",
|
||||
Usage: "when extending v1 sectors, skip sectors whose current expiration is more than <cutoff> epochs from now (infinity if unspecified)",
|
||||
Required: false,
|
||||
},
|
||||
&cli.StringFlag{},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
api, nCloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer nCloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := getActorAddress(ctx, cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var params []miner.ExtendSectorExpirationParams
|
||||
|
||||
if cctx.Bool("v1-sectors") {
|
||||
|
||||
head, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nv, err := api.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
extensions := map[lminer.SectorLocation]map[abi.ChainEpoch][]uint64{}
|
||||
|
||||
// are given durations within tolerance epochs
|
||||
withinTolerance := func(a, b abi.ChainEpoch) bool {
|
||||
diff := a - b
|
||||
if diff < 0 {
|
||||
diff = b - a
|
||||
}
|
||||
|
||||
return diff <= abi.ChainEpoch(cctx.Int64("tolerance"))
|
||||
}
|
||||
|
||||
sis, err := api.StateMinerActiveSectors(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner sector infos: %w", err)
|
||||
}
|
||||
|
||||
for _, si := range sis {
|
||||
if si.SealProof >= abi.RegisteredSealProof_StackedDrg2KiBV1_1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if si.Expiration < (head.Height() + abi.ChainEpoch(cctx.Int64("expiration-ignore"))) {
|
||||
continue
|
||||
}
|
||||
|
||||
if cctx.IsSet("expiration-cutoff") {
|
||||
if si.Expiration > (head.Height() + abi.ChainEpoch(cctx.Int64("expiration-cutoff"))) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
ml := policy.GetSectorMaxLifetime(si.SealProof, nv)
|
||||
// if the sector's missing less than "tolerance" of its maximum possible lifetime, don't bother extending it
|
||||
if withinTolerance(si.Expiration-si.Activation, ml) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Set the new expiration to 48 hours less than the theoretical maximum lifetime
|
||||
newExp := ml - (miner.WPoStProvingPeriod * 2) + si.Activation
|
||||
if withinTolerance(si.Expiration, newExp) || si.Expiration >= newExp {
|
||||
continue
|
||||
}
|
||||
|
||||
p, err := api.StateSectorPartition(ctx, maddr, si.SectorNumber, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting sector location for sector %d: %w", si.SectorNumber, err)
|
||||
}
|
||||
|
||||
if p == nil {
|
||||
return xerrors.Errorf("sector %d not found in any partition", si.SectorNumber)
|
||||
}
|
||||
|
||||
es, found := extensions[*p]
|
||||
if !found {
|
||||
ne := make(map[abi.ChainEpoch][]uint64)
|
||||
ne[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||
extensions[*p] = ne
|
||||
} else {
|
||||
added := false
|
||||
for exp := range es {
|
||||
if withinTolerance(exp, newExp) && newExp >= exp && exp > si.Expiration {
|
||||
es[exp] = append(es[exp], uint64(si.SectorNumber))
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !added {
|
||||
es[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p := miner.ExtendSectorExpirationParams{}
|
||||
scount := 0
|
||||
|
||||
for l, exts := range extensions {
|
||||
for newExp, numbers := range exts {
|
||||
scount += len(numbers)
|
||||
addressedMax, err := policy.GetAddressedSectorsMax(nv)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get addressed sectors max")
|
||||
}
|
||||
declMax, err := policy.GetDeclarationsMax(nv)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get declarations max")
|
||||
}
|
||||
if scount > addressedMax || len(p.Extensions) == declMax {
|
||||
params = append(params, p)
|
||||
p = miner.ExtendSectorExpirationParams{}
|
||||
scount = len(numbers)
|
||||
}
|
||||
|
||||
p.Extensions = append(p.Extensions, miner.ExpirationExtension{
|
||||
Deadline: l.Deadline,
|
||||
Partition: l.Partition,
|
||||
Sectors: bitfield.NewFromSet(numbers),
|
||||
NewExpiration: newExp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// if we have any sectors, then one last append is needed here
|
||||
if scount != 0 {
|
||||
params = append(params, p)
|
||||
}
|
||||
|
||||
} else {
|
||||
if !cctx.Args().Present() || !cctx.IsSet("new-expiration") {
|
||||
return xerrors.Errorf("must pass at least one sector number and new expiration")
|
||||
}
|
||||
sectors := map[lminer.SectorLocation][]uint64{}
|
||||
|
||||
for i, s := range cctx.Args().Slice() {
|
||||
id, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not parse sector %d: %w", i, err)
|
||||
}
|
||||
|
||||
p, err := api.StateSectorPartition(ctx, maddr, abi.SectorNumber(id), types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting sector location for sector %d: %w", id, err)
|
||||
}
|
||||
|
||||
if p == nil {
|
||||
return xerrors.Errorf("sector %d not found in any partition", id)
|
||||
}
|
||||
|
||||
sectors[*p] = append(sectors[*p], id)
|
||||
}
|
||||
|
||||
p := miner.ExtendSectorExpirationParams{}
|
||||
for l, numbers := range sectors {
|
||||
|
||||
// TODO: Dedup with above loop
|
||||
p.Extensions = append(p.Extensions, miner.ExpirationExtension{
|
||||
Deadline: l.Deadline,
|
||||
Partition: l.Partition,
|
||||
Sectors: bitfield.NewFromSet(numbers),
|
||||
NewExpiration: abi.ChainEpoch(cctx.Int64("new-expiration")),
|
||||
})
|
||||
}
|
||||
|
||||
params = append(params, p)
|
||||
}
|
||||
|
||||
if len(params) == 0 {
|
||||
fmt.Println("nothing to extend")
|
||||
return nil
|
||||
}
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner info: %w", err)
|
||||
}
|
||||
|
||||
for i := range params {
|
||||
sp, aerr := actors.SerializeParams(¶ms[i])
|
||||
if aerr != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: mi.Worker,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.ExtendSectorExpiration,
|
||||
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push message: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println(smsg.Cid())
|
||||
}
|
||||
fmt.Printf("%d sectors extended\n", stotal)
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -14,6 +15,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
||||
|
||||
@ -35,6 +37,8 @@ var actorCmd = &cli.Command{
|
||||
actorProposeChangeWorker,
|
||||
actorConfirmChangeWorker,
|
||||
actorGetMethodNum,
|
||||
actorProposeChangeBeneficiary,
|
||||
actorConfirmChangeBeneficiary,
|
||||
},
|
||||
}
|
||||
|
||||
@ -831,3 +835,255 @@ var actorGetMethodNum = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var actorProposeChangeBeneficiary = &cli.Command{
|
||||
Name: "propose-change-beneficiary",
|
||||
Usage: "Propose a beneficiary address change",
|
||||
ArgsUsage: "[beneficiaryAddress quota expiration minerID]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "Actually send transaction performing the action",
|
||||
Value: false,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "overwrite-pending-change",
|
||||
Usage: "Overwrite the current beneficiary change proposal",
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.NArg() != 4 {
|
||||
return lcli.IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting fullnode api: %w", err)
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
na, err := address.NewFromString(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing beneficiary address: %w", err)
|
||||
}
|
||||
|
||||
newAddr, err := api.StateLookupID(ctx, na, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("looking up new beneficiary address: %w", err)
|
||||
}
|
||||
|
||||
quota, err := types.ParseFIL(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing quota: %w", err)
|
||||
}
|
||||
|
||||
expiration, err := strconv.ParseInt(cctx.Args().Get(2), 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing expiration: %w", err)
|
||||
}
|
||||
|
||||
maddr, err := address.NewFromString(cctx.Args().Get(3))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner address: %w", err)
|
||||
}
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner info: %w", err)
|
||||
}
|
||||
|
||||
if mi.Beneficiary == mi.Owner && newAddr == mi.Owner {
|
||||
return fmt.Errorf("beneficiary %s already set to owner address", mi.Beneficiary)
|
||||
}
|
||||
|
||||
if mi.PendingBeneficiaryTerm != nil {
|
||||
fmt.Println("WARNING: replacing Pending Beneficiary Term of:")
|
||||
fmt.Println("Beneficiary: ", mi.PendingBeneficiaryTerm.NewBeneficiary)
|
||||
fmt.Println("Quota:", mi.PendingBeneficiaryTerm.NewQuota)
|
||||
fmt.Println("Expiration Epoch:", mi.PendingBeneficiaryTerm.NewExpiration)
|
||||
|
||||
if !cctx.Bool("overwrite-pending-change") {
|
||||
return fmt.Errorf("must pass --overwrite-pending-change to replace current pending beneficiary change. Please review CAREFULLY")
|
||||
}
|
||||
}
|
||||
|
||||
if !cctx.Bool("really-do-it") {
|
||||
fmt.Println("Pass --really-do-it to actually execute this action. Review what you're about to approve CAREFULLY please")
|
||||
return nil
|
||||
}
|
||||
|
||||
params := &miner.ChangeBeneficiaryParams{
|
||||
NewBeneficiary: newAddr,
|
||||
NewQuota: abi.TokenAmount(quota),
|
||||
NewExpiration: abi.ChainEpoch(expiration),
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(params)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: mi.Owner,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.ChangeBeneficiary,
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Propose Message CID:", smsg.Cid())
|
||||
|
||||
// wait for it to get mined into a block
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("waiting for message to be included in block: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode.IsError() {
|
||||
return fmt.Errorf("propose beneficiary change failed")
|
||||
}
|
||||
|
||||
updatedMinerInfo, err := api.StateMinerInfo(ctx, maddr, wait.TipSet)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner info: %w", err)
|
||||
}
|
||||
|
||||
if updatedMinerInfo.PendingBeneficiaryTerm == nil && updatedMinerInfo.Beneficiary == newAddr {
|
||||
fmt.Println("Beneficiary address successfully changed")
|
||||
} else {
|
||||
fmt.Println("Beneficiary address change awaiting additional confirmations")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var actorConfirmChangeBeneficiary = &cli.Command{
|
||||
Name: "confirm-change-beneficiary",
|
||||
Usage: "Confirm a beneficiary address change",
|
||||
ArgsUsage: "[minerAddress]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "Actually send transaction performing the action",
|
||||
Value: false,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "existing-beneficiary",
|
||||
Usage: "send confirmation from the existing beneficiary address",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "new-beneficiary",
|
||||
Usage: "send confirmation from the new beneficiary address",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.NArg() != 1 {
|
||||
return lcli.IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
api, acloser, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting fullnode api: %w", err)
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := address.NewFromString(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing beneficiary address: %w", err)
|
||||
}
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner info: %w", err)
|
||||
}
|
||||
|
||||
if mi.PendingBeneficiaryTerm == nil {
|
||||
return fmt.Errorf("no pending beneficiary term found for miner %s", maddr)
|
||||
}
|
||||
|
||||
if (cctx.IsSet("existing-beneficiary") && cctx.IsSet("new-beneficiary")) || (!cctx.IsSet("existing-beneficiary") && !cctx.IsSet("new-beneficiary")) {
|
||||
return lcli.ShowHelp(cctx, fmt.Errorf("must pass exactly one of --existing-beneficiary or --new-beneficiary"))
|
||||
}
|
||||
|
||||
var fromAddr address.Address
|
||||
if cctx.IsSet("existing-beneficiary") {
|
||||
if mi.PendingBeneficiaryTerm.ApprovedByBeneficiary {
|
||||
return fmt.Errorf("beneficiary change already approved by current beneficiary")
|
||||
}
|
||||
fromAddr = mi.Beneficiary
|
||||
} else {
|
||||
if mi.PendingBeneficiaryTerm.ApprovedByNominee {
|
||||
return fmt.Errorf("beneficiary change already approved by new beneficiary")
|
||||
}
|
||||
fromAddr = mi.PendingBeneficiaryTerm.NewBeneficiary
|
||||
}
|
||||
|
||||
fmt.Println("Confirming Pending Beneficiary Term of:")
|
||||
fmt.Println("Beneficiary: ", mi.PendingBeneficiaryTerm.NewBeneficiary)
|
||||
fmt.Println("Quota:", mi.PendingBeneficiaryTerm.NewQuota)
|
||||
fmt.Println("Expiration Epoch:", mi.PendingBeneficiaryTerm.NewExpiration)
|
||||
|
||||
if !cctx.Bool("really-do-it") {
|
||||
fmt.Println("Pass --really-do-it to actually execute this action. Review what you're about to approve CAREFULLY please")
|
||||
return nil
|
||||
}
|
||||
|
||||
params := &miner.ChangeBeneficiaryParams{
|
||||
NewBeneficiary: mi.PendingBeneficiaryTerm.NewBeneficiary,
|
||||
NewQuota: mi.PendingBeneficiaryTerm.NewQuota,
|
||||
NewExpiration: mi.PendingBeneficiaryTerm.NewExpiration,
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(params)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||
From: fromAddr,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.ChangeBeneficiary,
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Confirm Message CID:", smsg.Cid())
|
||||
|
||||
// wait for it to get mined into a block
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("waiting for message to be included in block: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode.IsError() {
|
||||
return fmt.Errorf("confirm beneficiary change failed with code %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
updatedMinerInfo, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updatedMinerInfo.PendingBeneficiaryTerm == nil && updatedMinerInfo.Beneficiary == mi.PendingBeneficiaryTerm.NewBeneficiary {
|
||||
fmt.Println("Beneficiary address successfully changed")
|
||||
} else {
|
||||
fmt.Println("Beneficiary address change awaiting additional confirmations")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"github.com/ipld/go-car"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
"github.com/urfave/cli/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
@ -27,6 +29,42 @@ var cidCmd = &cli.Command{
|
||||
Subcommands: cli.Commands{
|
||||
cidIdCmd,
|
||||
inspectBundleCmd,
|
||||
cborCid,
|
||||
cidBytes,
|
||||
},
|
||||
}
|
||||
|
||||
var cidBytes = &cli.Command{
|
||||
Name: "bytes",
|
||||
Usage: "cid bytes",
|
||||
ArgsUsage: "[cid]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
c, err := cid.Decode(cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Add in the troublesome zero byte prefix
|
||||
fmt.Printf("00%x\n", c.Bytes())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var cborCid = &cli.Command{
|
||||
Name: "cbor",
|
||||
Usage: "Serialize cid to cbor",
|
||||
ArgsUsage: "[cid]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
c, err := cid.Decode(cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cbgc := cbg.CborCid(c)
|
||||
buf := bytes.NewBuffer(make([]byte, 0))
|
||||
if err := cbgc.MarshalCBOR(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%x\n", buf.Bytes())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ func main() {
|
||||
|
||||
local := []*cli.Command{
|
||||
addressCmd,
|
||||
statActorCmd,
|
||||
statObjCmd,
|
||||
base64Cmd,
|
||||
base32Cmd,
|
||||
base16Cmd,
|
||||
|
533
cmd/lotus-shed/state-stats.go
Normal file
533
cmd/lotus-shed/state-stats.go
Normal file
@ -0,0 +1,533 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/ipfs/go-blockservice"
|
||||
"github.com/ipfs/go-cid"
|
||||
offline "github.com/ipfs/go-ipfs-exchange-offline"
|
||||
format "github.com/ipfs/go-ipld-format"
|
||||
"github.com/ipfs/go-merkledag"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/consensus"
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||
)
|
||||
|
||||
type actorStats struct {
|
||||
Address address.Address
|
||||
Actor *types.Actor
|
||||
Fields []fieldItem
|
||||
Stats api.ObjStat
|
||||
}
|
||||
|
||||
type fieldItem struct {
|
||||
Name string
|
||||
Cid cid.Cid
|
||||
Stats api.ObjStat
|
||||
}
|
||||
|
||||
type cacheNodeGetter struct {
|
||||
ds format.NodeGetter
|
||||
cache *lru.TwoQueueCache
|
||||
}
|
||||
|
||||
func newCacheNodeGetter(d format.NodeGetter, size int) (*cacheNodeGetter, error) {
|
||||
cng := &cacheNodeGetter{ds: d}
|
||||
|
||||
cache, err := lru.New2Q(size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cng.cache = cache
|
||||
|
||||
return cng, nil
|
||||
}
|
||||
|
||||
func (cng *cacheNodeGetter) Get(ctx context.Context, c cid.Cid) (format.Node, error) {
|
||||
if n, ok := cng.cache.Get(c); ok {
|
||||
return n.(format.Node), nil
|
||||
}
|
||||
|
||||
n, err := cng.ds.Get(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cng.cache.Add(c, n)
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (cng *cacheNodeGetter) GetMany(ctx context.Context, list []cid.Cid) <-chan *format.NodeOption {
|
||||
out := make(chan *format.NodeOption, len(list))
|
||||
go func() {
|
||||
for _, c := range list {
|
||||
n, err := cng.Get(ctx, c)
|
||||
if err != nil {
|
||||
out <- &format.NodeOption{Err: err}
|
||||
continue
|
||||
}
|
||||
|
||||
out <- &format.NodeOption{Node: n}
|
||||
}
|
||||
}()
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
type dagStatCollector struct {
|
||||
ds format.NodeGetter
|
||||
walk func(format.Node) ([]*format.Link, error)
|
||||
|
||||
statsLk sync.Mutex
|
||||
stats api.ObjStat
|
||||
}
|
||||
|
||||
func (dsc *dagStatCollector) record(ctx context.Context, nd format.Node) error {
|
||||
size, err := nd.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dsc.statsLk.Lock()
|
||||
defer dsc.statsLk.Unlock()
|
||||
|
||||
dsc.stats.Size = dsc.stats.Size + size
|
||||
dsc.stats.Links = dsc.stats.Links + 1
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dsc *dagStatCollector) walkLinks(ctx context.Context, c cid.Cid) ([]*format.Link, error) {
|
||||
nd, err := dsc.ds.Get(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dsc.record(ctx, nd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dsc.walk(nd)
|
||||
}
|
||||
|
||||
type ChainStoreTipSetResolver struct {
|
||||
Chain *store.ChainStore
|
||||
}
|
||||
|
||||
func (tsr *ChainStoreTipSetResolver) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return tsr.Chain.GetHeaviestTipSet(), nil
|
||||
}
|
||||
|
||||
func (tsr *ChainStoreTipSetResolver) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
ts, err := tsr.Chain.GetTipSetFromKey(ctx, tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
|
||||
}
|
||||
return tsr.Chain.GetTipsetByHeight(ctx, h, ts, true)
|
||||
}
|
||||
func (tsr *ChainStoreTipSetResolver) ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error) {
|
||||
return tsr.Chain.LoadTipSet(ctx, tsk)
|
||||
}
|
||||
|
||||
var statObjCmd = &cli.Command{
|
||||
Name: "stat-obj",
|
||||
Usage: "calculates the size of any DAG in the blockstore",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
c, err := cid.Parse(cctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := repo.NewFS(cctx.String("repo"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("opening fs repo: %w", err)
|
||||
}
|
||||
|
||||
exists, err := r.Exists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return xerrors.Errorf("lotus repo doesn't exist")
|
||||
}
|
||||
|
||||
lr, err := r.Lock(repo.FullNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lr.Close() //nolint:errcheck
|
||||
|
||||
bs, err := lr.Blockstore(ctx, repo.UniversalBlockstore)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open blockstore: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
if err := c.Close(); err != nil {
|
||||
log.Warnf("failed to close blockstore: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
dag := merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
|
||||
dsc := &dagStatCollector{
|
||||
ds: dag,
|
||||
walk: carWalkFunc,
|
||||
}
|
||||
|
||||
if err := merkledag.Walk(ctx, dsc.walkLinks, c, cid.NewSet().Visit, merkledag.Concurrent()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return DumpJSON(dsc.stats)
|
||||
},
|
||||
}
|
||||
|
||||
var statActorCmd = &cli.Command{
|
||||
Name: "stat-actor",
|
||||
Usage: "calculates the size of actors and their immeidate structures",
|
||||
Description: `Any DAG linked by the actor object (field) will have its size calculated independently of all
|
||||
other linked DAG. If an actor has two fields containing links to the same DAG the structure size will be counted
|
||||
twice, included in each fields size individually.
|
||||
|
||||
The top level stats reported for an actor is computed independently of all fields and is a more accurate
|
||||
accounting of the true size of the actor in the state datastore.
|
||||
|
||||
The calculation of these stats results in the actor state being traversed twice. The dag-cache-size flag can be used
|
||||
to reduce the number of decode operations performed by caching the decoded object after first access.`,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "tipset",
|
||||
Usage: "specify tipset to call method on (pass comma separated array of cids)",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "workers",
|
||||
Usage: "number of workers to use when processing",
|
||||
Value: 10,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "dag-cache-size",
|
||||
Usage: "cache size per worker (setting to 0 disables)",
|
||||
Value: 8092,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "all",
|
||||
Usage: "process all actors in stateroot of tipset",
|
||||
Value: false,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "pretty",
|
||||
Usage: "print formated output instead of ldjson",
|
||||
Value: false,
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
var addrs []address.Address
|
||||
|
||||
if !cctx.Bool("all") {
|
||||
for _, a := range cctx.Args().Slice() {
|
||||
addr, err := address.NewFromString(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
}
|
||||
|
||||
r, err := repo.NewFS(cctx.String("repo"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("opening fs repo: %w", err)
|
||||
}
|
||||
|
||||
exists, err := r.Exists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return xerrors.Errorf("lotus repo doesn't exist")
|
||||
}
|
||||
|
||||
lr, err := r.Lock(repo.FullNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer lr.Close() //nolint:errcheck
|
||||
|
||||
bs, err := lr.Blockstore(ctx, repo.UniversalBlockstore)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open blockstore: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if c, ok := bs.(io.Closer); ok {
|
||||
if err := c.Close(); err != nil {
|
||||
log.Warnf("failed to close blockstore: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
mds, err := lr.Datastore(context.Background(), "/metadata")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs := store.NewChainStore(bs, bs, mds, nil, nil)
|
||||
if err := cs.Load(ctx); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tsExec := consensus.NewTipSetExecutor(filcns.RewardFunc)
|
||||
sm, err := stmgr.NewStateManager(cs, tsExec, vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tsr := &ChainStoreTipSetResolver{
|
||||
Chain: cs,
|
||||
}
|
||||
|
||||
ts, err := lcli.LoadTipSet(ctx, cctx, tsr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infow("tipset", "parentstate", ts.ParentState())
|
||||
|
||||
if len(addrs) == 0 && cctx.Bool("all") {
|
||||
var err error
|
||||
addrs, err = sm.ListAllActors(ctx, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
numWorkers := cctx.Int("workers")
|
||||
dagCacheSize := cctx.Int("dag-cache-size")
|
||||
|
||||
eg, egctx := errgroup.WithContext(ctx)
|
||||
|
||||
jobs := make(chan address.Address, numWorkers)
|
||||
results := make(chan actorStats, numWorkers)
|
||||
|
||||
worker := func(ctx context.Context, id int) error {
|
||||
completed := 0
|
||||
defer func() {
|
||||
log.Infow("worker done", "id", id, "completed", completed)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case addr, ok := <-jobs:
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
actor, err := sm.LoadActor(ctx, addr, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dag format.NodeGetter = merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
|
||||
if dagCacheSize != 0 {
|
||||
var err error
|
||||
dag, err = newCacheNodeGetter(merkledag.NewDAGService(blockservice.New(bs, offline.Exchange(bs))), dagCacheSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
actStats, err := collectStats(ctx, addr, actor, dag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
select {
|
||||
case results <- actStats:
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
completed = completed + 1
|
||||
}
|
||||
}
|
||||
|
||||
for w := 0; w < numWorkers; w++ {
|
||||
id := w
|
||||
eg.Go(func() error {
|
||||
return worker(egctx, id)
|
||||
})
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(jobs)
|
||||
for _, addr := range addrs {
|
||||
jobs <- addr
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// error is check later
|
||||
eg.Wait() //nolint:errcheck
|
||||
close(results)
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case result, ok := <-results:
|
||||
if !ok {
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
if cctx.Bool("pretty") {
|
||||
DumpStats(result)
|
||||
} else {
|
||||
if err := DumpJSON(result); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func collectStats(ctx context.Context, addr address.Address, actor *types.Actor, dag format.NodeGetter) (actorStats, error) {
|
||||
log.Infow("actor", "addr", addr, "code", actor.Code, "name", builtin.ActorNameByCode(actor.Code))
|
||||
|
||||
nd, err := dag.Get(ctx, actor.Head)
|
||||
if err != nil {
|
||||
return actorStats{}, err
|
||||
}
|
||||
|
||||
// When it comes to fvm / evm actors this method of inspecting fields will probably not work
|
||||
// and we may only be able to collect stats for the top level object. We might be able to iterate
|
||||
// over the top level fields for the actors and identify field that are CIDs, but unsure if we would
|
||||
// be able to identify a field name.
|
||||
|
||||
oif, err := vm.DumpActorState(consensus.NewTipSetExecutor(filcns.RewardFunc).NewActorRegistry(), actor, nd.RawData())
|
||||
if err != nil {
|
||||
oif = nil
|
||||
}
|
||||
|
||||
fields := []fieldItem{}
|
||||
|
||||
// Account actors return nil from DumpActorState as they have no state
|
||||
if oif != nil {
|
||||
v := reflect.Indirect(reflect.ValueOf(oif))
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
varName := v.Type().Field(i).Name
|
||||
varType := v.Type().Field(i).Type
|
||||
varValue := v.Field(i).Interface()
|
||||
|
||||
if varType == reflect.TypeOf(cid.Cid{}) {
|
||||
fields = append(fields, fieldItem{
|
||||
Name: varName,
|
||||
Cid: varValue.(cid.Cid),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actStats := actorStats{
|
||||
Address: addr,
|
||||
Actor: actor,
|
||||
}
|
||||
|
||||
dsc := &dagStatCollector{
|
||||
ds: dag,
|
||||
walk: carWalkFunc,
|
||||
}
|
||||
|
||||
if err := merkledag.Walk(ctx, dsc.walkLinks, actor.Head, cid.NewSet().Visit, merkledag.Concurrent()); err != nil {
|
||||
return actorStats{}, err
|
||||
}
|
||||
|
||||
actStats.Stats = dsc.stats
|
||||
|
||||
for _, field := range fields {
|
||||
dsc := &dagStatCollector{
|
||||
ds: dag,
|
||||
walk: carWalkFunc,
|
||||
}
|
||||
|
||||
if err := merkledag.Walk(ctx, dsc.walkLinks, field.Cid, cid.NewSet().Visit, merkledag.Concurrent()); err != nil {
|
||||
return actorStats{}, err
|
||||
}
|
||||
|
||||
field.Stats = dsc.stats
|
||||
|
||||
actStats.Fields = append(actStats.Fields, field)
|
||||
}
|
||||
|
||||
return actStats, nil
|
||||
}
|
||||
|
||||
func DumpJSON(i interface{}) error {
|
||||
bs, err := json.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(string(bs))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DumpStats(actStats actorStats) {
|
||||
strtype := builtin.ActorNameByCode(actStats.Actor.Code)
|
||||
fmt.Printf("Address:\t%s\n", actStats.Address)
|
||||
fmt.Printf("Balance:\t%s\n", types.FIL(actStats.Actor.Balance))
|
||||
fmt.Printf("Nonce:\t\t%d\n", actStats.Actor.Nonce)
|
||||
fmt.Printf("Code:\t\t%s (%s)\n", actStats.Actor.Code, strtype)
|
||||
fmt.Printf("Head:\t\t%s\n", actStats.Actor.Head)
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("%-*s%-*s%-*s\n", 32, "Field", 24, "Size", 24, "\"Blocks\"")
|
||||
|
||||
stats := actStats.Stats
|
||||
sizeStr := units.BytesSize(float64(stats.Size))
|
||||
fmt.Printf("%-*s%-*s%-*s%-*d\n", 32, "<self>", 10, sizeStr, 14, fmt.Sprintf("(%d)", stats.Size), 24, stats.Links)
|
||||
|
||||
for _, s := range actStats.Fields {
|
||||
stats := s.Stats
|
||||
sizeStr := units.BytesSize(float64(stats.Size))
|
||||
fmt.Printf("%-*s%-*s%-*s%-*d\n", 32, s.Name, 10, sizeStr, 14, fmt.Sprintf("(%d)", stats.Size), 24, stats.Links)
|
||||
}
|
||||
|
||||
fmt.Println("--------------------------------------------------------------------------")
|
||||
}
|
@ -1677,8 +1677,7 @@ COMMANDS:
|
||||
precommits Print on-chain precommit info
|
||||
check-expire Inspect expiring sectors
|
||||
expired Get or cleanup expired sectors
|
||||
renew Renew expiring sectors while not exceeding each sector's max life
|
||||
extend Extend sector expiration
|
||||
extend Extend expiring sectors while not exceeding each sector's max life
|
||||
terminate Terminate sector on-chain then remove (WARNING: This means losing power and collateral for the removed sector)
|
||||
remove Forcefully remove a sector (WARNING: This means losing power and collateral for the removed sector (use 'terminate' for lower penalty))
|
||||
snap-up Mark a committed capacity sector to be filled with deals
|
||||
@ -1884,13 +1883,13 @@ OPTIONS:
|
||||
|
||||
```
|
||||
|
||||
### lotus-miner sectors renew
|
||||
### lotus-miner sectors extend
|
||||
```
|
||||
NAME:
|
||||
lotus-miner sectors renew - Renew expiring sectors while not exceeding each sector's max life
|
||||
lotus-miner sectors extend - Extend expiring sectors while not exceeding each sector's max life
|
||||
|
||||
USAGE:
|
||||
lotus-miner sectors renew [command options] [arguments...]
|
||||
lotus-miner sectors extend [command options] <sectorNumbers...(optional)>
|
||||
|
||||
OPTIONS:
|
||||
--exclude value optionally provide a file containing excluding sectors
|
||||
@ -1900,31 +1899,13 @@ OPTIONS:
|
||||
--max-sectors value the maximum number of sectors contained in each message message (default: 0)
|
||||
--new-expiration value try to extend selected sectors to this epoch, ignoring extension (default: 0)
|
||||
--only-cc only extend CC sectors (useful for making sector ready for snap upgrade) (default: false)
|
||||
--really-do-it pass this flag to really renew sectors, otherwise will only print out json representation of parameters (default: false)
|
||||
--really-do-it pass this flag to really extend sectors, otherwise will only print out json representation of parameters (default: false)
|
||||
--sector-file value provide a file containing one sector number in each line, ignoring above selecting criteria
|
||||
--to value only consider sectors whose current expiration epoch is in the range of [from, to], <to> defaults to: now + 92160 (32 days) (default: 0)
|
||||
--tolerance value don't try to extend sectors by fewer than this number of epochs, defaults to 7 days (default: 20160)
|
||||
|
||||
```
|
||||
|
||||
### lotus-miner sectors extend
|
||||
```
|
||||
NAME:
|
||||
lotus-miner sectors extend - Extend sector expiration
|
||||
|
||||
USAGE:
|
||||
lotus-miner sectors extend [command options] <sectorNumbers...>
|
||||
|
||||
OPTIONS:
|
||||
|
||||
--expiration-cutoff value when extending v1 sectors, skip sectors whose current expiration is more than <cutoff> epochs from now (infinity if unspecified) (default: 0)
|
||||
--expiration-ignore value when extending v1 sectors, skip sectors whose current expiration is less than <ignore> epochs from now (default: 120)
|
||||
--new-expiration value new expiration epoch (default: 0)
|
||||
--tolerance value when extending v1 sectors, don't try to extend sectors by fewer than this number of epochs (default: 20160)
|
||||
--v1-sectors renews all v1 sectors up to the maximum possible lifetime (default: false)
|
||||
|
||||
```
|
||||
|
||||
### lotus-miner sectors terminate
|
||||
```
|
||||
NAME:
|
||||
|
6
go.mod
6
go.mod
@ -39,7 +39,7 @@ require (
|
||||
github.com/filecoin-project/go-data-transfer v1.15.2
|
||||
github.com/filecoin-project/go-fil-commcid v0.1.0
|
||||
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0
|
||||
github.com/filecoin-project/go-fil-markets v1.25.2
|
||||
github.com/filecoin-project/go-fil-markets v1.26.0
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.9
|
||||
github.com/filecoin-project/go-legs v0.4.4
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
@ -48,7 +48,6 @@ require (
|
||||
github.com/filecoin-project/go-statemachine v1.0.2
|
||||
github.com/filecoin-project/go-statestore v0.2.0
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||
github.com/filecoin-project/index-provider v0.9.1
|
||||
github.com/filecoin-project/pubsub v1.0.0
|
||||
github.com/filecoin-project/specs-actors v0.9.15
|
||||
github.com/filecoin-project/specs-actors/v2 v2.3.6
|
||||
@ -110,6 +109,7 @@ require (
|
||||
github.com/ipld/go-codec-dagpb v1.5.0
|
||||
github.com/ipld/go-ipld-prime v0.18.0
|
||||
github.com/ipld/go-ipld-selector-text-lite v0.0.1
|
||||
github.com/ipni/index-provider v0.10.0
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/koalacxr/quantile v0.0.1
|
||||
github.com/libp2p/go-buffer-pool v0.1.0
|
||||
@ -201,7 +201,6 @@ require (
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 // indirect
|
||||
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 // indirect
|
||||
github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 // indirect
|
||||
github.com/filecoin-project/storetheindex v0.4.30-0.20221114113647-683091f8e893 // indirect
|
||||
github.com/flynn/noise v1.0.0 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
@ -245,6 +244,7 @@ require (
|
||||
github.com/ipfs/go-peertaskqueue v0.8.0 // indirect
|
||||
github.com/ipfs/go-verifcid v0.0.2 // indirect
|
||||
github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0 // indirect
|
||||
github.com/ipni/storetheindex v0.5.3-0.20221203123030-16745cb63f15 // indirect
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c // indirect
|
||||
|
12
go.sum
12
go.sum
@ -331,8 +331,8 @@ github.com/filecoin-project/go-fil-commcid v0.1.0 h1:3R4ds1A9r6cr8mvZBfMYxTS88Oq
|
||||
github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 h1:imrrpZWEHRnNqqv0tN7LXep5bFEVOVmQWHJvl2mgsGo=
|
||||
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0/go.mod h1:73S8WSEWh9vr0fDJVnKADhfIv/d6dCbAGaAGWbdJEI8=
|
||||
github.com/filecoin-project/go-fil-markets v1.25.2 h1:kVfgaamTC7dkn8KwS5zRJBNEBSNvVqdG3BCoDaUYuCI=
|
||||
github.com/filecoin-project/go-fil-markets v1.25.2/go.mod h1:dc2oTPU6GH3Qk1nA+Er+hSX64rg+NVykkPIWFBYxcZU=
|
||||
github.com/filecoin-project/go-fil-markets v1.26.0 h1:uNtt1UAxX2C/Q8tlWD00oF2Zma3CVGxhZmBc2ljYhkk=
|
||||
github.com/filecoin-project/go-fil-markets v1.26.0/go.mod h1:eOIYHfPwyqc64O1HiapvcelfnrTfU7gLQgBf55IYleQ=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
|
||||
github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM=
|
||||
@ -366,8 +366,6 @@ github.com/filecoin-project/go-statestore v0.2.0 h1:cRRO0aPLrxKQCZ2UOQbzFGn4WDNd
|
||||
github.com/filecoin-project/go-statestore v0.2.0/go.mod h1:8sjBYbS35HwPzct7iT4lIXjLlYyPor80aU7t7a/Kspo=
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0 h1:Mui6wSUBC+cQGHbDUBcO7rfh5zQkWJM/CpAZa/uOuus=
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0/go.mod h1:4ceukaXi4vFURIoxYMfKzaRF5Xv/Pinh2oTnoxpv+z8=
|
||||
github.com/filecoin-project/index-provider v0.9.1 h1:Jnh9dviIHvQxZ2baNoYu3n8z6F9O62ksnVlyREgPyyM=
|
||||
github.com/filecoin-project/index-provider v0.9.1/go.mod h1:NlHxQcy2iMGfUoUGUzrRxntcpiC50QSnvp68u2VTT40=
|
||||
github.com/filecoin-project/pubsub v1.0.0 h1:ZTmT27U07e54qV1mMiQo4HDr0buo8I1LDHBYLXlsNXM=
|
||||
github.com/filecoin-project/pubsub v1.0.0/go.mod h1:GkpB33CcUtUNrLPhJgfdy4FDx4OMNR9k+46DHx/Lqrg=
|
||||
github.com/filecoin-project/specs-actors v0.9.13/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
|
||||
@ -388,8 +386,6 @@ github.com/filecoin-project/specs-actors/v7 v7.0.1 h1:w72xCxijK7xs1qzmJiw+WYJaVt
|
||||
github.com/filecoin-project/specs-actors/v7 v7.0.1/go.mod h1:tPLEYXoXhcpyLh69Ccq91SOuLXsPWjHiY27CzawjUEk=
|
||||
github.com/filecoin-project/specs-actors/v8 v8.0.1 h1:4u0tIRJeT5G7F05lwLRIsDnsrN+bJ5Ixj6h49Q7uE2Y=
|
||||
github.com/filecoin-project/specs-actors/v8 v8.0.1/go.mod h1:UYIPg65iPWoFw5NEftREdJwv9b/5yaLKdCgTvNI/2FA=
|
||||
github.com/filecoin-project/storetheindex v0.4.30-0.20221114113647-683091f8e893 h1:6GCuzxLVHBzlz7y+FkbHh6n0UyoEGWqDwJKQPJoz7bE=
|
||||
github.com/filecoin-project/storetheindex v0.4.30-0.20221114113647-683091f8e893/go.mod h1:S7590oDimBvXMUtzWsBXoshu9HtYKwtXl47zAK9rcP8=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
@ -899,6 +895,10 @@ github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd
|
||||
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY=
|
||||
github.com/ipld/go-ipld-selector-text-lite v0.0.1 h1:lNqFsQpBHc3p5xHob2KvEg/iM5dIFn6iw4L/Hh+kS1Y=
|
||||
github.com/ipld/go-ipld-selector-text-lite v0.0.1/go.mod h1:U2CQmFb+uWzfIEF3I1arrDa5rwtj00PrpiwwCO+k1RM=
|
||||
github.com/ipni/index-provider v0.10.0 h1:nu8YBxzRopdjwZHsgCUuC4AHpq88VVHJYrbkqUDx7eg=
|
||||
github.com/ipni/index-provider v0.10.0/go.mod h1:InSXbZp2p/ZhAwiDElG/wzjnA1ea1iJ3hhyiAHrD+Vo=
|
||||
github.com/ipni/storetheindex v0.5.3-0.20221203123030-16745cb63f15 h1:qJq6QtLk+9nQi3CDBhNfJ1cjZ4pghjCHcQUZ1mWbF0k=
|
||||
github.com/ipni/storetheindex v0.5.3-0.20221203123030-16745cb63f15/go.mod h1:c/NS640Iu2NrCCIErnUhsUM5KVEyeXymgtNnx6eDwMU=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
|
||||
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
|
@ -8,12 +8,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
provider "github.com/ipni/index-provider"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
"github.com/filecoin-project/go-fil-markets/shared_testutil"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
provider "github.com/filecoin-project/index-provider"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
|
@ -38,7 +38,7 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
ctx := context.Background()
|
||||
blockTime := 5 * time.Millisecond
|
||||
blockTime := 10 * time.Millisecond
|
||||
|
||||
var (
|
||||
paymentCreator kit.TestFullNode
|
||||
@ -55,6 +55,15 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
||||
bms := ens.BeginMiningMustPost(blockTime)
|
||||
bm := bms[0]
|
||||
|
||||
waitRecvInSync := func() {
|
||||
// paymentCreator is the block miner, in some cases paymentReceiver may fall behind, so we wait for it to catch up
|
||||
|
||||
head, err := paymentReceiver.ChainHead(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
paymentReceiver.WaitTillChain(ctx, kit.HeightAtLeast(head.Height()))
|
||||
}
|
||||
|
||||
// send some funds to register the receiver
|
||||
receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1)
|
||||
require.NoError(t, err)
|
||||
@ -74,6 +83,8 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
||||
channel, err := paymentCreator.PaychGetWaitReady(ctx, channelInfo.WaitSentinel)
|
||||
require.NoError(t, err)
|
||||
|
||||
waitRecvInSync()
|
||||
|
||||
// allocate three lanes
|
||||
var lanes []uint64
|
||||
for i := 0; i < 3; i++ {
|
||||
@ -110,6 +121,8 @@ func TestPaymentChannelsAPI(t *testing.T) {
|
||||
res := waitForMessage(ctx, t, paymentCreator, settleMsgCid, time.Second*10, "settle")
|
||||
require.EqualValues(t, 0, res.Receipt.ExitCode, "Unable to settle payment channel")
|
||||
|
||||
waitRecvInSync()
|
||||
|
||||
creatorStore := adt.WrapStore(ctx, cbor.NewCborStore(blockstore.NewAPIBlockstore(paymentCreator)))
|
||||
|
||||
// wait for the receiver to submit their vouchers
|
||||
|
@ -83,7 +83,7 @@ func TestLotusAccessorFetchUnsealedPiece(t *testing.T) {
|
||||
dealInfo := piecestore.DealInfo{
|
||||
SectorID: sectorID,
|
||||
}
|
||||
err = ps.AddDealForPiece(cid1, dealInfo)
|
||||
err = ps.AddDealForPiece(cid1, cid.Undef, dealInfo)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ func TestLotusAccessorGetUnpaddedCARSize(t *testing.T) {
|
||||
dealInfo := piecestore.DealInfo{
|
||||
Length: 10,
|
||||
}
|
||||
err = ps.AddDealForPiece(cid1, dealInfo)
|
||||
err = ps.AddDealForPiece(cid1, cid.Undef, dealInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check that the data length is correct
|
||||
@ -153,7 +153,7 @@ func TestThrottle(t *testing.T) {
|
||||
SectorID: unsealedSectorID,
|
||||
Length: 10,
|
||||
}
|
||||
err = ps.AddDealForPiece(cid1, dealInfo)
|
||||
err = ps.AddDealForPiece(cid1, cid.Undef, dealInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
// hold the lock to block.
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
provider "github.com/ipni/index-provider"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -12,7 +13,6 @@ import (
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
||||
"github.com/filecoin-project/go-fil-markets/storagemarket/impl/storedask"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
provider "github.com/filecoin-project/index-provider"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v1api"
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
graphsync "github.com/ipfs/go-graphsync/impl"
|
||||
gsnet "github.com/ipfs/go-graphsync/network"
|
||||
"github.com/ipfs/go-graphsync/storeutil"
|
||||
provider "github.com/ipni/index-provider"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/multierr"
|
||||
@ -42,7 +43,6 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-statestore"
|
||||
provider "github.com/filecoin-project/index-provider"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
|
@ -5,14 +5,14 @@ import (
|
||||
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/ipfs/go-datastore/namespace"
|
||||
provider "github.com/ipni/index-provider"
|
||||
"github.com/ipni/index-provider/engine"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
"go.uber.org/fx"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
provider "github.com/filecoin-project/index-provider"
|
||||
"github.com/filecoin-project/index-provider/engine"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-datastore"
|
||||
provider "github.com/ipni/index-provider"
|
||||
"github.com/libp2p/go-libp2p"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
@ -14,7 +15,6 @@ import (
|
||||
"go.uber.org/fx"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
provider "github.com/filecoin-project/index-provider"
|
||||
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
|
@ -94,8 +94,9 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server
|
||||
fnapi = api.PermissionedFullAPI(fnapi)
|
||||
}
|
||||
|
||||
var v0 v0api.FullNode = &(struct{ v0api.FullNode }{&v0api.WrapperV1Full{FullNode: fnapi}})
|
||||
serveRpc("/rpc/v1", fnapi)
|
||||
serveRpc("/rpc/v0", &v0api.WrapperV1Full{FullNode: fnapi})
|
||||
serveRpc("/rpc/v0", v0)
|
||||
|
||||
// Import handler
|
||||
handleImportFunc := handleImport(a.(*impl.FullNodeAPI))
|
||||
|
@ -1,3 +1,6 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
|
16
storage/sealer/fsutil/filesize_windows.go
Normal file
16
storage/sealer/fsutil/filesize_windows.go
Normal file
@ -0,0 +1,16 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type SizeInfo struct {
|
||||
OnDisk int64
|
||||
}
|
||||
|
||||
// FileSize returns bytes used by a file or directory on disk
|
||||
// NOTE: We care about the allocated bytes, not file or directory size
|
||||
// This is not currently supported on Windows, but at least other lotus can components can build on Windows now
|
||||
func FileSize(path string) (SizeInfo, error) {
|
||||
return SizeInfo{0}, fmt.Errorf("unsupported")
|
||||
}
|
Loading…
Reference in New Issue
Block a user