Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c81ea6dca | ||
|
|
2b398d0d80 | ||
|
|
8cad245f80 | ||
|
|
c767399fc6 | ||
|
|
3a46c15c4a | ||
|
|
420ec18c5b | ||
|
|
d78dd42ed4 | ||
|
|
547c01f5ff | ||
|
|
75eb644108 | ||
|
|
ee5dcbc1d8 | ||
|
|
7f46ad19ac | ||
|
|
ed1645109a | ||
|
|
277d3e9ab4 | ||
|
|
556f92a823 | ||
|
|
ef32449309 | ||
|
|
e08032da93 | ||
|
|
dc40469cb3 | ||
|
|
c779e4e8ee | ||
|
|
ee0078f7c1 | ||
|
|
da044d8b00 | ||
|
|
09e92f98ff | ||
|
|
0dbf10ce69 | ||
|
|
e7a68dba58 | ||
|
|
608010c35d |
@@ -188,6 +188,14 @@ jobs:
|
||||
command: |
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
test-chain:
|
||||
<<: *test
|
||||
test-node:
|
||||
<<: *test
|
||||
test-storage:
|
||||
<<: *test
|
||||
test-cli:
|
||||
<<: *test
|
||||
test-short:
|
||||
<<: *test
|
||||
test-window-post:
|
||||
@@ -428,6 +436,22 @@ workflows:
|
||||
- test:
|
||||
codecov-upload: true
|
||||
test-suite-name: full
|
||||
- test-chain:
|
||||
codecov-upload: true
|
||||
test-suite-name: chain
|
||||
packages: "./chain/..."
|
||||
- test-node:
|
||||
codecov-upload: true
|
||||
test-suite-name: node
|
||||
packages: "./node/..."
|
||||
- test-storage:
|
||||
codecov-upload: true
|
||||
test-suite-name: storage
|
||||
packages: "./storage/... ./extern/..."
|
||||
- test-cli:
|
||||
codecov-upload: true
|
||||
test-suite-name: cli
|
||||
packages: "./cli/... ./cmd/... ./api/..."
|
||||
- test-window-post:
|
||||
go-test-flags: "-run=TestWindowedPost"
|
||||
winpost-test: "1"
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# Lotus changelog
|
||||
|
||||
# 1.1.0 / 2020-10-20
|
||||
|
||||
This is a mandatory release that introduces the first post-liftoff upgrade to the Filecoin network. The changes that break consensus are an upgrade to specs-actors v2.2.0 at epoch 170000.
|
||||
|
||||
## Changes
|
||||
|
||||
- Introduce Network version 6 (https://github.com/filecoin-project/lotus/pull/4506)
|
||||
- Update markets v1.0.0 (https://github.com/filecoin-project/lotus/pull/4505)
|
||||
- Add some extra logging to try and debug sync issues (https://github.com/filecoin-project/lotus/pull/4486)
|
||||
- Circle: Run tests for some subsystems separately (https://github.com/filecoin-project/lotus/pull/4496)
|
||||
- Add a terminate sectors command to lotus-shed (https://github.com/filecoin-project/lotus/pull/4507)
|
||||
- Add a comment to BlockMessages to address #4446 (https://github.com/filecoin-project/lotus/pull/4491)
|
||||
|
||||
# 1.0.0 / 2020-10-19
|
||||
|
||||
It's 1.0.0! This is an optional release of Lotus that introduces some UX improvements to the 0.10 series.
|
||||
|
||||
@@ -133,18 +133,30 @@ benchmarks:
|
||||
|
||||
lotus-pond: 2k
|
||||
go build -o lotus-pond ./lotuspond
|
||||
(cd lotuspond/front && npm i && CI=false npm run build)
|
||||
.PHONY: lotus-pond
|
||||
BINS+=lotus-pond
|
||||
|
||||
lotus-pond-front:
|
||||
(cd lotuspond/front && npm i && CI=false npm run build)
|
||||
.PHONY: lotus-pond-front
|
||||
|
||||
lotus-pond-app: lotus-pond-front lotus-pond
|
||||
.PHONY: lotus-pond-app
|
||||
|
||||
lotus-townhall:
|
||||
rm -f lotus-townhall
|
||||
go build -o lotus-townhall ./cmd/lotus-townhall
|
||||
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build
|
||||
.PHONY: lotus-townhall
|
||||
BINS+=lotus-townhall
|
||||
|
||||
lotus-townhall-front:
|
||||
(cd ./cmd/lotus-townhall/townhall && npm i && npm run build)
|
||||
.PHONY: lotus-townhall-front
|
||||
|
||||
lotus-townhall-app: lotus-touch lotus-townhall-front
|
||||
go run github.com/GeertJohan/go.rice/rice append --exec lotus-townhall -i ./cmd/lotus-townhall -i ./build
|
||||
.PHONY: lotus-townhall-app
|
||||
|
||||
lotus-fountain:
|
||||
rm -f lotus-fountain
|
||||
go build -o lotus-fountain ./cmd/lotus-fountain
|
||||
|
||||
@@ -591,6 +591,8 @@ type MsgGasCost struct {
|
||||
TotalCost abi.TokenAmount
|
||||
}
|
||||
|
||||
// BlsMessages[x].cid = Cids[x]
|
||||
// SecpkMessages[y].cid = Cids[BlsMessages.length + y]
|
||||
type BlockMessages struct {
|
||||
BlsMessages []*types.Message
|
||||
SecpkMessages []*types.SignedMessage
|
||||
|
||||
@@ -1,15 +1,2 @@
|
||||
/dns4/bootstrap-0.mainnet.filops.net/tcp/1347/p2p/12D3KooWCVe8MmsEMes2FzgTpt9fXtmCY7wrq91GRiaC8PHSCCBj
|
||||
/dns4/bootstrap-1.mainnet.filops.net/tcp/1347/p2p/12D3KooWCwevHg1yLCvktf2nvLu7L9894mcrJR4MsBCcm4syShVc
|
||||
/dns4/bootstrap-2.mainnet.filops.net/tcp/1347/p2p/12D3KooWEWVwHGn2yR36gKLozmb4YjDJGerotAPGxmdWZx2nxMC4
|
||||
/dns4/bootstrap-3.mainnet.filops.net/tcp/1347/p2p/12D3KooWKhgq8c7NQ9iGjbyK7v7phXvG6492HQfiDaGHLHLQjk7R
|
||||
/dns4/bootstrap-4.mainnet.filops.net/tcp/1347/p2p/12D3KooWL6PsFNPhYftrJzGgF5U18hFoaVhfGk7xwzD8yVrHJ3Uc
|
||||
/dns4/bootstrap-5.mainnet.filops.net/tcp/1347/p2p/12D3KooWLFynvDQiUpXoHroV1YxKHhPJgysQGH2k3ZGwtWzR4dFH
|
||||
/dns4/bootstrap-6.mainnet.filops.net/tcp/1347/p2p/12D3KooWP5MwCiqdMETF9ub1P3MbCvQCcfconnYHbWg6sUJcDRQQ
|
||||
/dns4/bootstrap-7.mainnet.filops.net/tcp/1347/p2p/12D3KooWRs3aY1p3juFjPy8gPN95PEQChm2QKGUCAdcDCC4EBMKf
|
||||
/dns4/bootstrap-8.mainnet.filops.net/tcp/1347/p2p/12D3KooWScFR7385LTyR4zU1bYdzSiiAb5rnNABfVahPvVSzyTkR
|
||||
/dns4/lotus-bootstrap.forceup.cn/tcp/41778/p2p/12D3KooWFQsv3nRMUevZNWWsY1Wu6NUzUbawnWU5NcRhgKuJA37C
|
||||
/dns4/bootstrap-0.starpool.in/tcp/12757/p2p/12D3KooWGHpBMeZbestVEWkfdnC9u7p6uFHXL1n7m1ZBqsEmiUzz
|
||||
/dns4/bootstrap-1.starpool.in/tcp/12757/p2p/12D3KooWQZrGH1PxSNZPum99M1zNvjNFM33d1AAu5DcvdHptuU7u
|
||||
/dns4/node.glif.io/tcp/1235/p2p/12D3KooWBF8cpp65hp2u9LK5mh19x67ftAam84z9LsfaquTDSBpt
|
||||
/dns4/bootstrap-0.ipfsmain.cn/tcp/34721/p2p/12D3KooWQnwEGNqcM2nAcPtRR9rAX8Hrg4k9kJLCHoTR5chJfz6d
|
||||
/dns4/bootstrap-1.ipfsmain.cn/tcp/34723/p2p/12D3KooWMKxMkD5DMpSWsW7dBddKxKT7L2GgbNuckz9otxvkvByP
|
||||
/dns4/bootstrap-0.butterfly.fildev.network/tcp/1347/p2p/12D3KooWMHa7pphgSUm2FMXLPPk5UodNzzu1eULWsnBEiyRQEdpe
|
||||
/dns4/bootstrap-1.butterfly.fildev.network/tcp/1347/p2p/12D3KooWE88B8e5sBgzCwfWjGAdzVY588BVKfhniuyXbRZaJSPbF
|
||||
|
||||
Binary file not shown.
@@ -22,6 +22,8 @@ const UpgradeTapeHeight = -4
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(10)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-5)
|
||||
|
||||
const UpgradeKumquatHeight = -6
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
+14
-21
@@ -5,9 +5,6 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
@@ -16,43 +13,39 @@ import (
|
||||
)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandIncentinet,
|
||||
UpgradeSmokeHeight: DrandMainnet,
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
const UpgradeBreezeHeight = 41280
|
||||
const UpgradeBreezeHeight = -1
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
const UpgradeSmokeHeight = 51000
|
||||
const UpgradeSmokeHeight = -2
|
||||
|
||||
const UpgradeIgnitionHeight = 94000
|
||||
const UpgradeRefuelHeight = 130800
|
||||
const UpgradeIgnitionHeight = -3
|
||||
const UpgradeRefuelHeight = -4
|
||||
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(138720)
|
||||
var UpgradeActorsV2Height = abi.ChainEpoch(30)
|
||||
|
||||
const UpgradeTapeHeight = 140760
|
||||
const UpgradeTapeHeight = 60
|
||||
|
||||
// This signals our tentative epoch for mainnet launch. Can make it later, but not earlier.
|
||||
// Miners, clients, developers, custodians all need time to prepare.
|
||||
// We still have upgrades and state changes to do, but can happen after signaling timing here.
|
||||
const UpgradeLiftoffHeight = 148888
|
||||
const UpgradeLiftoffHeight = -5
|
||||
|
||||
const UpgradeKumquatHeight = 90
|
||||
|
||||
func init() {
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(10 << 40))
|
||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(1 << 30))
|
||||
policy.SetSupportedProofTypes(
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
)
|
||||
|
||||
if os.Getenv("LOTUS_USE_TEST_ADDRESSES") != "1" {
|
||||
SetAddressNetwork(address.Mainnet)
|
||||
}
|
||||
SetAddressNetwork(address.Testnet)
|
||||
|
||||
if os.Getenv("LOTUS_DISABLE_V2_ACTOR_MIGRATION") == "1" {
|
||||
UpgradeActorsV2Height = math.MaxInt64
|
||||
}
|
||||
|
||||
Devnet = false
|
||||
Devnet = true
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin0.EpochDurationSeconds)
|
||||
|
||||
@@ -25,7 +25,7 @@ const UnixfsLinksPerLevel = 1024
|
||||
// Consensus / Network
|
||||
|
||||
const AllowableClockDriftSecs = uint64(1)
|
||||
const NewestNetworkVersion = network.Version5
|
||||
const NewestNetworkVersion = network.Version6
|
||||
const ActorUpgradeNetworkVersion = network.Version4
|
||||
|
||||
// Epochs
|
||||
|
||||
@@ -86,6 +86,7 @@ var (
|
||||
UpgradeTapeHeight abi.ChainEpoch = -4
|
||||
UpgradeActorsV2Height abi.ChainEpoch = 10
|
||||
UpgradeLiftoffHeight abi.ChainEpoch = -5
|
||||
UpgradeKumquatHeight abi.ChainEpoch = -6
|
||||
|
||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ func buildType() string {
|
||||
}
|
||||
|
||||
// BuildVersion is the local build version, set by build system
|
||||
const BuildVersion = "1.0.0"
|
||||
const BuildVersion = "1.1.0"
|
||||
|
||||
func UserVersion() string {
|
||||
return BuildVersion + buildType() + CurrentCommit
|
||||
|
||||
@@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version {
|
||||
switch version {
|
||||
case network.Version0, network.Version1, network.Version2, network.Version3:
|
||||
return Version0
|
||||
case network.Version4, network.Version5:
|
||||
case network.Version4, network.Version5, network.Version6:
|
||||
return Version2
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported network version %d", version))
|
||||
|
||||
@@ -405,7 +405,7 @@ func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.Toke
|
||||
rt := unsafeVM.MakeRuntime(ctx, &types.Message{
|
||||
GasLimit: 1_000_000_000,
|
||||
From: maddr,
|
||||
}, maddr, 0, 0, 0)
|
||||
})
|
||||
|
||||
return rt.TotalFilCircSupply()
|
||||
}
|
||||
|
||||
@@ -86,6 +86,10 @@ func DefaultUpgradeSchedule() UpgradeSchedule {
|
||||
Height: build.UpgradeLiftoffHeight,
|
||||
Network: network.Version5,
|
||||
Migration: UpgradeLiftoff,
|
||||
}, {
|
||||
Height: build.UpgradeKumquatHeight,
|
||||
Network: network.Version6,
|
||||
Migration: nil,
|
||||
}}
|
||||
|
||||
if build.UpgradeActorsV2Height == math.MaxInt64 { // disable actors upgrade
|
||||
|
||||
+3
-2
@@ -268,14 +268,15 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
|
||||
|
||||
syncer.Exchange.AddPeer(from)
|
||||
|
||||
bestPweight := syncer.store.GetHeaviestTipSet().ParentWeight()
|
||||
hts := syncer.store.GetHeaviestTipSet()
|
||||
bestPweight := hts.ParentWeight()
|
||||
targetWeight := fts.TipSet().ParentWeight()
|
||||
if targetWeight.LessThan(bestPweight) {
|
||||
var miners []string
|
||||
for _, blk := range fts.TipSet().Blocks() {
|
||||
miners = append(miners, blk.Miner.String())
|
||||
}
|
||||
log.Infof("incoming tipset from %s does not appear to be better than our best chain, ignoring for now", miners)
|
||||
log.Infow("incoming tipset does not appear to be better than our best chain, ignoring for now", "miners", miners, "bestPweight", bestPweight, "bestTS", hts.Cids(), "incomingWeight", targetWeight, "incomingTS", fts.TipSet().Cids())
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@ func (stb *syncTargetBucket) add(ts *types.TipSet) {
|
||||
|
||||
func (stb *syncTargetBucket) heaviestTipSet() *types.TipSet {
|
||||
if stb == nil {
|
||||
log.Warn("sync target bucket was nil when heaviestTipSet got called on it")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ type Runtime struct {
|
||||
originNonce uint64
|
||||
|
||||
executionTrace types.ExecutionTrace
|
||||
depth uint64
|
||||
numActorsCreated uint64
|
||||
allowInternal bool
|
||||
callerValidated bool
|
||||
|
||||
+23
-19
@@ -38,6 +38,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/bufbstore"
|
||||
)
|
||||
|
||||
const MaxCallDepth = 4096
|
||||
|
||||
var log = logging.Logger("vm")
|
||||
var actorLog = logging.Logger("actors")
|
||||
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
||||
@@ -97,24 +99,37 @@ func (bs *gasChargingBlocks) Put(blk block.Block) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime {
|
||||
func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime {
|
||||
rt := &Runtime{
|
||||
ctx: ctx,
|
||||
vm: vm,
|
||||
state: vm.cstate,
|
||||
origin: origin,
|
||||
originNonce: originNonce,
|
||||
origin: msg.From,
|
||||
originNonce: msg.Nonce,
|
||||
height: vm.blockHeight,
|
||||
|
||||
gasUsed: usedGas,
|
||||
gasUsed: 0,
|
||||
gasAvailable: msg.GasLimit,
|
||||
numActorsCreated: nac,
|
||||
depth: 0,
|
||||
numActorsCreated: 0,
|
||||
pricelist: PricelistByEpoch(vm.blockHeight),
|
||||
allowInternal: true,
|
||||
callerValidated: false,
|
||||
executionTrace: types.ExecutionTrace{Msg: msg},
|
||||
}
|
||||
|
||||
if parent != nil {
|
||||
rt.gasUsed = parent.gasUsed
|
||||
rt.origin = parent.origin
|
||||
rt.originNonce = parent.originNonce
|
||||
rt.numActorsCreated = parent.numActorsCreated
|
||||
rt.depth = parent.depth + 1
|
||||
}
|
||||
|
||||
if rt.depth > MaxCallDepth && rt.NetworkVersion() >= network.Version6 {
|
||||
rt.Abortf(exitcode.SysErrForbidden, "message execution exceeds call depth")
|
||||
}
|
||||
|
||||
rt.cst = &cbor.BasicIpldStore{
|
||||
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
|
||||
Atlas: vm.cst.Atlas,
|
||||
@@ -148,8 +163,8 @@ type UnsafeVM struct {
|
||||
VM *VM
|
||||
}
|
||||
|
||||
func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime {
|
||||
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac)
|
||||
func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtime {
|
||||
return vm.VM.makeRuntime(ctx, msg, nil)
|
||||
}
|
||||
|
||||
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
|
||||
@@ -224,18 +239,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
|
||||
|
||||
st := vm.cstate
|
||||
|
||||
origin := msg.From
|
||||
on := msg.Nonce
|
||||
var nac uint64 = 0
|
||||
var gasUsed int64
|
||||
if parent != nil {
|
||||
gasUsed = parent.gasUsed
|
||||
origin = parent.origin
|
||||
on = parent.originNonce
|
||||
nac = parent.numActorsCreated
|
||||
}
|
||||
|
||||
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
|
||||
rt := vm.makeRuntime(ctx, msg, parent)
|
||||
if EnableGasTracing {
|
||||
rt.lastGasChargeTime = start
|
||||
if parent != nil {
|
||||
|
||||
+402
-96
@@ -1,19 +1,25 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
tm "github.com/buger/goterm"
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/fatih/color"
|
||||
datatransfer "github.com/filecoin-project/go-data-transfer"
|
||||
@@ -74,6 +80,7 @@ var clientCmd = &cli.Command{
|
||||
WithCategory("storage", clientQueryAskCmd),
|
||||
WithCategory("storage", clientListDeals),
|
||||
WithCategory("storage", clientGetDealCmd),
|
||||
WithCategory("storage", clientListAsksCmd),
|
||||
WithCategory("data", clientImportCmd),
|
||||
WithCategory("data", clientDropCmd),
|
||||
WithCategory("data", clientLocalCmd),
|
||||
@@ -468,16 +475,26 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
state := "import"
|
||||
gib := types.NewInt(1 << 30)
|
||||
|
||||
var data cid.Cid
|
||||
var days int
|
||||
var maddr address.Address
|
||||
var ask storagemarket.StorageAsk
|
||||
var epochPrice big.Int
|
||||
var maddrs []address.Address
|
||||
var ask []storagemarket.StorageAsk
|
||||
var epochPrices []big.Int
|
||||
var dur time.Duration
|
||||
var epochs abi.ChainEpoch
|
||||
var verified bool
|
||||
var ds lapi.DataSize
|
||||
|
||||
// find
|
||||
var candidateAsks []*storagemarket.StorageAsk
|
||||
var budget types.FIL
|
||||
var dealCount int64
|
||||
|
||||
var a address.Address
|
||||
if from := cctx.String("from"); from != "" {
|
||||
@@ -494,10 +511,24 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
a = def
|
||||
}
|
||||
|
||||
fromBal, err := api.WalletBalance(ctx, a)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("checking from address balance: %w", err)
|
||||
}
|
||||
|
||||
printErr := func(err error) {
|
||||
fmt.Printf("%s %s\n", color.RedString("Error:"), err.Error())
|
||||
}
|
||||
|
||||
cs := readline.NewCancelableStdin(os.Stdin)
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
cs.Close() // nolint:errcheck
|
||||
}()
|
||||
|
||||
rl := bufio.NewReader(cs)
|
||||
|
||||
uiLoop:
|
||||
for {
|
||||
// TODO: better exit handling
|
||||
if err := ctx.Err(); err != nil {
|
||||
@@ -508,8 +539,8 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
case "import":
|
||||
fmt.Print("Data CID (from " + color.YellowString("lotus client import") + "): ")
|
||||
|
||||
var cidStr string
|
||||
_, err := fmt.Scan(&cidStr)
|
||||
_cidStr, _, err := rl.ReadLine()
|
||||
cidStr := string(_cidStr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("reading cid string: %w", err))
|
||||
continue
|
||||
@@ -521,11 +552,23 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
color.Blue(".. calculating data size\n")
|
||||
ds, err = api.ClientDealSize(ctx, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
state = "duration"
|
||||
case "duration":
|
||||
fmt.Print("Deal duration (days): ")
|
||||
|
||||
_, err := fmt.Scan(&days)
|
||||
_daystr, _, err := rl.ReadLine()
|
||||
daystr := string(_daystr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Sscan(daystr, &days)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("parsing duration: %w", err))
|
||||
continue
|
||||
@@ -536,44 +579,9 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
state = "miner"
|
||||
case "miner":
|
||||
fmt.Print("Miner Address (f0..): ")
|
||||
var maddrStr string
|
||||
dur = 24 * time.Hour * time.Duration(days)
|
||||
epochs = abi.ChainEpoch(dur / (time.Duration(build.BlockDelaySecs) * time.Second))
|
||||
|
||||
_, err := fmt.Scan(&maddrStr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("reading miner address: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
maddr, err = address.NewFromString(maddrStr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("parsing miner address: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
state = "query"
|
||||
case "query":
|
||||
color.Blue(".. querying miner ask")
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("failed to get peerID for miner: %w", err))
|
||||
state = "miner"
|
||||
continue
|
||||
}
|
||||
|
||||
a, err := api.ClientQueryAsk(ctx, *mi.PeerId, maddr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("failed to query ask: %w", err))
|
||||
state = "miner"
|
||||
continue
|
||||
}
|
||||
|
||||
ask = *a
|
||||
|
||||
// TODO: run more validation
|
||||
state = "verified"
|
||||
case "verified":
|
||||
ts, err := api.ChainHead(ctx)
|
||||
@@ -587,26 +595,20 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
}
|
||||
|
||||
if dcap == nil {
|
||||
state = "confirm"
|
||||
state = "miner"
|
||||
continue
|
||||
}
|
||||
|
||||
color.Blue(".. checking verified deal eligibility\n")
|
||||
ds, err := api.ClientDealSize(ctx, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dcap.Uint64() < uint64(ds.PieceSize) {
|
||||
color.Yellow(".. not enough DataCap available for a verified deal\n")
|
||||
state = "confirm"
|
||||
state = "miner"
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Print("\nMake this a verified deal? (yes/no): ")
|
||||
|
||||
var yn string
|
||||
_, err = fmt.Scan(&yn)
|
||||
_yn, _, err := rl.ReadLine()
|
||||
yn := string(_yn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -621,34 +623,162 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
state = "confirm"
|
||||
case "confirm":
|
||||
fromBal, err := api.WalletBalance(ctx, a)
|
||||
state = "miner"
|
||||
case "miner":
|
||||
fmt.Print("Miner Addresses (f0.. f0..), none to find: ")
|
||||
|
||||
_maddrsStr, _, err := rl.ReadLine()
|
||||
maddrsStr := string(_maddrsStr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("checking from address balance: %w", err)
|
||||
printErr(xerrors.Errorf("reading miner address: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
color.Blue(".. calculating data size\n")
|
||||
ds, err := api.ClientDealSize(ctx, data)
|
||||
for _, s := range strings.Fields(maddrsStr) {
|
||||
maddr, err := address.NewFromString(strings.TrimSpace(s))
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("parsing miner address: %w", err))
|
||||
continue uiLoop
|
||||
}
|
||||
|
||||
maddrs = append(maddrs, maddr)
|
||||
}
|
||||
|
||||
state = "query"
|
||||
if len(maddrs) == 0 {
|
||||
state = "find"
|
||||
}
|
||||
case "find":
|
||||
asks, err := getAsks(ctx, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dur := 24 * time.Hour * time.Duration(days)
|
||||
|
||||
epochs = abi.ChainEpoch(dur / (time.Duration(build.BlockDelaySecs) * time.Second))
|
||||
// TODO: do some more or epochs math (round to miner PP, deal start buffer)
|
||||
|
||||
pricePerGib := ask.Price
|
||||
if verified {
|
||||
pricePerGib = ask.VerifiedPrice
|
||||
for _, ask := range asks {
|
||||
if ask.MinPieceSize > ds.PieceSize {
|
||||
continue
|
||||
}
|
||||
if ask.MaxPieceSize < ds.PieceSize {
|
||||
continue
|
||||
}
|
||||
candidateAsks = append(candidateAsks, ask)
|
||||
}
|
||||
|
||||
gib := types.NewInt(1 << 30)
|
||||
fmt.Printf("Found %d candidate asks\n", len(candidateAsks))
|
||||
state = "find-budget"
|
||||
case "find-budget":
|
||||
fmt.Printf("Proposing from %s, Current Balance: %s\n", a, types.FIL(fromBal))
|
||||
fmt.Print("Maximum budget (FIL): ") // TODO: Propose some default somehow?
|
||||
|
||||
// TODO: price is based on PaddedPieceSize, right?
|
||||
epochPrice = types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||
_budgetStr, _, err := rl.ReadLine()
|
||||
budgetStr := string(_budgetStr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("reading miner address: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
budget, err = types.ParseFIL(budgetStr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("parsing FIL: %w", err))
|
||||
continue uiLoop
|
||||
}
|
||||
|
||||
var goodAsks []*storagemarket.StorageAsk
|
||||
for _, ask := range candidateAsks {
|
||||
p := ask.Price
|
||||
if verified {
|
||||
p = ask.VerifiedPrice
|
||||
}
|
||||
|
||||
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||
|
||||
if totalPrice.LessThan(abi.TokenAmount(budget)) {
|
||||
goodAsks = append(goodAsks, ask)
|
||||
}
|
||||
}
|
||||
candidateAsks = goodAsks
|
||||
fmt.Printf("%d asks within budget\n", len(candidateAsks))
|
||||
state = "find-count"
|
||||
case "find-count":
|
||||
fmt.Print("Deals to make (1): ")
|
||||
dealcStr, _, err := rl.ReadLine()
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("reading deal count: %w", err))
|
||||
continue
|
||||
}
|
||||
|
||||
dealCount, err = strconv.ParseInt(string(dealcStr), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
color.Blue(".. Picking miners")
|
||||
|
||||
// TODO: some better strategy (this tries to pick randomly)
|
||||
var pickedAsks []*storagemarket.StorageAsk
|
||||
pickLoop:
|
||||
for i := 0; i < 64; i++ {
|
||||
rand.Shuffle(len(candidateAsks), func(i, j int) {
|
||||
candidateAsks[i], candidateAsks[j] = candidateAsks[j], candidateAsks[i]
|
||||
})
|
||||
|
||||
remainingBudget := abi.TokenAmount(budget)
|
||||
pickedAsks = []*storagemarket.StorageAsk{}
|
||||
|
||||
for _, ask := range candidateAsks {
|
||||
p := ask.Price
|
||||
if verified {
|
||||
p = ask.VerifiedPrice
|
||||
}
|
||||
|
||||
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||
|
||||
if totalPrice.GreaterThan(remainingBudget) {
|
||||
continue
|
||||
}
|
||||
|
||||
pickedAsks = append(pickedAsks, ask)
|
||||
remainingBudget = big.Sub(remainingBudget, totalPrice)
|
||||
|
||||
if len(pickedAsks) == int(dealCount) {
|
||||
break pickLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, pickedAsk := range pickedAsks {
|
||||
maddrs = append(maddrs, pickedAsk.Miner)
|
||||
ask = append(ask, *pickedAsk)
|
||||
}
|
||||
|
||||
state = "confirm"
|
||||
case "query":
|
||||
color.Blue(".. querying miner asks")
|
||||
|
||||
for _, maddr := range maddrs {
|
||||
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("failed to get peerID for miner: %w", err))
|
||||
state = "miner"
|
||||
continue uiLoop
|
||||
}
|
||||
|
||||
a, err := api.ClientQueryAsk(ctx, *mi.PeerId, maddr)
|
||||
if err != nil {
|
||||
printErr(xerrors.Errorf("failed to query ask: %w", err))
|
||||
state = "miner"
|
||||
continue uiLoop
|
||||
}
|
||||
|
||||
ask = append(ask, *a)
|
||||
}
|
||||
|
||||
// TODO: run more validation
|
||||
state = "confirm"
|
||||
case "confirm":
|
||||
// TODO: do some more or epochs math (round to miner PP, deal start buffer)
|
||||
|
||||
fmt.Printf("-----\n")
|
||||
fmt.Printf("Proposing from %s\n", a)
|
||||
@@ -656,15 +786,41 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
fmt.Printf("\n")
|
||||
fmt.Printf("Piece size: %s (Payload size: %s)\n", units.BytesSize(float64(ds.PieceSize)), units.BytesSize(float64(ds.PayloadSize)))
|
||||
fmt.Printf("Duration: %s\n", dur)
|
||||
fmt.Printf("Total price: ~%s (%s per epoch)\n", types.FIL(totalPrice), types.FIL(epochPrice))
|
||||
|
||||
pricePerGib := big.Zero()
|
||||
for _, a := range ask {
|
||||
p := a.Price
|
||||
if verified {
|
||||
p = a.VerifiedPrice
|
||||
}
|
||||
pricePerGib = big.Add(pricePerGib, p)
|
||||
epochPrice := types.BigDiv(types.BigMul(p, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||
epochPrices = append(epochPrices, epochPrice)
|
||||
|
||||
mpow, err := api.StateMinerPower(ctx, a.Miner, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting power (%s): %w", a.Miner, err)
|
||||
}
|
||||
|
||||
if len(ask) > 1 {
|
||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||
fmt.Printf("Miner %s (Power:%s) price: ~%s (%s per epoch)\n", color.YellowString(a.Miner.String()), color.GreenString(types.SizeStr(mpow.MinerPower.QualityAdjPower)), color.BlueString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: price is based on PaddedPieceSize, right?
|
||||
epochPrice := types.BigDiv(types.BigMul(pricePerGib, types.NewInt(uint64(ds.PieceSize))), gib)
|
||||
totalPrice := types.BigMul(epochPrice, types.NewInt(uint64(epochs)))
|
||||
|
||||
fmt.Printf("Total price: ~%s (%s per epoch)\n", color.CyanString(types.FIL(totalPrice).String()), types.FIL(epochPrice))
|
||||
fmt.Printf("Verified: %v\n", verified)
|
||||
|
||||
state = "accept"
|
||||
case "accept":
|
||||
fmt.Print("\nAccept (yes/no): ")
|
||||
|
||||
var yn string
|
||||
_, err := fmt.Scan(&yn)
|
||||
_yn, _, err := rl.ReadLine()
|
||||
yn := string(_yn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -680,30 +836,34 @@ func interactiveDeal(cctx *cli.Context) error {
|
||||
|
||||
state = "execute"
|
||||
case "execute":
|
||||
color.Blue(".. executing")
|
||||
proposal, err := api.ClientStartDeal(ctx, &lapi.StartDealParams{
|
||||
Data: &storagemarket.DataRef{
|
||||
TransferType: storagemarket.TTGraphsync,
|
||||
Root: data,
|
||||
},
|
||||
Wallet: a,
|
||||
Miner: maddr,
|
||||
EpochPrice: epochPrice,
|
||||
MinBlocksDuration: uint64(epochs),
|
||||
DealStartEpoch: abi.ChainEpoch(cctx.Int64("start-epoch")),
|
||||
FastRetrieval: cctx.Bool("fast-retrieval"),
|
||||
VerifiedDeal: verified,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
color.Blue(".. executing\n")
|
||||
|
||||
for i, maddr := range maddrs {
|
||||
proposal, err := api.ClientStartDeal(ctx, &lapi.StartDealParams{
|
||||
Data: &storagemarket.DataRef{
|
||||
TransferType: storagemarket.TTGraphsync,
|
||||
Root: data,
|
||||
},
|
||||
Wallet: a,
|
||||
Miner: maddr,
|
||||
EpochPrice: epochPrices[i],
|
||||
MinBlocksDuration: uint64(epochs),
|
||||
DealStartEpoch: abi.ChainEpoch(cctx.Int64("start-epoch")),
|
||||
FastRetrieval: cctx.Bool("fast-retrieval"),
|
||||
VerifiedDeal: verified,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
encoder, err := GetCidEncoder(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Deal (%s) CID: %s\n", maddr, color.GreenString(encoder.Encode(*proposal)))
|
||||
}
|
||||
|
||||
encoder, err := GetCidEncoder(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("\nDeal CID:", color.GreenString(encoder.Encode(*proposal)))
|
||||
return nil
|
||||
default:
|
||||
return xerrors.Errorf("unknown state: %s", state)
|
||||
@@ -944,6 +1104,152 @@ var clientRetrieveCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var clientListAsksCmd = &cli.Command{
|
||||
Name: "list-asks",
|
||||
Usage: "List asks for top miners",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
asks, err := getAsks(ctx, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ask := range asks {
|
||||
fmt.Printf("%s: min:%s max:%s price:%s/GiB/Epoch verifiedPrice:%s/GiB/Epoch\n", ask.Miner,
|
||||
types.SizeStr(types.NewInt(uint64(ask.MinPieceSize))),
|
||||
types.SizeStr(types.NewInt(uint64(ask.MaxPieceSize))),
|
||||
types.FIL(ask.Price),
|
||||
types.FIL(ask.VerifiedPrice),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func getAsks(ctx context.Context, api lapi.FullNode) ([]*storagemarket.StorageAsk, error) {
|
||||
color.Blue(".. getting miner list")
|
||||
miners, err := api.StateListMiners(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting miner list: %w", err)
|
||||
}
|
||||
|
||||
var lk sync.Mutex
|
||||
var found int64
|
||||
var withMinPower []address.Address
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(miners))
|
||||
|
||||
throttle := make(chan struct{}, 50)
|
||||
for _, miner := range miners {
|
||||
throttle <- struct{}{}
|
||||
go func(miner address.Address) {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
<-throttle
|
||||
}()
|
||||
|
||||
power, err := api.StateMinerPower(ctx, miner, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if power.HasMinPower { // TODO: Lower threshold
|
||||
atomic.AddInt64(&found, 1)
|
||||
lk.Lock()
|
||||
withMinPower = append(withMinPower, miner)
|
||||
lk.Unlock()
|
||||
}
|
||||
}(miner)
|
||||
}
|
||||
}()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-time.After(150 * time.Millisecond):
|
||||
fmt.Printf("\r* Found %d miners with power", atomic.LoadInt64(&found))
|
||||
case <-done:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
fmt.Printf("\r* Found %d miners with power\n", atomic.LoadInt64(&found))
|
||||
|
||||
color.Blue(".. querying asks")
|
||||
|
||||
var asks []*storagemarket.StorageAsk
|
||||
var queried, got int64
|
||||
|
||||
done = make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(withMinPower))
|
||||
|
||||
throttle := make(chan struct{}, 50)
|
||||
for _, miner := range withMinPower {
|
||||
throttle <- struct{}{}
|
||||
go func(miner address.Address) {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
<-throttle
|
||||
atomic.AddInt64(&queried, 1)
|
||||
}()
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
||||
defer cancel()
|
||||
|
||||
mi, err := api.StateMinerInfo(ctx, miner, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if mi.PeerId == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ask, err := api.ClientQueryAsk(ctx, *mi.PeerId, miner)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
atomic.AddInt64(&got, 1)
|
||||
lk.Lock()
|
||||
asks = append(asks, ask)
|
||||
lk.Unlock()
|
||||
}(miner)
|
||||
}
|
||||
}()
|
||||
|
||||
loop2:
|
||||
for {
|
||||
select {
|
||||
case <-time.After(150 * time.Millisecond):
|
||||
fmt.Printf("\r* Queried %d asks, got %d responses", atomic.LoadInt64(&queried), atomic.LoadInt64(&got))
|
||||
case <-done:
|
||||
break loop2
|
||||
}
|
||||
}
|
||||
fmt.Printf("\r* Queried %d asks, got %d responses\n", atomic.LoadInt64(&queried), atomic.LoadInt64(&got))
|
||||
|
||||
sort.Slice(asks, func(i, j int) bool {
|
||||
return asks[i].Price.LessThan(asks[j].Price)
|
||||
})
|
||||
|
||||
return asks, nil
|
||||
}
|
||||
|
||||
var clientQueryAskCmd = &cli.Command{
|
||||
Name: "query-ask",
|
||||
Usage: "Find a miners ask",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
@@ -42,6 +43,7 @@ func main() {
|
||||
stateTreePruneCmd,
|
||||
datastoreCmd,
|
||||
ledgerCmd,
|
||||
sectorsCmd,
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
@@ -56,6 +58,13 @@ func main() {
|
||||
Hidden: true,
|
||||
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "miner-repo",
|
||||
Aliases: []string{"storagerepo"},
|
||||
EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusminer", // TODO: Consider XDG_DATA_HOME
|
||||
Usage: fmt.Sprintf("Specify miner repo path. flag storagerepo and env LOTUS_STORAGE_PATH are DEPRECATION, will REMOVE SOON"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Value: "info",
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/go-bitfield"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
miner0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var sectorsCmd = &cli.Command{
|
||||
Name: "sectors",
|
||||
Usage: "Tools for interacting with sectors",
|
||||
Flags: []cli.Flag{},
|
||||
Subcommands: []*cli.Command{
|
||||
terminateSectorCmd,
|
||||
},
|
||||
}
|
||||
|
||||
var terminateSectorCmd = &cli.Command{
|
||||
Name: "terminate",
|
||||
Usage: "Forcefully terminate a sector (WARNING: This means losing power and pay a one-time termination penalty(including collateral) for the terminated sector)",
|
||||
ArgsUsage: "[sectorNum1 sectorNum2 ...]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "really-do-it",
|
||||
Usage: "pass this flag if you know what you are doing",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() < 1 {
|
||||
return fmt.Errorf("at least one sector must be specified")
|
||||
}
|
||||
|
||||
if !cctx.Bool("really-do-it") {
|
||||
return fmt.Errorf("this is a command for advanced users, only use it if you are sure of what you are doing")
|
||||
}
|
||||
|
||||
nodeApi, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
api, acloser, err := lcli.GetStorageMinerAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer acloser()
|
||||
|
||||
ctx := lcli.ReqContext(cctx)
|
||||
|
||||
maddr, err := api.ActorAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mi, err := nodeApi.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
terminationDeclarationParams := []miner0.TerminationDeclaration{}
|
||||
|
||||
for _, sn := range cctx.Args().Slice() {
|
||||
sectorNum, err := strconv.ParseUint(sn, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse sector number: %w", err)
|
||||
}
|
||||
|
||||
sectorbit := bitfield.New()
|
||||
sectorbit.Set(sectorNum)
|
||||
|
||||
loca, err := nodeApi.StateSectorPartition(ctx, maddr, abi.SectorNumber(sectorNum), types.EmptyTSK)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get state sector partition %s", err)
|
||||
}
|
||||
|
||||
para := miner0.TerminationDeclaration{
|
||||
Deadline: loca.Deadline,
|
||||
Partition: loca.Partition,
|
||||
Sectors: sectorbit,
|
||||
}
|
||||
|
||||
terminationDeclarationParams = append(terminationDeclarationParams, para)
|
||||
}
|
||||
|
||||
terminateSectorParams := &miner0.TerminateSectorsParams{
|
||||
Terminations: terminationDeclarationParams,
|
||||
}
|
||||
|
||||
sp, err := actors.SerializeParams(terminateSectorParams)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("serializing params: %w", err)
|
||||
}
|
||||
|
||||
smsg, err := nodeApi.MpoolPushMessage(ctx, &types.Message{
|
||||
From: mi.Owner,
|
||||
To: maddr,
|
||||
Method: builtin.MethodsMiner.TerminateSectors,
|
||||
|
||||
Value: big.Zero(),
|
||||
Params: sp,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("mpool push message: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("sent termination message:", smsg.Cid())
|
||||
|
||||
wait, err := nodeApi.StateWaitMsg(ctx, smsg.Cid(), uint64(cctx.Int("confidence")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("terminate sectors message returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -23,6 +23,7 @@ var ProtocolCodenames = []struct {
|
||||
{build.UpgradeActorsV2Height + 1, "actorsv2"},
|
||||
{build.UpgradeTapeHeight + 1, "tape"},
|
||||
{build.UpgradeLiftoffHeight + 1, "liftoff"},
|
||||
{build.UpgradeKumquatHeight + 1, "postliftoff"},
|
||||
}
|
||||
|
||||
// GetProtocolCodename gets the protocol codename associated with a height.
|
||||
|
||||
@@ -4004,7 +4004,7 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response: `5`
|
||||
Response: `6`
|
||||
|
||||
### StateReadState
|
||||
StateReadState returns the indicated actor's state.
|
||||
|
||||
@@ -11,6 +11,7 @@ require (
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||
github.com/cockroachdb/pebble v0.0.0-20200916222308-4e219a90ba5b
|
||||
github.com/coreos/go-systemd/v22 v22.0.0
|
||||
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
|
||||
@@ -29,17 +30,17 @@ require (
|
||||
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
|
||||
github.com/filecoin-project/go-data-transfer v0.9.0
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
|
||||
github.com/filecoin-project/go-fil-markets v0.9.1
|
||||
github.com/filecoin-project/go-fil-markets v1.0.0
|
||||
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49
|
||||
github.com/filecoin-project/go-multistore v0.0.3
|
||||
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
|
||||
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe
|
||||
github.com/filecoin-project/go-statestore v0.1.0
|
||||
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
|
||||
github.com/filecoin-project/specs-actors v0.9.12
|
||||
github.com/filecoin-project/specs-actors/v2 v2.1.0
|
||||
github.com/filecoin-project/specs-actors/v2 v2.2.0
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.5
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
|
||||
@@ -66,7 +67,7 @@ require (
|
||||
github.com/ipfs/go-ds-pebble v0.0.2-0.20200921225637-ce220f8ac459
|
||||
github.com/ipfs/go-filestore v1.0.0
|
||||
github.com/ipfs/go-fs-lock v0.0.6
|
||||
github.com/ipfs/go-graphsync v0.3.0
|
||||
github.com/ipfs/go-graphsync v0.3.1
|
||||
github.com/ipfs/go-ipfs-blockstore v1.0.1
|
||||
github.com/ipfs/go-ipfs-chunker v0.0.5
|
||||
github.com/ipfs/go-ipfs-ds-help v1.0.0
|
||||
|
||||
@@ -120,8 +120,11 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
@@ -246,8 +249,8 @@ github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl
|
||||
github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
|
||||
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
|
||||
github.com/filecoin-project/go-fil-markets v0.9.1 h1:MgO+UkpreD6x8DV2Zkw2xlBogixfpw9/wf4+nBii7bU=
|
||||
github.com/filecoin-project/go-fil-markets v0.9.1/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM=
|
||||
github.com/filecoin-project/go-fil-markets v1.0.0 h1:np9+tlnWXh9xYG4oZfha6HZFLYOaAZoMGR3V4w6DM48=
|
||||
github.com/filecoin-project/go-fil-markets v1.0.0/go.mod h1:lXExJyYHwpMMddCqhEdNrc7euYJKNkp04K76NZqJLGg=
|
||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
|
||||
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=
|
||||
@@ -266,8 +269,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab h1:cEDC5Ei8UuT99hPWhCjA72SM9AuRtnpvdSTIYbnzN8I=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20200928172055-2df22083d8ab/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b h1:bMUfG6Sy6YSMbsjQAO1Q2vEZldbSdsbRy/FX3OlTck0=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201003010437-c33112184a2b/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f h1:TZDTu4MtBKSFLXWGKLy+cvC3nHfMFIrVgWLAz/+GgZQ=
|
||||
github.com/filecoin-project/go-state-types v0.0.0-20201013222834-41ea465f274f/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe h1:dF8u+LEWeIcTcfUcCf3WFVlc81Fr2JKg8zPzIbBDKDw=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ=
|
||||
@@ -278,8 +281,8 @@ github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07
|
||||
github.com/filecoin-project/specs-actors v0.9.12 h1:iIvk58tuMtmloFNHhAOQHG+4Gci6Lui0n7DYQGi3cJk=
|
||||
github.com/filecoin-project/specs-actors v0.9.12/go.mod h1:TS1AW/7LbG+615j4NsjMK1qlpAwaFsG9w0V2tg2gSao=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.0.1/go.mod h1:v2NZVYinNIKA9acEMBm5wWXxqv5+frFEbekBFemYghY=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT+dGVWJTr5yDevU00g=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.2.0 h1:IyCICb0NHYeD0sdSqjVGwWydn/7r7xXuxdpvGAcRCGY=
|
||||
github.com/filecoin-project/specs-actors/v2 v2.2.0/go.mod h1:rlv5Mx9wUhV8Qsz+vUezZNm+zL4tK08O0HreKKPB2Wc=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
|
||||
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
|
||||
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=
|
||||
@@ -376,6 +379,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -540,6 +545,8 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28
|
||||
github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE=
|
||||
github.com/ipfs/go-graphsync v0.3.0 h1:I6Y20kSuCWkUvPoUWo4V3am704/9QjgDVVkf0zIV8+8=
|
||||
github.com/ipfs/go-graphsync v0.3.0/go.mod h1:gEBvJUNelzMkaRPJTpg/jaKN4AQW/7wDWu0K92D8o10=
|
||||
github.com/ipfs/go-graphsync v0.3.1 h1:dJLYrck4oyJDfMVhGEKiWHxaY8oYMWko4m2Fi+4bofo=
|
||||
github.com/ipfs/go-graphsync v0.3.1/go.mod h1:bw4LiLM5Oq/uLdzEtih9LK8GrwSijv+XqYiWCTxHMqs=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1 h1:0IQdvwnAAUKmDE+PMJa5y1QiwOPHpI9+eAbQEEEYthk=
|
||||
github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk=
|
||||
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
|
||||
@@ -1818,6 +1825,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -50,9 +50,16 @@ type GCLocker = blockstore.GCLocker
|
||||
|
||||
var NewGCLocker = blockstore.NewGCLocker
|
||||
var NewGCBlockstore = blockstore.NewGCBlockstore
|
||||
var DefaultCacheOpts = blockstore.DefaultCacheOpts
|
||||
var ErrNotFound = blockstore.ErrNotFound
|
||||
|
||||
func DefaultCacheOpts() CacheOpts {
|
||||
return CacheOpts{
|
||||
HasBloomFilterSize: 0,
|
||||
HasBloomFilterHashes: 0,
|
||||
HasARCCacheSize: 512 << 10,
|
||||
}
|
||||
}
|
||||
|
||||
func CachedBlockstore(ctx context.Context, bs Blockstore, opts CacheOpts) (Blockstore, error) {
|
||||
bs, err := blockstore.CachedBlockstore(ctx, bs, opts)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user