diff --git a/api/api_full.go b/api/api_full.go index 2e9a8d575..6c70fdda1 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -126,6 +126,8 @@ type FullNode interface { StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) StateMinerFaults(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) + StateMinerInitialPledgeCollateral(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) + StateMinerAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) StatePledgeCollateral(context.Context, types.TipSetKey) (types.BigInt, error) StateWaitMsg(context.Context, cid.Cid) (*MsgLookup, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 66baf0cdb..96116f5cd 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -114,34 +114,36 @@ type FullNodeStruct struct { ClientCalcCommP func(ctx context.Context, inpath string, miner address.Address) (*api.CommPRet, error) `perm:"read"` ClientGenCar func(ctx context.Context, ref api.FileRef, outpath string) error `perm:"write"` - StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` - StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` - StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` - StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` - StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"` - StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) `perm:"read"` - StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"` - StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` - StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` - StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` - StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"` - StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateWaitMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` - StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` - StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"` - StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` - StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"` - StateMarketStorageDeal func(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` - StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) `perm:"read"` - StateAccountKey func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"` - StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"` - StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` - StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"` - StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` - StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` + StateNetworkName func(context.Context) (dtypes.NetworkName, error) `perm:"read"` + StateMinerSectors func(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` + StateMinerProvingSet func(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) `perm:"read"` + StateMinerPower func(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) `perm:"read"` + StateMinerInfo func(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) `perm:"read"` + StateMinerDeadlines func(context.Context, address.Address, types.TipSetKey) (*miner.Deadlines, error) `perm:"read"` + StateMinerFaults func(context.Context, address.Address, types.TipSetKey) ([]abi.SectorNumber, error) `perm:"read"` + StateMinerInitialPledgeCollateral func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateSectorPreCommitInfo func(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` + StateCall func(context.Context, *types.Message, types.TipSetKey) (*api.InvocResult, error) `perm:"read"` + StateReplay func(context.Context, types.TipSetKey, cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateGetActor func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) `perm:"read"` + StateReadState func(context.Context, *types.Actor, types.TipSetKey) (*api.ActorState, error) `perm:"read"` + StatePledgeCollateral func(context.Context, types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateWaitMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` + StateSearchMsg func(context.Context, cid.Cid) (*api.MsgLookup, error) `perm:"read"` + StateListMiners func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListActors func(context.Context, types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateMarketBalance func(context.Context, address.Address, types.TipSetKey) (api.MarketBalance, error) `perm:"read"` + StateMarketParticipants func(context.Context, types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` + StateMarketDeals func(context.Context, types.TipSetKey) (map[string]api.MarketDeal, error) `perm:"read"` + StateMarketStorageDeal func(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` + StateLookupID func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) `perm:"read"` + StateAccountKey func(context.Context, address.Address, types.TipSetKey) (address.Address, error) `perm:"read"` + StateChangedActors func(context.Context, cid.Cid, cid.Cid) (map[string]types.Actor, error) `perm:"read"` + StateGetReceipt func(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` + StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"` + StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"` @@ -514,6 +516,14 @@ func (c *FullNodeStruct) StateMinerFaults(ctx context.Context, actor address.Add return c.Internal.StateMinerFaults(ctx, actor, tsk) } +func (c *FullNodeStruct) StateMinerInitialPledgeCollateral(ctx context.Context, maddr address.Address, snum abi.SectorNumber, tsk types.TipSetKey) (types.BigInt, error) { + return c.Internal.StateMinerInitialPledgeCollateral(ctx, maddr, snum, tsk) +} + +func (c *FullNodeStruct) StateMinerAvailableBalance(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (types.BigInt, error) { + return c.Internal.StateMinerAvailableBalance(ctx, maddr, tsk) +} + func (c *FullNodeStruct) StateSectorPreCommitInfo(ctx context.Context, maddr address.Address, n abi.SectorNumber, tsk types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) { return c.Internal.StateSectorPreCommitInfo(ctx, maddr, n, tsk) } diff --git a/api/test/deals.go b/api/test/deals.go index c10f9d6b0..4056843fd 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -9,7 +9,6 @@ import ( "math/rand" "os" "path/filepath" - "sync/atomic" "testing" "time" @@ -52,8 +51,67 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport } time.Sleep(time.Second) - data := make([]byte, 600) - rand.New(rand.NewSource(5)).Read(data) + mine := true + done := make(chan struct{}) + go func() { + defer close(done) + for mine { + time.Sleep(blocktime) + if err := sn[0].MineOne(ctx, func(bool) {}); err != nil { + t.Error(err) + } + } + }() + + makeDeal(t, ctx, 6, client, miner, carExport) + + mine = false + fmt.Println("shutting down mining") + <-done +} + +func TestDoubleDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration) { + os.Setenv("BELLMAN_NO_GPU", "1") + + ctx := context.Background() + n, sn := b(t, 1, oneMiner) + client := n[0].FullNode.(*impl.FullNodeAPI) + miner := sn[0] + + addrinfo, err := client.NetAddrsListen(ctx) + if err != nil { + t.Fatal(err) + } + + if err := miner.NetConnect(ctx, addrinfo); err != nil { + t.Fatal(err) + } + time.Sleep(time.Second) + + mine := true + done := make(chan struct{}) + + go func() { + defer close(done) + for mine { + time.Sleep(blocktime) + if err := sn[0].MineOne(ctx, func(bool) {}); err != nil { + t.Error(err) + } + } + }() + + makeDeal(t, ctx, 6, client, miner, false) + makeDeal(t, ctx, 7, client, miner, false) + + mine = false + fmt.Println("shutting down mining") + <-done +} + +func makeDeal(t *testing.T, ctx context.Context, rseed int, client *impl.FullNodeAPI, miner TestStorageNode, carExport bool) { + data := make([]byte, 1600) + rand.New(rand.NewSource(int64(rseed))).Read(data) r := bytes.NewReader(data) fcid, err := client.ClientImportLocal(ctx, r) @@ -63,36 +121,18 @@ func TestDealFlow(t *testing.T, b APIBuilder, blocktime time.Duration, carExport fmt.Println("FILE CID: ", fcid) - var mine int32 = 1 - done := make(chan struct{}) - - go func() { - defer close(done) - for atomic.LoadInt32(&mine) == 1 { - time.Sleep(blocktime) - if err := sn[0].MineOne(ctx, func(bool) {}); err != nil { - t.Error(err) - } - } - }() - - deal := startDeal(t, miner, ctx, client, fcid) + deal := startDeal(t, ctx, miner, client, fcid) // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this time.Sleep(time.Second) - waitDealSealed(t, ctx, client, deal) // Retrieval - testRetrieval(t, err, client, ctx, fcid, carExport, data) - - atomic.StoreInt32(&mine, 0) - fmt.Println("shutting down mining") - <-done + testRetrieval(t, ctx, err, client, fcid, carExport, data) } -func startDeal(t *testing.T, miner TestStorageNode, ctx context.Context, client *impl.FullNodeAPI, fcid cid.Cid) *cid.Cid { +func startDeal(t *testing.T, ctx context.Context, miner TestStorageNode, client *impl.FullNodeAPI, fcid cid.Cid) *cid.Cid { maddr, err := miner.ActorAddress(ctx) if err != nil { t.Fatal(err) @@ -102,7 +142,6 @@ func startDeal(t *testing.T, miner TestStorageNode, ctx context.Context, client if err != nil { t.Fatal(err) } - deal, err := client.ClientStartDeal(ctx, &api.StartDealParams{ Data: &storagemarket.DataRef{Root: fcid}, Wallet: addr, @@ -139,7 +178,7 @@ loop: } } -func testRetrieval(t *testing.T, err error, client *impl.FullNodeAPI, ctx context.Context, fcid cid.Cid, carExport bool, data []byte) { +func testRetrieval(t *testing.T, ctx context.Context, err error, client *impl.FullNodeAPI, fcid cid.Cid, carExport bool, data []byte) { offers, err := client.ClientFindData(ctx, fcid) if err != nil { t.Fatal(err) diff --git a/api/test/mining.go b/api/test/mining.go index 4ce7c9ec9..b97c9592a 100644 --- a/api/test/mining.go +++ b/api/test/mining.go @@ -146,7 +146,7 @@ func TestDealMining(t *testing.T, b APIBuilder, blocktime time.Duration, carExpo } }() - deal := startDeal(t, provider, ctx, client, fcid) + deal := startDeal(t, ctx, provider, client, fcid) // TODO: this sleep is only necessary because deals don't immediately get logged in the dealstore, we should fix this time.Sleep(time.Second) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 292f88b4b..e29c2b0e3 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -536,7 +536,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch, return nil, xerrors.Errorf("failed to cbor marshal address: %w") } - electionRand, err := store.DrawRandomness(brand.Data, 17, round, buf.Bytes()) + electionRand, err := store.DrawRandomness(brand.Data, crypto.DomainSeparationTag_ElectionProofProduction, round, buf.Bytes()) if err != nil { return nil, xerrors.Errorf("failed to draw randomness: %w", err) } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index b480259d3..2c54a2939 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -443,7 +443,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, tsk types.TipSetKey } // TODO: use the right dst, also NB: not using any 'entropy' in this call because nicola really didnt want it - prand, err := sm.cs.GetRandomness(ctx, ts.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, round-1, nil) + prand, err := sm.cs.GetRandomness(ctx, ts.Cids(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, round-1, nil) if err != nil { return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err) } diff --git a/chain/sync.go b/chain/sync.go index c6af41842..92df7820f 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -612,7 +612,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } //TODO: DST from spec actors when it is there - vrfBase, err := store.DrawRandomness(rBeacon.Data, 17, h.Height, buf.Bytes()) + vrfBase, err := store.DrawRandomness(rBeacon.Data, crypto.DomainSeparationTag_ElectionProofProduction, h.Height, buf.Bytes()) if err != nil { return xerrors.Errorf("could not draw randomness: %w", err) } @@ -742,7 +742,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block } // TODO: use proper DST - rand, err := syncer.sm.ChainStore().GetRandomness(ctx, curTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, h.Height-1, nil) + rand, err := syncer.sm.ChainStore().GetRandomness(ctx, curTs.Cids(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, h.Height-1, nil) if err != nil { return xerrors.Errorf("failed to get randomness for verifying winningPost proof: %w", err) } diff --git a/cli/client.go b/cli/client.go index 3ed208ea4..e7a5f43bf 100644 --- a/cli/client.go +++ b/cli/client.go @@ -488,9 +488,9 @@ var clientListDeals = &cli.Command{ } w := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0) - fmt.Fprintf(w, "DealCid\tProvider\tState\tPieceCID\tSize\tPrice\tDuration\tMessage\n") + fmt.Fprintf(w, "DealCid\tDealId\tProvider\tState\tPieceCID\tSize\tPrice\tDuration\tMessage\n") for _, d := range deals { - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d\t%s\t%d\t%s\n", d.ProposalCid, d.Provider, storagemarket.DealStates[d.State], d.PieceCID, d.Size, d.PricePerEpoch, d.Duration, d.Message) + fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%d\t%s\t%d\t%s\n", d.ProposalCid, d.DealID, d.Provider, storagemarket.DealStates[d.State], d.PieceCID, d.Size, d.PricePerEpoch, d.Duration, d.Message) } return w.Flush() }, diff --git a/cli/send.go b/cli/send.go index f26df3785..f43e90c36 100644 --- a/cli/send.go +++ b/cli/send.go @@ -92,11 +92,13 @@ var sendCmd = &cli.Command{ if err != nil { return err } + fmt.Println(sm.Cid()) } else { - _, err = api.MpoolPushMessage(ctx, msg) + sm, err := api.MpoolPushMessage(ctx, msg) if err != nil { return err } + fmt.Println(sm.Cid()) } return nil diff --git a/cmd/lotus-chainwatch/storage.go b/cmd/lotus-chainwatch/storage.go index e2e6ecf82..059fd0ed8 100644 --- a/cmd/lotus-chainwatch/storage.go +++ b/cmd/lotus-chainwatch/storage.go @@ -70,7 +70,7 @@ create table if not exists blocks miner text not null, timestamp bigint not null, vrfproof bytea, - eprof bytea, + eprof bytea ); create unique index if not exists block_cid_uindex diff --git a/cmd/lotus-fountain/main.go b/cmd/lotus-fountain/main.go index f84a490a2..2c4b7dfe0 100644 --- a/cmd/lotus-fountain/main.go +++ b/cmd/lotus-fountain/main.go @@ -30,7 +30,7 @@ import ( var log = logging.Logger("main") -var sendPerRequest, _ = types.ParseFIL("0.005") +var sendPerRequest, _ = types.ParseFIL("50") func main() { logging.SetLogLevel("*", "INFO") @@ -277,7 +277,7 @@ func (h *handler) mkminer(w http.ResponseWriter, r *http.Request) { Owner: owner, Worker: owner, SectorSize: abi.SectorSize(ssize), - Peer: peer.ID("SETME"), + Peer: peer.ID("12D3KooWJpBNhwgvoZ15EB1JwRTRpxgM9D2fwq6eEktrJJG74aP6"), }) if err != nil { w.WriteHeader(400) diff --git a/cmd/lotus-seed/genesis.go b/cmd/lotus-seed/genesis.go index 187f5b499..3dc6e15d2 100644 --- a/cmd/lotus-seed/genesis.go +++ b/cmd/lotus-seed/genesis.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/specs-actors/actors/abi/big" + "github.com/filecoin-project/lotus/build" genesis2 "github.com/filecoin-project/lotus/chain/gen/genesis" "github.com/filecoin-project/lotus/genesis" ) @@ -123,7 +124,7 @@ var genesisAddMinerCmd = &cli.Command{ log.Infof("Giving %s some initial balance", miner.Owner) template.Accounts = append(template.Accounts, genesis.Actor{ Type: genesis.TAccount, - Balance: big.NewInt(100000000000000), + Balance: big.Mul(big.NewInt(50_000_000), big.NewInt(build.FilecoinPrecision)), Meta: (&genesis.AccountMeta{Owner: miner.Owner}).ActorMeta(), }) } diff --git a/cmd/lotus-storage-miner/rewards.go b/cmd/lotus-storage-miner/rewards.go index 2fac099d4..68b7ab9d9 100644 --- a/cmd/lotus-storage-miner/rewards.go +++ b/cmd/lotus-storage-miner/rewards.go @@ -22,6 +22,13 @@ var rewardsCmd = &cli.Command{ var rewardsRedeemCmd = &cli.Command{ Name: "redeem", Usage: "Redeem block rewards", + Flags: []cli.Flag{ + &cli.Int64Flag{ + Name: "gas-limit", + Usage: "set gas limit", + Value: 100000, + }, + }, Action: func(cctx *cli.Context) error { nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) if err != nil { @@ -59,12 +66,14 @@ var rewardsRedeemCmd = &cli.Command{ return err } + gasLimit := cctx.Int64("gas-limit") + smsg, err := api.MpoolPushMessage(ctx, &types.Message{ To: maddr, From: mi.Owner, Value: types.NewInt(0), GasPrice: types.NewInt(1), - GasLimit: 100000, + GasLimit: gasLimit, Method: builtin.MethodsMiner.WithdrawBalance, Params: params, }) diff --git a/go.mod b/go.mod index 08bcf52e5..025a9b60e 100644 --- a/go.mod +++ b/go.mod @@ -19,14 +19,14 @@ require ( github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-data-transfer v0.0.0-20200408061858-82c58b423ca6 github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5 - github.com/filecoin-project/go-fil-markets v0.0.0-20200413201123-731e6ca89984 + github.com/filecoin-project/go-fil-markets v0.0.0-20200415011556-4378bd41b91f github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 github.com/filecoin-project/go-paramfetch v0.0.2-0.20200218225740-47c639bab663 github.com/filecoin-project/go-statestore v0.1.0 github.com/filecoin-project/sector-storage v0.0.0-20200417225459-e75536581a08 - github.com/filecoin-project/specs-actors v0.0.0-20200421235624-312ac81e2aa4 + github.com/filecoin-project/specs-actors v1.0.0 github.com/filecoin-project/specs-storage v0.0.0-20200417134612-61b2d91a6102 - github.com/filecoin-project/storage-fsm v0.0.0-20200420183220-1515cffb5d13 + github.com/filecoin-project/storage-fsm v0.0.0-20200423114251-f3bea4aa8bd7 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.4 diff --git a/go.sum b/go.sum index e7b244667..8ba07ff61 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,6 @@ github.com/filecoin-project/go-amt-ipld/v2 v2.0.0/go.mod h1:PAZ5tvSfMfWE327osqFX github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200131012142-05d80eeccc5e h1:IOoff6yAZSJ5zHCPY2jzGNwQYQU6ygsRVe/cSnJrY+o= github.com/filecoin-project/go-amt-ipld/v2 v2.0.1-0.20200131012142-05d80eeccc5e/go.mod h1:boRtQhzmxNocrMxOXo1NYn4oUc1NGvR8tEa79wApNXg= github.com/filecoin-project/go-bitfield v0.0.0-20200309034705-8c7ac40bd550/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw= -github.com/filecoin-project/go-bitfield v0.0.0-20200415174627-536a2ee8529d h1:ufxUB1ssNdti7SgDNnHXZ863F8g04/yx+EW4ygvGcSU= -github.com/filecoin-project/go-bitfield v0.0.0-20200415174627-536a2ee8529d/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw= github.com/filecoin-project/go-bitfield v0.0.0-20200416002808-b3ee67ec9060 h1:/3qjGMn6ukXgZJHsIbuwGL7ipla8DOV3uHZDBJkBYfU= github.com/filecoin-project/go-bitfield v0.0.0-20200416002808-b3ee67ec9060/go.mod h1:iodsLxOFZnqKtjj2zkgqzoGNrv6vUqj69AT/J8DKXEw= github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 h1:av5fw6wmm58FYMgJeoB/lK9XXrgdugYiTqkdxjTy9k8= @@ -149,8 +147,8 @@ github.com/filecoin-project/go-data-transfer v0.0.0-20200408061858-82c58b423ca6/ github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5 h1:yvQJCW9mmi9zy+51xA01Ea2X7/dL7r8eKDPuGUjRmbo= github.com/filecoin-project/go-fil-commcid v0.0.0-20200208005934-2b8bd03caca5/go.mod h1:JbkIgFF/Z9BDlvrJO1FuKkaWsH673/UdFaiVS6uIHlA= github.com/filecoin-project/go-fil-markets v0.0.0-20200114015428-74d100f305f8/go.mod h1:c8NTjvFVy1Ud02mmGDjOiMeawY2t6ALfrrdvAB01FQc= -github.com/filecoin-project/go-fil-markets v0.0.0-20200413201123-731e6ca89984 h1:QY5jgd5T4txUEC2k9BPqWRlhDUTdFx5f1z/StOlh92g= -github.com/filecoin-project/go-fil-markets v0.0.0-20200413201123-731e6ca89984/go.mod h1:vcX3y5FVyuclIZgogPG1uIvJxHLSBU54B1ANJ88uMNk= +github.com/filecoin-project/go-fil-markets v0.0.0-20200415011556-4378bd41b91f h1:mPmWWrEwc/5zZW2E14m8a7HMrrOWREaflGZL1Iun/Aw= +github.com/filecoin-project/go-fil-markets v0.0.0-20200415011556-4378bd41b91f/go.mod h1:vcX3y5FVyuclIZgogPG1uIvJxHLSBU54B1ANJ88uMNk= github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6 h1:92PET+sx1Hb4W/8CgFwGuxaKbttwY+UNspYZTvXY0vs= github.com/filecoin-project/go-padreader v0.0.0-20200210211231-548257017ca6/go.mod h1:0HgYnrkeSU4lu1p+LEOeDpFsNBssa0OGGriWdA4hvaE= github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878/go.mod h1:40kI2Gv16mwcRsHptI3OAV4nlOEU7wVDc4RgMylNFjU= @@ -170,17 +168,14 @@ github.com/filecoin-project/sector-storage v0.0.0-20200417225459-e75536581a08 h1 github.com/filecoin-project/sector-storage v0.0.0-20200417225459-e75536581a08/go.mod h1:m5wM3aqbgDcg+mT2EW0Urv7t/sCok9TmvQqtb7Sf738= github.com/filecoin-project/specs-actors v0.0.0-20200210130641-2d1fbd8672cf/go.mod h1:xtDZUB6pe4Pksa/bAJbJ693OilaC5Wbot9jMhLm3cZA= github.com/filecoin-project/specs-actors v0.0.0-20200409043918-e569f4a2f504/go.mod h1:mdJraXq5vMy0+/FqVQIrnNlpQ/Em6zeu06G/ltQ0/lA= -github.com/filecoin-project/specs-actors v0.0.0-20200415170224-54c7b2a42e71/go.mod h1:M2HNOBpYbgXl/V4GmJFOsY7lQNuAmOtrCQMa6Yfpfrc= -github.com/filecoin-project/specs-actors v0.0.0-20200421160610-702cd4b229c4 h1:RUj2hy/fN+l7VRT0uy034vDA/DEG7rd3+D/wVeVqSoM= -github.com/filecoin-project/specs-actors v0.0.0-20200421160610-702cd4b229c4/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= -github.com/filecoin-project/specs-actors v0.0.0-20200421235624-312ac81e2aa4 h1:zljJmKrvksZTWGBkMPNJJFl030ZRahq01FG05npKYxE= -github.com/filecoin-project/specs-actors v0.0.0-20200421235624-312ac81e2aa4/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= +github.com/filecoin-project/specs-actors v1.0.0 h1:H0G6n2R8MnfvYuI0irmY7Bj5FI/JHUxnIldg/YX472I= +github.com/filecoin-project/specs-actors v1.0.0/go.mod h1:nQYnFbQ7Y0bHZyq6HDEuVlCPR+U3z5Q3wMOQ+2aiV+Y= github.com/filecoin-project/specs-storage v0.0.0-20200410185809-9fbaaa08f275 h1:6OTcpsTQBQM0f/A67oEi4E4YtYd6fzkMqbU8cPIWMMs= github.com/filecoin-project/specs-storage v0.0.0-20200410185809-9fbaaa08f275/go.mod h1:xJ1/xl9+8zZeSSSFmDC3Wr6uusCTxyYPI0VeNVSFmPE= github.com/filecoin-project/specs-storage v0.0.0-20200417134612-61b2d91a6102 h1:T3f/zkuvgtgqcXrb0NO3BicuveGOxxUAMPa/Yif2kuE= github.com/filecoin-project/specs-storage v0.0.0-20200417134612-61b2d91a6102/go.mod h1:xJ1/xl9+8zZeSSSFmDC3Wr6uusCTxyYPI0VeNVSFmPE= -github.com/filecoin-project/storage-fsm v0.0.0-20200420183220-1515cffb5d13 h1:Zv0ovLy4nOgMk9bCKOp+Wo6NMSSeuNgPNk0N3aLf5Wg= -github.com/filecoin-project/storage-fsm v0.0.0-20200420183220-1515cffb5d13/go.mod h1:mJtW2Y2qIbZErBoc1MmgVKMFiNHWZ2qqeH6Hl3fHFWU= +github.com/filecoin-project/storage-fsm v0.0.0-20200423114251-f3bea4aa8bd7 h1:o9eAbR2GZiCn32AKYBVAasL3NJCHVrGPdxPozr0l0mM= +github.com/filecoin-project/storage-fsm v0.0.0-20200423114251-f3bea4aa8bd7/go.mod h1:kS9btPajAeZkv0pS6cBLxdCCr9SyQ0VdGoXrXT0/hDs= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 h1:EzDjxMg43q1tA2c0MV3tNbaontnHLplHyFF6M5KiVP0= diff --git a/markets/retrievaladapter/client.go b/markets/retrievaladapter/client.go index 39fae18b6..dcd42d414 100644 --- a/markets/retrievaladapter/client.go +++ b/markets/retrievaladapter/client.go @@ -1,13 +1,18 @@ package retrievaladapter import ( + "bytes" "context" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/shared" "github.com/filecoin-project/specs-actors/actors/abi" + initactor "github.com/filecoin-project/specs-actors/actors/builtin/init" "github.com/filecoin-project/specs-actors/actors/builtin/paych" + "github.com/filecoin-project/specs-actors/actors/runtime/exitcode" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/node/impl/full" payapi "github.com/filecoin-project/lotus/node/impl/paych" @@ -29,11 +34,10 @@ func NewRetrievalClientNode(pmgr *paychmgr.Manager, payapi payapi.PaychAPI, chai // GetOrCreatePaymentChannel sets up a new payment channel if one does not exist // between a client and a miner and ensures the client has the given amount of // funds available in the channel. -func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable abi.TokenAmount, tok shared.TipSetToken) (address.Address, error) { +func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, clientAddress address.Address, minerAddress address.Address, clientFundsAvailable abi.TokenAmount, tok shared.TipSetToken) (address.Address, cid.Cid, error) { // TODO: respect the provided TipSetToken (a serialized TipSetKey) when // querying the chain - paych, _, err := rcn.pmgr.GetPaych(ctx, clientAddress, minerAddress, clientFundsAvailable) - return paych, err + return rcn.pmgr.GetPaych(ctx, clientAddress, minerAddress, clientFundsAvailable) } // Allocate late creates a lane within a payment channel so that calls to @@ -64,3 +68,33 @@ func (rcn *retrievalClientNode) GetChainHead(ctx context.Context) (shared.TipSet return head.Key().Bytes(), head.Height(), nil } + +// WaitForPaymentChannelAddFunds waits messageCID to appear on chain. If it doesn't appear within +// defaultMsgWaitTimeout it returns error +func (rcn *retrievalClientNode) WaitForPaymentChannelAddFunds(messageCID cid.Cid) error { + _, mr, err := rcn.chainapi.StateManager.WaitForMessage(context.TODO(), messageCID) + + if err != nil { + return err + } + if mr.ExitCode != exitcode.Ok { + return xerrors.Errorf("wait for payment channel to add funds failed. exit code: %d", mr.ExitCode) + } + return nil +} + +func (rcn *retrievalClientNode) WaitForPaymentChannelCreation(messageCID cid.Cid) (address.Address, error) { + _, mr, err := rcn.chainapi.StateManager.WaitForMessage(context.TODO(), messageCID) + + if err != nil { + return address.Undef, err + } + if mr.ExitCode != exitcode.Ok { + return address.Undef, xerrors.Errorf("payment channel creation failed. exit code: %d", mr.ExitCode) + } + var retval initactor.ExecReturn + if err := retval.UnmarshalCBOR(bytes.NewReader(mr.Return)); err != nil { + return address.Undef, err + } + return retval.RobustAddress, nil +} diff --git a/miner/miner.go b/miner/miner.go index a9036f530..594106b98 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -348,8 +348,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return nil, nil } - // TODO: use the right dst, also NB: not using any 'entropy' in this call because nicola really didnt want it - rand, err := m.api.ChainGetRandomness(ctx, base.TipSet.Key(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, base.TipSet.Height()+base.NullRounds, nil) + rand, err := m.api.ChainGetRandomness(ctx, base.TipSet.Key(), crypto.DomainSeparationTag_WinningPoStChallengeSeed, base.TipSet.Height()+base.NullRounds, nil) if err != nil { return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err) } diff --git a/node/builder.go b/node/builder.go index ad9eb479b..195e1affd 100644 --- a/node/builder.go +++ b/node/builder.go @@ -280,7 +280,6 @@ func Online() Option { Override(new(storage2.Prover), From(new(sectorstorage.SectorManager))), Override(new(*sectorblocks.SectorBlocks), sectorblocks.NewSectorBlocks), - Override(new(sealing.TicketFn), modules.SealTicketGen), Override(new(*storage.Miner), modules.StorageMiner), Override(new(dtypes.NetworkName), modules.StorageNetworkName), Override(new(beacon.RandomBeacon), modules.MinerRandomBeacon), diff --git a/node/impl/full/state.go b/node/impl/full/state.go index acb5db129..04902978b 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" @@ -32,6 +33,7 @@ import ( "github.com/filecoin-project/specs-actors/actors/builtin/market" "github.com/filecoin-project/specs-actors/actors/builtin/miner" samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + "github.com/filecoin-project/specs-actors/actors/builtin/power" ) type StateAPI struct { @@ -604,3 +606,126 @@ func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Add minBalance = types.BigMul(minBalance, types.NewInt(uint64(offset))) return types.BigSub(act.Balance, minBalance), nil } + +func (a *StateAPI) StateMinerInitialPledgeCollateral(ctx context.Context, maddr address.Address, snum abi.SectorNumber, tsk types.TipSetKey) (types.BigInt, error) { + ts, err := a.Chain.GetTipSetFromKey(tsk) + if err != nil { + return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + + act, err := a.StateManager.GetActor(maddr, ts) + if err != nil { + return types.EmptyInt, err + } + + as := store.ActorStore(ctx, a.Chain.Blockstore()) + + var st miner.State + if err := as.Get(ctx, act.Head, &st); err != nil { + return types.EmptyInt, err + } + + precommit, found, err := st.GetPrecommittedSector(as, snum) + if err != nil { + return types.EmptyInt, err + } + + if !found { + return types.EmptyInt, xerrors.Errorf("no precommit found for sector %d", snum) + } + + var dealWeights market.VerifyDealsOnSectorProveCommitReturn + { + var err error + params, err := actors.SerializeParams(&market.VerifyDealsOnSectorProveCommitParams{ + DealIDs: precommit.Info.DealIDs, + SectorSize: st.GetSectorSize(), + SectorExpiry: precommit.Info.Expiration, + }) + if err != nil { + return types.EmptyInt, err + } + + ret, err := a.StateManager.Call(ctx, &types.Message{ + From: maddr, + To: builtin.StorageMarketActorAddr, + Method: builtin.MethodsMarket.VerifyDealsOnSectorProveCommit, + GasLimit: 100000000000, + GasPrice: types.NewInt(0), + Params: params, + }, ts) + if err != nil { + return types.EmptyInt, err + } + + if err := dealWeights.UnmarshalCBOR(bytes.NewReader(ret.MsgRct.Return)); err != nil { + return types.BigInt{}, err + } + } + + initialPledge := big.Zero() + { + ssize, err := precommit.Info.RegisteredProof.SectorSize() + if err != nil { + return types.EmptyInt, err + } + + params, err := actors.SerializeParams(&power.OnSectorProveCommitParams{ + Weight: power.SectorStorageWeightDesc{ + SectorSize: ssize, + Duration: precommit.Info.Expiration - ts.Height(), // NB: not exactly accurate, but should always lead us to *over* estimate, not under + DealWeight: dealWeights.DealWeight, + VerifiedDealWeight: dealWeights.VerifiedDealWeight, + }, + }) + if err != nil { + return types.EmptyInt, err + } + + ret, err := a.StateManager.Call(ctx, &types.Message{ + From: maddr, + To: builtin.StoragePowerActorAddr, + Method: builtin.MethodsPower.OnSectorProveCommit, + GasLimit: 10000000000, + GasPrice: types.NewInt(0), + Params: params, + }, ts) + if err != nil { + return types.EmptyInt, err + } + + if err := initialPledge.UnmarshalCBOR(bytes.NewReader(ret.MsgRct.Return)); err != nil { + return types.BigInt{}, err + } + } + + return initialPledge, nil +} + +func (a *StateAPI) StateMinerAvailableBalance(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (types.BigInt, error) { + ts, err := a.Chain.GetTipSetFromKey(tsk) + if err != nil { + return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err) + } + + act, err := a.StateManager.GetActor(maddr, ts) + if err != nil { + return types.EmptyInt, err + } + + as := store.ActorStore(ctx, a.Chain.Blockstore()) + + var st miner.State + if err := as.Get(ctx, act.Head, &st); err != nil { + return types.EmptyInt, err + } + + // TODO: !!!! Use method that doesnt trigger additional state mutations, this is going to cause lots of objects to be created and written to disk + log.Warnf("calling inefficient unlock vested funds method, fixme") + vested, err := st.UnlockVestedFunds(as, ts.Height()) + if err != nil { + return types.EmptyInt, err + } + + return types.BigAdd(st.GetAvailableBalance(act.Balance), vested), nil +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 04281e913..e23a576cc 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -1,7 +1,6 @@ package modules import ( - "bytes" "context" "net/http" "reflect" @@ -35,12 +34,6 @@ import ( "github.com/filecoin-project/go-fil-markets/storedcounter" paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-statestore" - sectorstorage "github.com/filecoin-project/sector-storage" - "github.com/filecoin-project/sector-storage/ffiwrapper" - "github.com/filecoin-project/sector-storage/stores" - "github.com/filecoin-project/specs-actors/actors/abi" - "github.com/filecoin-project/specs-actors/actors/crypto" - lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/beacon" @@ -53,6 +46,10 @@ import ( "github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/storage" + sectorstorage "github.com/filecoin-project/sector-storage" + "github.com/filecoin-project/sector-storage/ffiwrapper" + "github.com/filecoin-project/sector-storage/stores" + "github.com/filecoin-project/specs-actors/actors/abi" sealing "github.com/filecoin-project/storage-fsm" ) @@ -124,7 +121,7 @@ func SectorIDCounter(ds dtypes.MetadataDS) sealing.SectorIDCounter { return &sidsc{sc} } -func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h host.Host, ds dtypes.MetadataDS, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, tktFn sealing.TicketFn) (*storage.Miner, error) { +func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h host.Host, ds dtypes.MetadataDS, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier) (*storage.Miner, error) { maddr, err := minerAddrFromDS(ds) if err != nil { return nil, err @@ -147,7 +144,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api lapi.FullNode, h return nil, err } - sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif, tktFn) + sm, err := storage.NewMiner(api, maddr, worker, h, ds, sealer, sc, verif) if err != nil { return nil, err } @@ -283,37 +280,6 @@ func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api lapi.FullNode return m, nil } -func SealTicketGen(fapi lapi.FullNode, ds dtypes.MetadataDS) (sealing.TicketFn, error) { - minerAddr, err := minerAddrFromDS(ds) - if err != nil { - return nil, err - } - - entropy := new(bytes.Buffer) - if err := minerAddr.MarshalCBOR(entropy); err != nil { - return nil, err - } - - return func(ctx context.Context, tok sealing.TipSetToken) (abi.SealRandomness, abi.ChainEpoch, error) { - tsk, err := types.TipSetKeyFromBytes(tok) - if err != nil { - return nil, 0, xerrors.Errorf("could not unmarshal TipSetToken to TipSetKey: %w", err) - } - - ts, err := fapi.ChainGetTipSet(ctx, tsk) - if err != nil { - return nil, 0, xerrors.Errorf("getting TipSet for key failed: %w", err) - } - - r, err := fapi.ChainGetRandomness(ctx, ts.Key(), crypto.DomainSeparationTag_SealRandomness, ts.Height()-build.SealRandomnessLookback, entropy.Bytes()) - if err != nil { - return nil, 0, xerrors.Errorf("getting randomness for SealTicket failed: %w", err) - } - - return abi.SealRandomness(r), ts.Height() - build.SealRandomnessLookback, nil - }, nil -} - func NewProviderRequestValidator(deals dtypes.ProviderDealStore) *requestvalidation.ProviderRequestValidator { return requestvalidation.NewProviderRequestValidator(deals) } diff --git a/node/node_test.go b/node/node_test.go index 361597d4a..d1f0621fc 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -195,7 +195,7 @@ func builder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test.TestN genaccs = append(genaccs, genesis.Actor{ Type: genesis.TAccount, - Balance: big.NewInt(40000000000), + Balance: big.NewInt(5000000000000000000), Meta: (&genesis.AccountMeta{Owner: wk.Address}).ActorMeta(), }) @@ -331,7 +331,7 @@ func mockSbBuilder(t *testing.T, nFull int, storage []test.StorageMiner) ([]test genaccs = append(genaccs, genesis.Actor{ Type: genesis.TAccount, - Balance: big.NewInt(40000000000), + Balance: big.NewInt(5000000000000000000), Meta: (&genesis.AccountMeta{Owner: wk.Address}).ActorMeta(), }) @@ -453,11 +453,15 @@ func TestAPIDealFlow(t *testing.T) { logging.SetLogLevel("sub", "ERROR") logging.SetLogLevel("storageminer", "ERROR") - test.TestDealFlow(t, mockSbBuilder, 10*time.Millisecond, false) - + t.Run("TestDealFlow", func(t *testing.T) { + test.TestDealFlow(t, mockSbBuilder, 10*time.Millisecond, false) + }) t.Run("WithExportedCAR", func(t *testing.T) { test.TestDealFlow(t, mockSbBuilder, 10*time.Millisecond, true) }) + t.Run("TestDoubleDealFlow", func(t *testing.T) { + test.TestDoubleDealFlow(t, mockSbBuilder, 10*time.Millisecond) + }) } func TestAPIDealFlowReal(t *testing.T) { diff --git a/paychmgr/simple.go b/paychmgr/simple.go index 653f58491..ff537d425 100644 --- a/paychmgr/simple.go +++ b/paychmgr/simple.go @@ -3,7 +3,6 @@ package paychmgr import ( "bytes" "context" - "fmt" "github.com/filecoin-project/specs-actors/actors/builtin" init_ "github.com/filecoin-project/specs-actors/actors/builtin/init" @@ -17,10 +16,10 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, amt types.BigInt) (address.Address, cid.Cid, error) { +func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, amt types.BigInt) (cid.Cid, error) { params, aerr := actors.SerializeParams(&paych.ConstructorParams{From: from, To: to}) if aerr != nil { - return address.Undef, cid.Undef, aerr + return cid.Undef, aerr } enc, aerr := actors.SerializeParams(&init_.ExecParams{ @@ -28,7 +27,7 @@ func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, am ConstructorParams: params, }) if aerr != nil { - return address.Undef, cid.Undef, aerr + return cid.Undef, aerr } msg := &types.Message{ @@ -43,42 +42,46 @@ func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, am smsg, err := pm.mpool.MpoolPushMessage(ctx, msg) if err != nil { - return address.Undef, cid.Undef, xerrors.Errorf("initializing paych actor: %w", err) + return cid.Undef, xerrors.Errorf("initializing paych actor: %w", err) } - mcid := smsg.Cid() + go pm.waitForPaychCreateMsg(ctx, mcid) + return mcid, nil +} - // TODO: wait outside the store lock! - // (tricky because we need to setup channel tracking before we know it's address) +// WaitForPaychCreateMsg waits for mcid to appear on chain and returns the robust address of the +// created payment channel +// TODO: wait outside the store lock! +// (tricky because we need to setup channel tracking before we know its address) +func (pm *Manager) waitForPaychCreateMsg(ctx context.Context, mcid cid.Cid) { + defer pm.store.lk.Unlock() mwait, err := pm.state.StateWaitMsg(ctx, mcid) if err != nil { - return address.Undef, cid.Undef, xerrors.Errorf("wait msg: %w", err) + log.Errorf("wait msg: %w", err) } if mwait.Receipt.ExitCode != 0 { - return address.Undef, cid.Undef, fmt.Errorf("payment channel creation failed (exit code %d)", mwait.Receipt.ExitCode) + log.Errorf("payment channel creation failed (exit code %d)", mwait.Receipt.ExitCode) } var decodedReturn init_.ExecReturn err = decodedReturn.UnmarshalCBOR(bytes.NewReader(mwait.Receipt.Return)) if err != nil { - return address.Undef, cid.Undef, err + log.Error(err) } paychaddr := decodedReturn.RobustAddress ci, err := pm.loadOutboundChannelInfo(ctx, paychaddr) if err != nil { - return address.Undef, cid.Undef, xerrors.Errorf("loading channel info: %w", err) + log.Errorf("loading channel info: %w", err) } if err := pm.store.trackChannel(ci); err != nil { - return address.Undef, cid.Undef, xerrors.Errorf("tracking channel: %w", err) + log.Errorf("tracking channel: %w", err) } - - return paychaddr, mcid, nil } -func (pm *Manager) addFunds(ctx context.Context, ch address.Address, from address.Address, amt types.BigInt) error { +func (pm *Manager) addFunds(ctx context.Context, ch address.Address, from address.Address, amt types.BigInt) (cid.Cid, error) { msg := &types.Message{ To: ch, From: from, @@ -90,25 +93,31 @@ func (pm *Manager) addFunds(ctx context.Context, ch address.Address, from addres smsg, err := pm.mpool.MpoolPushMessage(ctx, msg) if err != nil { - return err + return cid.Undef, err } + mcid := smsg.Cid() + go pm.waitForAddFundsMsg(ctx, mcid) + return mcid, nil +} - mwait, err := pm.state.StateWaitMsg(ctx, smsg.Cid()) // TODO: wait outside the store lock! +// WaitForAddFundsMsg waits for mcid to appear on chain and returns error, if any +// TODO: wait outside the store lock! +// (tricky because we need to setup channel tracking before we know it's address) +func (pm *Manager) waitForAddFundsMsg(ctx context.Context, mcid cid.Cid) { + defer pm.store.lk.Unlock() + mwait, err := pm.state.StateWaitMsg(ctx, mcid) if err != nil { - return err + log.Error(err) } if mwait.Receipt.ExitCode != 0 { - return fmt.Errorf("voucher channel creation failed: adding funds (exit code %d)", mwait.Receipt.ExitCode) + log.Errorf("voucher channel creation failed: adding funds (exit code %d)", mwait.Receipt.ExitCode) } - - return nil } func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, ensureFree types.BigInt) (address.Address, cid.Cid, error) { - pm.store.lk.Lock() - defer pm.store.lk.Unlock() - + pm.store.lk.Lock() // unlock only on err; wait funcs will defer unlock + var mcid cid.Cid ch, err := pm.store.findChan(func(ci *ChannelInfo) bool { if ci.Direction != DirOutbound { return false @@ -116,12 +125,17 @@ func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, ensur return ci.Control == from && ci.Target == to }) if err != nil { + pm.store.lk.Unlock() return address.Undef, cid.Undef, xerrors.Errorf("findChan: %w", err) } if ch != address.Undef { // TODO: Track available funds - return ch, cid.Undef, pm.addFunds(ctx, ch, from, ensureFree) + mcid, err = pm.addFunds(ctx, ch, from, ensureFree) + } else { + mcid, err = pm.createPaych(ctx, from, to, ensureFree) } - - return pm.createPaych(ctx, from, to, ensureFree) + if err != nil { + pm.store.lk.Unlock() + } + return ch, mcid, err } diff --git a/scripts/deploy-node.sh b/scripts/deploy-node.sh index 4fc3d9aff..57856f945 100755 --- a/scripts/deploy-node.sh +++ b/scripts/deploy-node.sh @@ -10,7 +10,7 @@ HOST=$1 # TODO: destroy FILES_TO_SEND=( - ./louts + ./lotus ./lotus-storage-miner scripts/lotus-daemon.service scripts/louts-miner.service @@ -26,7 +26,7 @@ systemctl stop lotus-daemon mkdir -p .lotus .lotusstorage cd "$HOME/lotus-stage/" -cp -f louts lotus-storage-miner /usr/local/bin +cp -f lotus lotus-storage-miner /usr/local/bin cp -f lotus-daemon.service /etc/systemd/system/lotus-daemon.service cp -f lotus-miner.service /etc/systemd/system/lotus-storage-miner.service diff --git a/storage/adapter_storage_miner.go b/storage/adapter_storage_miner.go index e8d0e090d..61572143b 100644 --- a/storage/adapter_storage_miner.go +++ b/storage/adapter_storage_miner.go @@ -48,6 +48,15 @@ func (s SealingAPIAdapter) StateMinerSectorSize(ctx context.Context, maddr addre return mi.SectorSize, nil } +func (s SealingAPIAdapter) StateMinerInitialPledgeCollateral(ctx context.Context, a address.Address, n abi.SectorNumber, tok sealing.TipSetToken) (big.Int, error) { + tsk, err := types.TipSetKeyFromBytes(tok) + if err != nil { + return big.Zero(), xerrors.Errorf("failed to unmarshal TipSetToken to TipSetKey: %w", err) + } + + return s.delegate.StateMinerInitialPledgeCollateral(ctx, a, n, tsk) +} + func (s SealingAPIAdapter) StateMinerWorkerAddress(ctx context.Context, maddr address.Address, tok sealing.TipSetToken) (address.Address, error) { tsk, err := types.TipSetKeyFromBytes(tok) if err != nil { diff --git a/storage/miner.go b/storage/miner.go index 4248529fe..78f88d797 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -36,7 +36,6 @@ type Miner struct { h host.Host sealer sectorstorage.SectorManager ds datastore.Batching - tktFn sealing.TicketFn sc sealing.SectorIDCounter verif ffiwrapper.Verifier @@ -53,6 +52,7 @@ type storageMinerApi interface { StateMinerSectors(context.Context, address.Address, *abi.BitField, bool, types.TipSetKey) ([]*api.ChainSectorInfo, error) StateSectorPreCommitInfo(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) StateMinerInfo(context.Context, address.Address, types.TipSetKey) (miner.MinerInfo, error) + StateMinerInitialPledgeCollateral(context.Context, address.Address, abi.SectorNumber, types.TipSetKey) (types.BigInt, error) StateWaitMsg(context.Context, cid.Cid) (*api.MsgLookup, error) // TODO: removeme eventually StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error) StateGetReceipt(context.Context, cid.Cid, types.TipSetKey) (*types.MessageReceipt, error) @@ -74,13 +74,12 @@ type storageMinerApi interface { WalletHas(context.Context, address.Address) (bool, error) } -func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier, tktFn sealing.TicketFn) (*Miner, error) { +func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sealer sectorstorage.SectorManager, sc sealing.SectorIDCounter, verif ffiwrapper.Verifier) (*Miner, error) { m := &Miner{ api: api, h: h, sealer: sealer, ds: ds, - tktFn: tktFn, sc: sc, verif: verif, @@ -104,7 +103,7 @@ func (m *Miner) Run(ctx context.Context) error { evts := events.NewEvents(ctx, m.api) adaptedAPI := NewSealingAPIAdapter(m.api) pcp := sealing.NewBasicPreCommitPolicy(adaptedAPI, 10000000, mi.ProvingPeriodBoundary) - m.sealing = sealing.New(adaptedAPI, NewEventsAdapter(evts), m.maddr, m.ds, m.sealer, m.sc, m.verif, m.tktFn, &pcp) + m.sealing = sealing.New(adaptedAPI, NewEventsAdapter(evts), m.maddr, m.ds, m.sealer, m.sc, m.verif, &pcp) go m.sealing.Run(ctx) diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 151eb4155..1aa9977d6 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -3,6 +3,7 @@ package storage import ( "bytes" "context" + "errors" "time" "github.com/filecoin-project/go-address" @@ -17,6 +18,8 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) +var errNoPartitions = errors.New("no partitions") + func (s *WindowPoStScheduler) failPost(deadline *miner.DeadlineInfo) { log.Errorf("TODO") /*s.failLk.Lock() @@ -39,18 +42,20 @@ func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.Deadli defer span.End() proof, err := s.runPost(ctx, *deadline, ts) - if err != nil { + switch err { + case errNoPartitions: + return + case nil: + if err := s.submitPost(ctx, proof); err != nil { + log.Errorf("submitPost failed: %+v", err) + s.failPost(deadline) + return + } + default: log.Errorf("runPost failed: %+v", err) s.failPost(deadline) return } - - if err := s.submitPost(ctx, proof); err != nil { - log.Errorf("submitPost failed: %+v", err) - s.failPost(deadline) - return - } - }() } @@ -114,7 +119,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo log.Infof("ts: %+v (%d)", ts.Key(), ts.Height()) if partitionCount == 0 { - return nil, nil + return nil, errNoPartitions } partitions := make([]uint64, partitionCount)