From f8eabd3db47e59f951dbe7a3104892bec24590e2 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 19 Nov 2019 09:53:00 -0600 Subject: [PATCH 01/93] Refactor mining logic to match specs ticket chain --- api/api_full.go | 4 +- api/struct.go | 42 ++++++++--------- chain/blocksync/cbor_gen.go | 2 +- chain/events/events_test.go | 4 +- chain/gen/gen.go | 55 +++++++++++---------- chain/gen/gen_test.go | 8 +--- chain/gen/mining.go | 6 +-- chain/gen/utils.go | 2 +- chain/stmgr/call.go | 2 +- chain/stmgr/stmgr.go | 2 +- chain/store/store.go | 84 ++++++++++++++------------------- chain/store/weight.go | 5 +- chain/sync.go | 37 ++++++--------- chain/sync_test.go | 2 +- chain/types/blockheader.go | 4 +- chain/types/blockheader_test.go | 6 +-- chain/types/cbor_gen.go | 46 +++++++----------- chain/types/tipset.go | 3 +- miner/miner.go | 36 ++++++-------- node/impl/full/chain.go | 4 +- node/impl/full/state.go | 4 +- node/modules/storageminer.go | 2 +- storage/miner.go | 2 +- storage/post.go | 5 +- storage/sector_states.go | 2 +- tools/stats/rpc.go | 13 +---- 26 files changed, 166 insertions(+), 216 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index dba59ad31..c63d52df9 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -23,7 +23,7 @@ type FullNode interface { // First message is guaranteed to be of len == 1, and type == 'current' ChainNotify(context.Context) (<-chan []*store.HeadChange, error) ChainHead(context.Context) (*types.TipSet, error) - ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) + ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error) ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) @@ -52,7 +52,7 @@ type FullNode interface { MinerRegister(context.Context, address.Address) error MinerUnregister(context.Context, address.Address) error MinerAddresses(context.Context) ([]address.Address, error) - MinerCreateBlock(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error) + MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) // // UX ? diff --git a/api/struct.go b/api/struct.go index d94cc031f..f6bc160cb 100644 --- a/api/struct.go +++ b/api/struct.go @@ -37,19 +37,19 @@ type FullNodeStruct struct { CommonStruct Internal struct { - ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` - ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetRandomness func(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) `perm:"read"` - ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"` - ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"` - ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"` - ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` - ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"` - ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` - ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` + ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"` + ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetRandomness func(context.Context, types.TipSetKey, int64) ([]byte, error) `perm:"read"` + ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"` + ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"` + ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"` + ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"` + ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"` + ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"` + ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` SyncState func(context.Context) (*SyncState, error) `perm:"read"` SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"` @@ -58,10 +58,10 @@ type FullNodeStruct struct { MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` - MinerRegister func(context.Context, address.Address) error `perm:"admin"` - MinerUnregister func(context.Context, address.Address) error `perm:"admin"` - MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"` - MinerCreateBlock func(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error) `perm:"write"` + MinerRegister func(context.Context, address.Address) error `perm:"admin"` + MinerUnregister func(context.Context, address.Address) error `perm:"admin"` + MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"` + MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"` WalletNew func(context.Context, string) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` @@ -237,16 +237,16 @@ func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address, return c.Internal.MinerAddresses(ctx) } -func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, tickets []*types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) { - return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs, ts) +func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { + return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) } func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) { return c.Internal.ChainHead(ctx) } -func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) { - return c.Internal.ChainGetRandomness(ctx, pts, ticks, lb) +func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) { + return c.Internal.ChainGetRandomness(ctx, pts, round) } func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) { diff --git a/chain/blocksync/cbor_gen.go b/chain/blocksync/cbor_gen.go index 579b3f857..4af61a490 100644 --- a/chain/blocksync/cbor_gen.go +++ b/chain/blocksync/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "github.com/filecoin-project/lotus/chain/types" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/chain/events/events_test.go b/chain/events/events_test.go index c4ecabe50..ea0f6b225 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -52,7 +52,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { Height: h, Miner: a, - Tickets: []*types.Ticket{{[]byte{byte(h % 2)}}}, + Ticket: &types.Ticket{[]byte{byte(h % 2)}}, ParentStateRoot: dummyCid, Messages: msgcid, @@ -65,7 +65,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { Height: h, Miner: b, - Tickets: []*types.Ticket{{[]byte{byte((h + 1) % 2)}}}, + Ticket: &types.Ticket{[]byte{byte((h + 1) % 2)}}, ParentStateRoot: dummyCid, Messages: msgcid, diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 1fa00f47f..763a7179d 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -3,6 +3,8 @@ package gen import ( "bytes" "context" + "crypto/sha256" + "encoding/binary" "fmt" "sync/atomic" @@ -46,7 +48,7 @@ type ChainGen struct { genesis *types.BlockHeader CurTipset *store.FullTipSet - Timestamper func(*types.TipSet, int) uint64 + Timestamper func(*types.TipSet, uint64) uint64 w *wallet.Wallet @@ -195,14 +197,9 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) { return out.Bytes(), nil } -func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, ticks []*types.Ticket) (types.ElectionProof, *types.Ticket, error) { +func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (types.ElectionProof, *types.Ticket, error) { - var lastTicket *types.Ticket - if len(ticks) == 0 { - lastTicket = pts.MinTicket() - } else { - lastTicket = ticks[len(ticks)-1] - } + lastTicket := pts.MinTicket() st := pts.ParentState() @@ -211,7 +208,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add return nil, nil, xerrors.Errorf("get miner worker: %w", err) } - vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VRFProof) + vrfBase := TicketHash(lastTicket, uint64(round)) + vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, vrfBase) if err != nil { return nil, nil, xerrors.Errorf("compute VRF: %w", err) } @@ -220,7 +218,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add VRFProof: vrfout, } - win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm}) + win, eproof, err := IsRoundWinner(ctx, pts, round, m, &mca{w: cg.w, sm: cg.sm}) if err != nil { return nil, nil, xerrors.Errorf("checking round winner failed: %w", err) } @@ -248,23 +246,21 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) { func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) { var blks []*types.FullBlock - ticketSets := make([][]*types.Ticket, len(miners)) msgs, err := cg.getRandomMessages() if err != nil { return nil, xerrors.Errorf("get random messages: %w", err) } - for len(blks) == 0 { - for i, m := range miners { - proof, t, err := cg.nextBlockProof(context.TODO(), base, m, ticketSets[i]) + for round := int64(base.Height() + 1); len(blks) == 0; round++ { + for _, m := range miners { + proof, t, err := cg.nextBlockProof(context.TODO(), base, m, round) if err != nil { return nil, xerrors.Errorf("next block proof: %w", err) } - ticketSets[i] = append(ticketSets[i], t) if proof != nil { - fblk, err := cg.makeBlock(base, m, proof, ticketSets[i], msgs) + fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs) if err != nil { return nil, xerrors.Errorf("making a block for next tipset failed: %w", err) } @@ -286,16 +282,16 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad }, nil } -func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, tickets []*types.Ticket, msgs []*types.SignedMessage) (*types.FullBlock, error) { +func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) { var ts uint64 if cg.Timestamper != nil { - ts = cg.Timestamper(parents, len(tickets)) + ts = cg.Timestamper(parents, height-parents.Height()) } else { - ts = parents.MinTimestamp() + (uint64(len(tickets)) * build.BlockDelay) + ts = parents.MinTimestamp() + ((height - parents.Height()) * build.BlockDelay) } - fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, tickets, eproof, msgs, ts) + fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts) if err != nil { return nil, err } @@ -354,7 +350,7 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) { } type MiningCheckAPI interface { - ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) + ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error) StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error) @@ -368,8 +364,8 @@ type mca struct { sm *stmgr.StateManager } -func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) { - return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), ticks, int64(lb)) +func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb int64) ([]byte, error) { + return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb)) } func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) { @@ -392,8 +388,8 @@ func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*ty return mca.w.Sign(ctx, a, v) } -func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) { - r, err := a.ChainGetRandomness(ctx, ts.Key(), ticks, build.EcRandomnessLookback) +func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) { + r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback) if err != nil { return false, nil, xerrors.Errorf("chain get randomness: %w", err) } @@ -430,3 +426,12 @@ func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []b return sig.Data, nil } + +func TicketHash(t *types.Ticket, round uint64) []byte { + h := sha256.New() + h.Write(t.VRFProof) + var roundbuf [8]byte + binary.LittleEndian.PutUint64(roundbuf[:], round) + h.Write(roundbuf[:]) + return h.Sum(nil) +} diff --git a/chain/gen/gen_test.go b/chain/gen/gen_test.go index b4f2456b4..399742f5f 100644 --- a/chain/gen/gen_test.go +++ b/chain/gen/gen_test.go @@ -12,18 +12,12 @@ func testGeneration(t testing.TB, n int, msgs int) { g.msgsPerBlock = msgs - var height int for i := 0; i < n; i++ { mts, err := g.NextTipSet() if err != nil { t.Fatalf("error at H:%d, %s", i, err) } - - ts := mts.TipSet.TipSet() - if ts.Height() != uint64(height+len(ts.Blocks()[0].Tickets)) { - t.Fatal("wrong height", ts.Height(), i, len(ts.Blocks()[0].Tickets), len(ts.Blocks())) - } - height += len(ts.Blocks()[0].Tickets) + _ = mts } } diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 5cfc3a694..49f510cf1 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -18,14 +18,12 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" ) -func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) { +func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) { st, recpts, err := sm.TipSetState(ctx, parents) if err != nil { return nil, xerrors.Errorf("failed to load tipset state: %w", err) } - height := parents.Height() + uint64(len(tickets)) - worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, miner) if err != nil { return nil, xerrors.Errorf("failed to get miner worker: %w", err) @@ -34,7 +32,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal next := &types.BlockHeader{ Miner: miner, Parents: parents.Cids(), - Tickets: tickets, + Ticket: ticket, Height: height, Timestamp: timestamp, ElectionProof: proof, diff --git a/chain/gen/utils.go b/chain/gen/utils.go index f60da262d..b0aab3fa9 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -384,7 +384,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B b := &types.BlockHeader{ Miner: actors.InitAddress, - Tickets: []*types.Ticket{genesisticket}, + Ticket: genesisticket, ElectionProof: []byte("the Genesis block"), Parents: []cid.Cid{}, Height: 0, diff --git a/chain/stmgr/call.go b/chain/stmgr/call.go index 731633d26..cfbe729c0 100644 --- a/chain/stmgr/call.go +++ b/chain/stmgr/call.go @@ -68,7 +68,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types. state := ts.ParentState() - r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil) + r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height()) return sm.CallRaw(ctx, msg, state, r, ts.Height()) } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 5b6eafb81..68c3ea24e 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -102,7 +102,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl cids[i] = v.Cid() } - r := store.NewChainRand(sm.cs, cids, blks[0].Height, nil) + r := store.NewChainRand(sm.cs, cids, blks[0].Height) vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore()) if err != nil { diff --git a/chain/store/store.go b/chain/store/store.go index 00e863e5f..8f42390d5 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -3,8 +3,8 @@ package store import ( "context" "crypto/sha256" + "encoding/binary" "encoding/json" - "fmt" "sync" "github.com/filecoin-project/lotus/build" @@ -12,7 +12,6 @@ import ( "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/vm" "go.opencensus.io/trace" - "go.uber.org/zap" amt "github.com/filecoin-project/go-amt-ipld" "github.com/filecoin-project/lotus/chain/types" @@ -771,24 +770,21 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) { return NewFullTipSet(out), nil } -func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets []*types.Ticket, lb int64) ([]byte, error) { +func ticketHash(t *types.Ticket, round int64) []byte { + h := sha256.New() + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], uint64(round)) + + h.Write(t.VRFProof) + h.Write(buf[:]) + + return h.Sum(nil) +} + +func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) { ctx, span := trace.StartSpan(ctx, "store.GetRandomness") defer span.End() - span.AddAttributes(trace.Int64Attribute("lb", lb)) - - if lb < 0 { - return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb) - } - lt := int64(len(tickets)) - if lb < lt { - log.Desugar().Warn("self sampling randomness. this should be extremely rare, if you see this often it may be a bug", zap.Stack("stacktrace")) - - t := tickets[lt-(1+lb)] - - return t.VRFProof, nil - } - - nv := lb - lt + span.AddAttributes(trace.Int64Attribute("round", round)) for { nts, err := cs.LoadTipSet(blks) @@ -797,26 +793,21 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets } mtb := nts.MinTicketBlock() - lt := int64(len(mtb.Tickets)) - if nv < lt { - t := mtb.Tickets[lt-(1+nv)] - return t.VRFProof, nil - } - nv -= lt + if int64(nts.Height()) <= round { + return ticketHash(nts.MinTicketBlock().Ticket, round), nil + } // special case for lookback behind genesis block // TODO(spec): this is not in the spec, need to sync that if mtb.Height == 0 { - t := mtb.Tickets[0] + // round is negative + thash := ticketHash(mtb.Ticket, round*-1) - rval := t.VRFProof - for i := int64(0); i < nv; i++ { - h := sha256.Sum256(rval) - rval = h[:] - } - return rval, nil + // for negative lookbacks, just use the hash of the positive tickethash value + h := sha256.Sum256(thash) + return h[:], nil } blks = mtb.Parents @@ -837,36 +828,33 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types } for { - mtb := ts.MinTicketBlock() - if h >= ts.Height()-uint64(len(mtb.Tickets)) { - return ts, nil - } - pts, err := cs.LoadTipSet(ts.Parents()) if err != nil { return nil, err } + + if h > pts.Height() { + return ts, nil + } + ts = pts } } type chainRand struct { - cs *ChainStore - blks []cid.Cid - bh uint64 - tickets []*types.Ticket + cs *ChainStore + blks []cid.Cid + bh uint64 } -func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) vm.Rand { +func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand { return &chainRand{ - cs: cs, - blks: blks, - bh: bheight, - tickets: tickets, + cs: cs, + blks: blks, + bh: bheight, } } -func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) { - lb := (int64(cr.bh) + int64(len(cr.tickets))) - h - return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb) +func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) { + return cr.cs.GetRandomness(ctx, cr.blks, round) } diff --git a/chain/store/weight.go b/chain/store/weight.go index 53c202845..901356728 100644 --- a/chain/store/weight.go +++ b/chain/store/weight.go @@ -2,12 +2,13 @@ package store import ( "context" + "math/big" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "golang.org/x/xerrors" - "math/big" ) var zero = types.NewInt(0) @@ -57,7 +58,7 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) { bstate := ts.ParentState() - r := NewChainRand(cs, ts.Cids(), ts.Height(), nil) + r := NewChainRand(cs, ts.Cids(), ts.Height()) vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs) if err != nil { diff --git a/chain/sync.go b/chain/sync.go index aff1e6cee..3a9624239 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -27,6 +27,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/blocksync" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/state" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -466,30 +467,22 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b return nil } -func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Address, tickets []*types.Ticket, base *types.TipSet) error { +func (syncer *Syncer) validateTicket(ctx context.Context, mworker address.Address, ticket *types.Ticket, base *types.TipSet, round uint64) error { ctx, span := trace.StartSpan(ctx, "validateTickets") defer span.End() - span.AddAttributes(trace.Int64Attribute("tickets", int64(len(tickets)))) - if len(tickets) == 0 { - return xerrors.Errorf("block had no tickets") + sig := &types.Signature{ + Type: types.KTBLS, + Data: ticket.VRFProof, } - cur := base.MinTicket() - for i := 0; i < len(tickets); i++ { - next := tickets[i] + vrfBase := gen.TicketHash(base.MinTicket(), round) - sig := &types.Signature{ - Type: types.KTBLS, - Data: next.VRFProof, - } + log.Infof("about to verify ticket: %x %d", base.MinTicket().VRFProof, round) - // TODO: ticket signatures should also include miner address - if err := sig.Verify(mworker, cur.VRFProof); err != nil { - return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err) - } - - cur = next + // TODO: ticket signatures should also include miner address + if err := sig.Verify(mworker, vrfBase); err != nil { + return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err) } return nil @@ -514,9 +507,9 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return xerrors.Errorf("block was from the future") } - if h.Timestamp < baseTs.MinTimestamp()+uint64(build.BlockDelay*len(h.Tickets)) { - log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), len(h.Tickets)) - return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * tkts.len:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, len(h.Tickets)) + if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*(h.Height-baseTs.Height())) { + log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), h.Height, baseTs.Height()) + return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height()) } winnerCheck := async.Err(func() error { @@ -583,14 +576,14 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) tktsCheck := async.Err(func() error { - if err := syncer.validateTickets(ctx, waddr, h.Tickets, baseTs); err != nil { + if err := syncer.validateTicket(ctx, waddr, h.Ticket, baseTs, h.Height); err != nil { return xerrors.Errorf("validating block tickets failed: %w", err) } return nil }) eproofCheck := async.Err(func() error { - rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), h.Tickets, build.EcRandomnessLookback) + rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback)) if err != nil { return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) } diff --git a/chain/sync_test.go b/chain/sync_test.go index d17b6e853..c5cf21c1e 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -390,7 +390,7 @@ func TestSyncBadTimestamp(t *testing.T) { tu.waitUntilSync(0, client) base := tu.g.CurTipset - tu.g.Timestamper = func(pts *types.TipSet, tl int) uint64 { + tu.g.Timestamper = func(pts *types.TipSet, tl uint64) uint64 { return pts.MinTimestamp() + (build.BlockDelay / 2) } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index aa311db0c..1c0d683e7 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -25,7 +25,7 @@ type ElectionProof []byte type BlockHeader struct { Miner address.Address - Tickets []*Ticket + Ticket *Ticket ElectionProof []byte @@ -91,7 +91,7 @@ func (blk *BlockHeader) Serialize() ([]byte, error) { } func (blk *BlockHeader) LastTicket() *Ticket { - return blk.Tickets[len(blk.Tickets)-1] + return blk.Ticket } func (blk *BlockHeader) SigningBytes() ([]byte, error) { diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index 09ca061b9..96808eda6 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -25,10 +25,8 @@ func testBlockHeader(t testing.TB) *BlockHeader { return &BlockHeader{ Miner: addr, ElectionProof: []byte("cats won the election"), - Tickets: []*Ticket{ - &Ticket{ - VRFProof: []byte("vrf proof0000000vrf proof0000000"), - }, + Ticket: &Ticket{ + VRFProof: []byte("vrf proof0000000vrf proof0000000"), }, Parents: []cid.Cid{c, c}, ParentMessageReceipts: c, diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index fa3cddaf4..6818e1203 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "math" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) @@ -28,15 +28,10 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error { return err } - // t.t.Tickets ([]*types.Ticket) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Tickets)))); err != nil { + // t.t.Ticket (types.Ticket) (struct) + if err := t.Ticket.MarshalCBOR(w); err != nil { return err } - for _, v := range t.Tickets { - if err := v.MarshalCBOR(w); err != nil { - return err - } - } // t.t.ElectionProof ([]uint8) (slice) if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.ElectionProof)))); err != nil { @@ -125,32 +120,27 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error { } } - // t.t.Tickets ([]*types.Ticket) (slice) + // t.t.Ticket (types.Ticket) (struct) - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.Tickets: array too large (%d)", extra) - } + { - if maj != cbg.MajArray { - return fmt.Errorf("expected cbor array") - } - if extra > 0 { - t.Tickets = make([]*Ticket, extra) - } - for i := 0; i < int(extra); i++ { - - var v Ticket - if err := v.UnmarshalCBOR(br); err != nil { + pb, err := br.PeekByte() + if err != nil { return err } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.Ticket = new(Ticket) + if err := t.Ticket.UnmarshalCBOR(br); err != nil { + return err + } + } - t.Tickets[i] = &v } - // t.t.ElectionProof ([]uint8) (slice) maj, extra, err = cbg.CborReadHeader(br) diff --git a/chain/types/tipset.go b/chain/types/tipset.go index ca6941e5c..1ed15289e 100644 --- a/chain/types/tipset.go +++ b/chain/types/tipset.go @@ -165,8 +165,7 @@ func (t *Ticket) Less(o *Ticket) bool { } func (ts *TipSet) MinTicket() *Ticket { - b := ts.MinTicketBlock() - return b.Tickets[len(b.Tickets)-1] + return ts.MinTicketBlock().Ticket } func (ts *TipSet) MinTimestamp() uint64 { diff --git a/miner/miner.go b/miner/miner.go index 09e904e0c..b5e84507b 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -161,8 +161,8 @@ eventLoop: log.Errorf("failed to get best mining candidate: %s", err) continue } - if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) { - log.Errorf("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets)) + if base.ts.Equals(lastBase.ts) && lastBase.nullRounds == base.nullRounds { + log.Errorf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds) time.Sleep(build.BlockDelay * time.Second) continue } @@ -205,15 +205,15 @@ eventLoop: } } } else { - nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*len(base.tickets))), 0) + nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*base.nullRounds)), 0) time.Sleep(time.Until(nextRound)) } } } type MiningBase struct { - ts *types.TipSet - tickets []*types.Ticket + ts *types.TipSet + nullRounds uint64 } func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) { @@ -253,13 +253,13 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return nil, errors.Wrap(err, "scratching ticket failed") } - win, proof, err := gen.IsRoundWinner(ctx, base.ts, append(base.tickets, ticket), addr, &m.api) + win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, &m.api) if err != nil { return nil, errors.Wrap(err, "failed to check if we win next round") } if !win { - m.submitNullTicket(base, ticket) + base.nullRounds++ return nil, nil } @@ -272,11 +272,6 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return b, nil } -func (m *Miner) submitNullTicket(base *MiningBase, ticket *types.Ticket) { - base.tickets = append(base.tickets, ticket) - m.lastWork = base -} - func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []byte) ([]byte, error) { w, err := m.getMinerWorker(ctx, addr, nil) if err != nil { @@ -309,14 +304,11 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty } func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { - var lastTicket *types.Ticket - if len(base.tickets) > 0 { - lastTicket = base.tickets[len(base.tickets)-1] - } else { - lastTicket = base.ts.MinTicket() - } + round := base.ts.Height() + base.nullRounds - vrfOut, err := m.computeVRF(ctx, addr, lastTicket.VRFProof) + vrfBase := gen.TicketHash(base.ts.MinTicket(), round) + + vrfOut, err := m.computeVRF(ctx, addr, vrfBase) if err != nil { return nil, err } @@ -338,10 +330,12 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type return nil, xerrors.Errorf("message filtering failed: %w", err) } - uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(len(base.tickets)+1)) + uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(base.nullRounds+1)) + + nheight := base.ts.Height() + base.nullRounds + 1 // why even return this? that api call could just submit it for us - return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, append(base.tickets, ticket), proof, msgs, uint64(uts)) + return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts)) } type actorLookup func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) diff --git a/node/impl/full/chain.go b/node/impl/full/chain.go index 4285682fc..1e39be598 100644 --- a/node/impl/full/chain.go +++ b/node/impl/full/chain.go @@ -28,8 +28,8 @@ func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) { return a.Chain.GetHeaviestTipSet(), nil } -func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, tickets []*types.Ticket, lb int) ([]byte, error) { - return a.Chain.GetRandomness(ctx, pts.Cids(), tickets, int64(lb)) +func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) { + return a.Chain.GetRandomness(ctx, pts.Cids(), round) } func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) { diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 75e68f337..38d9490b7 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -177,8 +177,8 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ } // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner -func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) { - fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, tickets, proof, msgs, ts) +func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { + fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts) if err != nil { return nil, err } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index e5cbe8d62..a7cc98463 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -221,7 +221,7 @@ func SealTicketGen(api api.FullNode) storage.TicketFn { return nil, xerrors.Errorf("getting head ts for SealTicket failed: %w", err) } - r, err := api.ChainGetRandomness(ctx, ts.Key(), nil, build.SealRandomnessLookback) + r, err := api.ChainGetRandomness(ctx, ts.Key(), int64(ts.Height())-build.SealRandomnessLookback) if err != nil { return nil, xerrors.Errorf("getting randomness for SealTicket failed: %w", err) } diff --git a/storage/miner.go b/storage/miner.go index af8bf5a6d..3750d41fe 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -64,7 +64,7 @@ type storageMinerApi interface { ChainHead(context.Context) (*types.TipSet, error) ChainNotify(context.Context) (<-chan []*store.HeadChange, error) - ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) + ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error) ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) diff --git a/storage/post.go b/storage/post.go index ab94d719a..be2d06eac 100644 --- a/storage/post.go +++ b/storage/post.go @@ -154,9 +154,8 @@ func (p *post) preparePost(ctx context.Context) error { p.sset = sset - // Compute how many blocks back we have to look from the given tipset for the PoSt challenge - challengeLookback := int((int64(p.ts.Height()) - int64(p.ppe)) + int64(build.PoStChallangeTime) + int64(build.PoStRandomnessLookback)) - r, err := p.m.api.ChainGetRandomness(ctx, p.ts.Key(), nil, challengeLookback) + challengeRound := int64(p.ppe) - int64(build.PoStChallangeTime+build.PoStRandomnessLookback) + r, err := p.m.api.ChainGetRandomness(ctx, p.ts.Key(), challengeRound) if err != nil { return xerrors.Errorf("failed to get chain randomness for post (ts=%d; ppe=%d): %w", p.ts.Height(), p.ppe, err) } diff --git a/storage/sector_states.go b/storage/sector_states.go index 2e69b7ce7..537ee2b1d 100644 --- a/storage/sector_states.go +++ b/storage/sector_states.go @@ -145,7 +145,7 @@ func (m *Miner) preCommitted(ctx context.Context, sector SectorInfo) (func(*Sect log.Infof("precommit for sector %d made it on chain, will start proof computation at height %d", sector.SectorID, randHeight) err = m.events.ChainAt(func(ctx context.Context, ts *types.TipSet, curH uint64) error { - rand, err := m.api.ChainGetRandomness(ctx, ts.Key(), nil, int(ts.Height()-randHeight)) + rand, err := m.api.ChainGetRandomness(ctx, ts.Key(), int64(randHeight)) if err != nil { return xerrors.Errorf("failed to get randomness for computing seal proof: %w", err) } diff --git a/tools/stats/rpc.go b/tools/stats/rpc.go index c2131b480..af0f5690c 100644 --- a/tools/stats/rpc.go +++ b/tools/stats/rpc.go @@ -134,12 +134,8 @@ func loadTipsets(ctx context.Context, api api.FullNode, curr *types.TipSet, lowe log.Printf("Walking back { height:%d }", curr.Height()) tipsets = append(tipsets, curr) - ph := ParentTipsetHeight(curr) - if ph == 0 { - break - } - - prev, err := api.ChainGetTipSetByHeight(ctx, ph, curr) + tsk := types.NewTipSetKey(curr.Parents()...) + prev, err := api.ChainGetTipSet(ctx, tsk) if err != nil { return tipsets, err } @@ -154,11 +150,6 @@ func loadTipsets(ctx context.Context, api api.FullNode, curr *types.TipSet, lowe return tipsets, nil } -func ParentTipsetHeight(tipset *types.TipSet) uint64 { - mtb := tipset.MinTicketBlock() - return tipset.Height() - uint64(len(mtb.Tickets)) - 1 -} - func GetFullNodeAPI(repo string) (api.FullNode, jsonrpc.ClientCloser, error) { addr, headers, err := getAPI(repo) if err != nil { From c4564c0597c5c8825e9a17e6c1f98ebbf4b958bc Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 19 Nov 2019 14:05:21 -0600 Subject: [PATCH 02/93] use proper round number, allow block signature to be nil --- chain/gen/mining.go | 2 +- chain/gen/utils.go | 2 +- chain/sync.go | 2 -- chain/types/blockheader.go | 4 ++-- chain/types/blockheader_test.go | 2 +- chain/types/cbor_gen.go | 14 +++++++++++++- miner/miner.go | 2 +- 7 files changed, 19 insertions(+), 9 deletions(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 49f510cf1..51036ad5b 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -120,7 +120,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal return nil, xerrors.Errorf("failed to sign new block: %w", err) } - next.BlockSig = *sig + next.BlockSig = sig fullBlock := &types.FullBlock{ Header: next, diff --git a/chain/gen/utils.go b/chain/gen/utils.go index b0aab3fa9..1a86e0d1f 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -393,7 +393,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B Messages: mmb.Cid(), ParentMessageReceipts: emptyroot, BLSAggregate: types.Signature{Type: types.KTBLS, Data: []byte("signatureeee")}, - BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")}, + BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("block signatureeee")}, Timestamp: ts, } diff --git a/chain/sync.go b/chain/sync.go index 3a9624239..c1e68b02e 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -478,8 +478,6 @@ func (syncer *Syncer) validateTicket(ctx context.Context, mworker address.Addres vrfBase := gen.TicketHash(base.MinTicket(), round) - log.Infof("about to verify ticket: %x %d", base.MinTicket().VRFProof, round) - // TODO: ticket signatures should also include miner address if err := sig.Verify(mworker, vrfBase); err != nil { return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err) diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 1c0d683e7..c0fc59214 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -45,7 +45,7 @@ type BlockHeader struct { Timestamp uint64 - BlockSig Signature + BlockSig *Signature } func (b *BlockHeader) ToStorageBlock() (block.Block, error) { @@ -96,7 +96,7 @@ func (blk *BlockHeader) LastTicket() *Ticket { func (blk *BlockHeader) SigningBytes() ([]byte, error) { blkcopy := *blk - blkcopy.BlockSig = Signature{} + blkcopy.BlockSig = nil return blkcopy.Serialize() } diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index 96808eda6..6c41f3b4b 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -35,7 +35,7 @@ func testBlockHeader(t testing.TB) *BlockHeader { Messages: c, Height: 85919298723, ParentStateRoot: c, - BlockSig: Signature{Type: KTBLS, Data: []byte("boo! im a signature")}, + BlockSig: &Signature{Type: KTBLS, Data: []byte("boo! im a signature")}, } } diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index 6818e1203..a0af53450 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -261,9 +261,21 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error { { - if err := t.BlockSig.UnmarshalCBOR(br); err != nil { + pb, err := br.PeekByte() + if err != nil { return err } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.BlockSig = new(Signature) + if err := t.BlockSig.UnmarshalCBOR(br); err != nil { + return err + } + } } return nil diff --git a/miner/miner.go b/miner/miner.go index b5e84507b..1a394da2b 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -304,7 +304,7 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty } func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { - round := base.ts.Height() + base.nullRounds + round := base.ts.Height() + base.nullRounds + 1 vrfBase := gen.TicketHash(base.ts.MinTicket(), round) From d57f048c2c71d893418d03fd067db34e12e39eb3 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 19 Nov 2019 14:07:16 -0600 Subject: [PATCH 03/93] reject blocks with nil signatures --- chain/actors/actor_storagepower_test.go | 2 +- chain/events/events_test.go | 4 ++-- chain/events/tscache_test.go | 4 ++-- chain/sync.go | 4 ++++ chain/types/mock/chain.go | 8 +++----- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/chain/actors/actor_storagepower_test.go b/chain/actors/actor_storagepower_test.go index b5330be5a..20157ada8 100644 --- a/chain/actors/actor_storagepower_test.go +++ b/chain/actors/actor_storagepower_test.go @@ -170,5 +170,5 @@ func signBlock(t *testing.T, w *wallet.Wallet, worker address.Address, blk *type t.Fatal(err) } - blk.BlockSig = *sig + blk.BlockSig = sig } diff --git a/chain/events/events_test.go b/chain/events/events_test.go index ea0f6b225..6ceeb8db0 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -58,7 +58,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { Messages: msgcid, ParentMessageReceipts: dummyCid, - BlockSig: types.Signature{Type: types.KTBLS}, + BlockSig: &types.Signature{Type: types.KTBLS}, BLSAggregate: types.Signature{Type: types.KTBLS}, }, { @@ -71,7 +71,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { Messages: msgcid, ParentMessageReceipts: dummyCid, - BlockSig: types.Signature{Type: types.KTBLS}, + BlockSig: &types.Signature{Type: types.KTBLS}, BLSAggregate: types.Signature{Type: types.KTBLS}, }, }) diff --git a/chain/events/tscache_test.go b/chain/events/tscache_test.go index 7d715aea0..9c7c203bb 100644 --- a/chain/events/tscache_test.go +++ b/chain/events/tscache_test.go @@ -27,7 +27,7 @@ func TestTsCache(t *testing.T) { ParentStateRoot: dummyCid, Messages: dummyCid, ParentMessageReceipts: dummyCid, - BlockSig: types.Signature{Type: types.KTBLS}, + BlockSig: &types.Signature{Type: types.KTBLS}, BLSAggregate: types.Signature{Type: types.KTBLS}, }}) if err != nil { @@ -69,7 +69,7 @@ func TestTsCacheNulls(t *testing.T) { ParentStateRoot: dummyCid, Messages: dummyCid, ParentMessageReceipts: dummyCid, - BlockSig: types.Signature{Type: types.KTBLS}, + BlockSig: &types.Signature{Type: types.KTBLS}, BLSAggregate: types.Signature{Type: types.KTBLS}, }}) if err != nil { diff --git a/chain/sync.go b/chain/sync.go index c1e68b02e..c804afcd3 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -501,6 +501,10 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } // fast checks first + if h.BlockSig == nil { + return xerrors.Errorf("block had nil signature") + } + if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) { return xerrors.Errorf("block was from the future") } diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index 09b37370a..474d8a92b 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -36,10 +36,8 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types return &types.BlockHeader{ Miner: addr, ElectionProof: []byte("cats won the election"), - Tickets: []*types.Ticket{ - { - VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)), - }, + Ticket: &types.Ticket{ + VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)), }, Parents: pcids, ParentMessageReceipts: c, @@ -48,7 +46,7 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types Messages: c, Height: height, ParentStateRoot: c, - BlockSig: types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")}, + BlockSig: &types.Signature{Type: types.KTBLS, Data: []byte("boo! im a signature")}, } } From 96482f456a8be84fb415acc2a6b816681fe1b67a Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 21 Nov 2019 16:21:45 -0600 Subject: [PATCH 04/93] WIP: election post restructuring --- api/api_full.go | 2 +- api/struct.go | 10 +- chain/actors/actor_miner.go | 19 ++- chain/actors/cbor_gen.go | 27 +--- chain/gen/gen.go | 159 ++++++++++++++++++-- chain/gen/mining.go | 4 +- chain/gen/utils.go | 9 +- chain/stmgr/utils.go | 21 +++ chain/store/store.go | 6 +- chain/sync.go | 98 ++++++++----- chain/types/blockheader.go | 34 +++-- chain/types/blockheader_test.go | 6 +- chain/types/cbor_gen.go | 226 ++++++++++++++++++++++++++--- chain/types/mock/chain.go | 6 +- extern/go-bls-sigs | 2 +- extern/go-sectorbuilder | 2 +- gen/main.go | 2 + lib/sectorbuilder/sectorbuilder.go | 30 +++- miner/miner.go | 15 +- node/impl/full/state.go | 2 +- storage/post.go | 5 +- 21 files changed, 547 insertions(+), 138 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index c63d52df9..47e2f71d7 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -52,7 +52,7 @@ type FullNode interface { MinerRegister(context.Context, address.Address) error MinerUnregister(context.Context, address.Address) error MinerAddresses(context.Context) ([]address.Address, error) - MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) + MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) // // UX ? diff --git a/api/struct.go b/api/struct.go index f6bc160cb..bbd200b7d 100644 --- a/api/struct.go +++ b/api/struct.go @@ -58,10 +58,10 @@ type FullNodeStruct struct { MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` - MinerRegister func(context.Context, address.Address) error `perm:"admin"` - MinerUnregister func(context.Context, address.Address) error `perm:"admin"` - MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"` - MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"` + MinerRegister func(context.Context, address.Address) error `perm:"admin"` + MinerUnregister func(context.Context, address.Address) error `perm:"admin"` + MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"` + MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"` WalletNew func(context.Context, string) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` @@ -237,7 +237,7 @@ func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address, return c.Internal.MinerAddresses(ctx) } -func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { +func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) } diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 2f2a1df33..b5442b1fa 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -389,9 +389,8 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC } type SubmitPoStParams struct { - Proof []byte + Proof types.EPostProof DoneSet types.BitField - // TODO: once the spec changes finish, we have more work to do here... } func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { @@ -402,8 +401,6 @@ func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { return end, period } -// TODO: this is a dummy method that allows us to plumb in other parts of the -// system for now. func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) { oldstate, self, err := loadState(vmctx) if err != nil { @@ -491,10 +488,20 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, } faults := self.CurrentFaultSet.All() + _ = faults + + _ = seed + //VerifyPoStRandomness() + + convertToCandidates := func(wins []types.EPostTicket) []sectorbuilder.EPostCandidate { + panic("NYI") + } + winners := convertToCandidates(params.Proof.Winners) + + proverID := vmctx.Message().To // TODO: normalize to ID address if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize, - sectorbuilder.NewSortedSectorInfo(sectorInfos), seed, params.Proof, - faults); !ok || lerr != nil { + sectorbuilder.NewSortedSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil { if lerr != nil { // TODO: study PoST errors return nil, aerrors.Absorb(lerr, 4, "PoST error") diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 53de185e1..522896008 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -836,11 +836,8 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error { return err } - // t.t.Proof ([]uint8) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil { - return err - } - if _, err := w.Write(t.Proof); err != nil { + // t.t.Proof (types.EPostProof) (struct) + if err := t.Proof.MarshalCBOR(w); err != nil { return err } @@ -866,22 +863,14 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.t.Proof ([]uint8) (slice) + // t.t.Proof (types.EPostProof) (struct) - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.Proof: array too large (%d)", extra) - } + { + + if err := t.Proof.UnmarshalCBOR(br); err != nil { + return err + } - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.Proof = make([]byte, extra) - if _, err := io.ReadFull(br, t.Proof); err != nil { - return err } // t.t.DoneSet (types.BitField) (struct) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 763a7179d..e0db5e1ec 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -13,6 +13,7 @@ import ( offline "github.com/ipfs/go-ipfs-exchange-offline" "github.com/ipfs/go-merkledag" peer "github.com/libp2p/go-libp2p-peer" + "go.opencensus.io/trace" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" @@ -22,6 +23,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/node/repo" block "github.com/ipfs/go-block-format" @@ -52,6 +54,7 @@ type ChainGen struct { w *wallet.Wallet + eppProvs map[address.Address]ElectionPoStProver Miners []address.Address mworkers []address.Address receivers []address.Address @@ -155,6 +158,11 @@ func NewGenerator() (*ChainGen, error) { return nil, xerrors.Errorf("MakeGenesisBlock failed to set miner address") } + mgen := make(map[address.Address]ElectionPoStProver) + for _, m := range minercfg.MinerAddrs { + mgen[m] = &eppProvider{} + } + sm := stmgr.NewStateManager(cs) gen := &ChainGen{ @@ -166,6 +174,7 @@ func NewGenerator() (*ChainGen, error) { w: w, Miners: minercfg.MinerAddrs, + eppProvs: mgen, mworkers: minercfg.Workers, banker: banker, receivers: receievers, @@ -191,13 +200,13 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) { out := new(bytes.Buffer) if err := car.WriteCar(context.TODO(), dserv, []cid.Cid{cg.Genesis().Cid()}, out); err != nil { - return nil, err + return nil, xerrors.Errorf("genesis car write car failed: %w", err) } return out.Bytes(), nil } -func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (types.ElectionProof, *types.Ticket, error) { +func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (*types.EPostProof, *types.Ticket, error) { lastTicket := pts.MinTicket() @@ -208,8 +217,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add return nil, nil, xerrors.Errorf("get miner worker: %w", err) } - vrfBase := TicketHash(lastTicket, uint64(round)) - vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, vrfBase) + vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof) if err != nil { return nil, nil, xerrors.Errorf("compute VRF: %w", err) } @@ -218,7 +226,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add VRFProof: vrfout, } - win, eproof, err := IsRoundWinner(ctx, pts, round, m, &mca{w: cg.w, sm: cg.sm}) + win, eproof, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm}) if err != nil { return nil, nil, xerrors.Errorf("checking round winner failed: %w", err) } @@ -282,7 +290,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad }, nil } -func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) { +func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) { var ts uint64 if cg.Timestamper != nil { @@ -356,6 +364,8 @@ type MiningCheckAPI interface { StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) + StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) + WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) } @@ -384,11 +394,38 @@ func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, ts * return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr) } +func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, ts *types.TipSet) (uint64, error) { + return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr) +} + func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) { return mca.w.Sign(ctx, a, v) } -func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) { +type ElectionPoStProver interface { + GenerateCandidates(context.Context, []byte) ([]sectorbuilder.EPostCandidate, error) + ComputeProof(context.Context, []byte, []sectorbuilder.EPostCandidate) ([]byte, error) +} + +type eppProvider struct { +} + +func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { + return []sectorbuilder.EPostCandidate{ + sectorbuilder.EPostCandidate{ + SectorID: 1, + PartialTicket: [32]byte{}, + Ticket: [32]byte{}, + SectorChallengeIndex: 1, + }, + }, nil +} + +func (epp *eppProvider) ComputeProof(ctx context.Context, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { + return []byte("this is an election post proof"), nil +} + +func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *types.EPostProof, error) { r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback) if err != nil { return false, nil, xerrors.Errorf("chain get randomness: %w", err) @@ -399,23 +436,111 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return false, nil, xerrors.Errorf("failed to get miner worker: %w", err) } - vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, r) + vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, miner, DSepElectionPost, r) if err != nil { return false, nil, xerrors.Errorf("failed to compute VRF: %w", err) } + candidates, err := epp.GenerateCandidates(ctx, vrfout) + if err != nil { + return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates") + } + pow, err := a.StateMinerPower(ctx, miner, ts) if err != nil { return false, nil, xerrors.Errorf("failed to check power: %w", err) } - return types.PowerCmp(vrfout, pow.MinerPower, pow.TotalPower), vrfout, nil + ssize, err := a.StateMinerSectorSize(ctx, miner, ts) + if err != nil { + return false, nil, xerrors.Errorf("failed to look up miners sector size: %w", err) + } + + var winners []sectorbuilder.EPostCandidate + for _, c := range candidates { + if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, 1) { + winners = append(winners, c) + } + } + + // no winners, sad + if len(winners) == 0 { + return false, nil, nil + } + + proof, err := epp.ComputeProof(ctx, vrfout, winners) + if err != nil { + return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err) + } + + ept := types.EPostProof{ + Proof: proof, + PostRand: vrfout, + } + for _, win := range winners { + ept.Winners = append(ept.Winners, types.EPostTicket{ + Partial: win.PartialTicket[:], + SectorID: win.SectorID, + ChallengeIndex: win.SectorChallengeIndex, + }) + } + + return true, &ept, nil } type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error) -func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []byte) ([]byte, error) { - sig, err := sign(ctx, w, input) +const ( + DSepTicket = 1 + DSepElectionPost = 2 +) + +func hashVRFBase(personalization uint64, miner address.Address, input []byte) ([]byte, error) { + if miner.Protocol() != address.ID { + return nil, xerrors.Errorf("miner address for compute VRF must be an ID address") + } + + var persbuf [8]byte + binary.LittleEndian.PutUint64(persbuf[:], personalization) + + h := sha256.New() + h.Write(persbuf[:]) + h.Write([]byte{0}) + h.Write(input) + h.Write([]byte{0}) + h.Write(miner.Bytes()) + + return h.Sum(nil), nil +} + +func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, input, vrfproof []byte) error { + ctx, span := trace.StartSpan(ctx, "VerifyVRF") + defer span.End() + + vrfBase, err := hashVRFBase(p, miner, input) + if err != nil { + return xerrors.Errorf("computing vrf base failed: %w", err) + } + + sig := &types.Signature{ + Type: types.KTBLS, + Data: vrfproof, + } + + if err := sig.Verify(worker, vrfBase); err != nil { + return xerrors.Errorf("vrf was invalid: %w", err) + } + + return nil +} + +func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Address, p uint64, input []byte) ([]byte, error) { + sigInput, err := hashVRFBase(p, miner, input) + if err != nil { + return nil, err + } + + sig, err := sign(ctx, worker, sigInput) if err != nil { return nil, err } @@ -427,11 +552,15 @@ func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []b return sig.Data, nil } -func TicketHash(t *types.Ticket, round uint64) []byte { +func TicketHash(t *types.Ticket, addr address.Address) []byte { h := sha256.New() + h.Write(t.VRFProof) - var roundbuf [8]byte - binary.LittleEndian.PutUint64(roundbuf[:], round) - h.Write(roundbuf[:]) + + // Field Delimeter + h.Write([]byte{0}) + + h.Write(addr.Bytes()) + return h.Sum(nil) } diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 51036ad5b..5789de2a2 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -18,7 +18,7 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" ) -func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) { +func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, timestamp uint64) (*types.FullBlock, error) { st, recpts, err := sm.TipSetState(ctx, parents) if err != nil { return nil, xerrors.Errorf("failed to load tipset state: %w", err) @@ -35,7 +35,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal Ticket: ticket, Height: height, Timestamp: timestamp, - ElectionProof: proof, + EPostProof: *proof, ParentStateRoot: st, ParentMessageReceipts: recpts, } diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 1a86e0d1f..38591870d 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -383,9 +383,12 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B } b := &types.BlockHeader{ - Miner: actors.InitAddress, - Ticket: genesisticket, - ElectionProof: []byte("the Genesis block"), + Miner: actors.InitAddress, + Ticket: genesisticket, + EPostProof: types.EPostProof{ + Proof: []byte("not a real proof"), + PostRand: []byte("i guess this is kinda random"), + }, Parents: []cid.Cid{}, Height: 0, ParentWeight: types.NewInt(0), diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index b507fd387..6540e86ed 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -7,6 +7,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sectorbuilder" amt "github.com/filecoin-project/go-amt-ipld" cid "github.com/ipfs/go-cid" @@ -177,6 +178,26 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors) } +func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedSectorInfo, error) { + sectors, err := GetMinerSectorSet(ctx, sm, ts, maddr) + if err != nil { + return nil, xerrors.Errorf("failed to get sector set for miner: %w", err) + } + + var uselessOtherArray []sectorbuilder.SectorInfo + for _, s := range sectors { + var uselessBuffer [32]byte + copy(uselessBuffer[:], s.CommR) + uselessOtherArray = append(uselessOtherArray, sectorbuilder.SectorInfo{ + SectorID: s.SectorID, + CommR: uselessBuffer, + }) + } + + ssi := sectorbuilder.NewSortedSectorInfo(uselessOtherArray) + return &ssi, nil +} + func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) diff --git a/chain/store/store.go b/chain/store/store.go index 8f42390d5..5b047a38f 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -770,7 +770,7 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) { return NewFullTipSet(out), nil } -func ticketHash(t *types.Ticket, round int64) []byte { +func drawRandomness(t *types.Ticket, round int64) []byte { h := sha256.New() var buf [8]byte binary.LittleEndian.PutUint64(buf[:], uint64(round)) @@ -795,7 +795,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i mtb := nts.MinTicketBlock() if int64(nts.Height()) <= round { - return ticketHash(nts.MinTicketBlock().Ticket, round), nil + return drawRandomness(nts.MinTicketBlock().Ticket, round), nil } // special case for lookback behind genesis block @@ -803,7 +803,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round i if mtb.Height == 0 { // round is negative - thash := ticketHash(mtb.Ticket, round*-1) + thash := drawRandomness(mtb.Ticket, round*-1) // for negative lookbacks, just use the hash of the positive tickethash value h := sha256.Sum256(thash) diff --git a/chain/sync.go b/chain/sync.go index c804afcd3..af915cfba 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -32,6 +32,7 @@ import ( "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sectorbuilder" ) var log = logging.Logger("chain") @@ -467,23 +468,8 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b return nil } -func (syncer *Syncer) validateTicket(ctx context.Context, mworker address.Address, ticket *types.Ticket, base *types.TipSet, round uint64) error { - ctx, span := trace.StartSpan(ctx, "validateTickets") - defer span.End() - - sig := &types.Signature{ - Type: types.KTBLS, - Data: ticket.VRFProof, - } - - vrfBase := gen.TicketHash(base.MinTicket(), round) - - // TODO: ticket signatures should also include miner address - if err := sig.Verify(mworker, vrfBase); err != nil { - return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err) - } - - return nil +func (syncer *Syncer) validateTicket(ctx context.Context, maddr, mworker address.Address, ticket *types.Ticket, base *types.TipSet) error { + return gen.VerifyVRF(ctx, mworker, maddr, gen.DSepTicket, base.MinTicket().VRFProof, ticket.VRFProof) } var ErrTemporal = errors.New("temporal error") @@ -515,13 +501,20 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } winnerCheck := async.Err(func() error { - mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) + _, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) if err != nil { return xerrors.Errorf("failed getting power: %w", err) } - if !types.PowerCmp(h.ElectionProof, mpow, tpow) { - return xerrors.Errorf("miner created a block but was not a winner") + ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner) + if err != nil { + return xerrors.Errorf("failed to get sector size for block miner: %w", err) + } + + for _, t := range h.EPostProof.Winners { + if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) { + return xerrors.Errorf("miner created a block but was not a winner") + } } return nil }) @@ -578,20 +571,15 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) tktsCheck := async.Err(func() error { - if err := syncer.validateTicket(ctx, waddr, h.Ticket, baseTs, h.Height); err != nil { + if err := syncer.validateTicket(ctx, h.Miner, waddr, h.Ticket, baseTs); err != nil { return xerrors.Errorf("validating block tickets failed: %w", err) } return nil }) eproofCheck := async.Err(func() error { - rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback)) - if err != nil { - return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) - } - - if err := VerifyElectionProof(ctx, h.ElectionProof, rand, waddr); err != nil { - return xerrors.Errorf("checking eproof failed: %w", err) + if err := syncer.VerifyElectionPoStProof(ctx, h, baseTs, waddr); err != nil { + return xerrors.Errorf("invalid election post: %w", err) } return nil }) @@ -615,6 +603,49 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return merr } +func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, baseTs *types.TipSet, waddr address.Address) error { + rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback)) + if err != nil { + return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) + } + + if err := VerifyElectionPoStVRF(ctx, h.EPostProof.PostRand, rand, waddr, h.Miner); err != nil { + return xerrors.Errorf("checking eproof failed: %w", err) + } + + ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner) + if err != nil { + return xerrors.Errorf("failed to get sector size for miner: %w", err) + } + + var winners []sectorbuilder.EPostCandidate + for _, t := range h.EPostProof.Winners { + var partial [32]byte + copy(partial[:], t.Partial) + winners = append(winners, sectorbuilder.EPostCandidate{ + PartialTicket: partial, + SectorID: t.SectorID, + SectorChallengeIndex: t.ChallengeIndex, + }) + } + + sectorInfo, err := stmgr.GetSectorsForElectionPost(ctx, syncer.sm, baseTs, h.Miner) + if err != nil { + return xerrors.Errorf("getting election post sector set: %w", err) + } + + ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, waddr) + if err != nil { + return xerrors.Errorf("failed to verify election post: %w", err) + } + + if !ok { + return xerrors.Errorf("election post was invalid") + } + + return nil +} + func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error { nonces := make(map[address.Address]uint64) balances := make(map[address.Address]types.BigInt) @@ -1058,14 +1089,9 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet) error return nil } -func VerifyElectionProof(ctx context.Context, eproof []byte, rand []byte, worker address.Address) error { - sig := types.Signature{ - Data: eproof, - Type: types.KTBLS, - } - - if err := sig.Verify(worker, rand); err != nil { - return xerrors.Errorf("failed to verify election proof signature: %w", err) +func VerifyElectionPoStVRF(ctx context.Context, evrf []byte, rand []byte, worker, miner address.Address) error { + if err := gen.VerifyVRF(ctx, worker, miner, gen.DSepElectionPost, rand, evrf); err != nil { + return xerrors.Errorf("failed to verify post_randomness vrf: %w", err) } return nil diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index c0fc59214..9cac4fd42 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -20,14 +20,24 @@ type Ticket struct { VRFProof []byte } -type ElectionProof []byte +type EPostTicket struct { + Partial []byte + SectorID uint64 + ChallengeIndex uint64 +} + +type EPostProof struct { + Proof []byte + PostRand []byte + Winners []EPostTicket +} type BlockHeader struct { Miner address.Address Ticket *Ticket - ElectionProof []byte + EPostProof EPostProof Parents []cid.Cid @@ -162,29 +172,31 @@ func CidArrsEqual(a, b []cid.Cid) bool { var blocksPerEpoch = NewInt(build.BlocksPerEpoch) -func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool { +func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt, sampleRate int64) bool { + ssize := NewInt(ssizeI) /* Need to check that - (h(vrfout) + 1) / (max(h) + 1) <= e * minerPower / totalPower + (h(vrfout) + 1) / (max(h) + 1) <= e * sectorSize / totalPower max(h) == 2^256-1 which in terms of integer math means: - (h(vrfout) + 1) * totalPower <= e * minerPower * 2^256 + (h(vrfout) + 1) * totalPower <= e * sectorSize * 2^256 in 2^256 space, it is equivalent to: - h(vrfout) * totalPower < e * minerPower * 2^256 + h(vrfout) * totalPower < e * sectorSize * 2^256 */ - h := sha256.Sum256(eproof) + h := sha256.Sum256(partialTicket) lhs := BigFromBytes(h[:]).Int lhs = lhs.Mul(lhs, totpow.Int) + lhs = lhs.Mul(lhs, big.NewInt(sampleRate)) - // rhs = minerPower * 2^256 - // rhs = minerPower << 256 - rhs := new(big.Int).Lsh(mpow.Int, 256) + // rhs = sectorSize * 2^256 + // rhs = sectorSize << 256 + rhs := new(big.Int).Lsh(ssize.Int, 256) rhs = rhs.Mul(rhs, blocksPerEpoch.Int) - // h(vrfout) * totalPower < e * minerPower * 2^256? + // h(vrfout) * totalPower < e * sectorSize * 2^256? return lhs.Cmp(rhs) == -1 } diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index 6c41f3b4b..60f8b7770 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -23,8 +23,10 @@ func testBlockHeader(t testing.TB) *BlockHeader { } return &BlockHeader{ - Miner: addr, - ElectionProof: []byte("cats won the election"), + Miner: addr, + EPostProof: EPostProof{ + Proof: []byte("pruuf"), + }, Ticket: &Ticket{ VRFProof: []byte("vrf proof0000000vrf proof0000000"), }, diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index a0af53450..aa821245c 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -33,11 +33,8 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error { return err } - // t.t.ElectionProof ([]uint8) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.ElectionProof)))); err != nil { - return err - } - if _, err := w.Write(t.ElectionProof); err != nil { + // t.t.EPostProof (types.EPostProof) (struct) + if err := t.EPostProof.MarshalCBOR(w); err != nil { return err } @@ -141,22 +138,14 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error { } } - // t.t.ElectionProof ([]uint8) (slice) + // t.t.EPostProof (types.EPostProof) (struct) - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.ElectionProof: array too large (%d)", extra) - } + { + + if err := t.EPostProof.UnmarshalCBOR(br); err != nil { + return err + } - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.ElectionProof = make([]byte, extra) - if _, err := io.ReadFull(br, t.ElectionProof); err != nil { - return err } // t.t.Parents ([]cid.Cid) (slice) @@ -335,6 +324,205 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error { return nil } +func (t *EPostProof) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{131}); err != nil { + return err + } + + // t.t.Proof ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil { + return err + } + if _, err := w.Write(t.Proof); err != nil { + return err + } + + // t.t.PostRand ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil { + return err + } + if _, err := w.Write(t.PostRand); err != nil { + return err + } + + // t.t.Winners ([]types.EPostTicket) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Winners)))); err != nil { + return err + } + for _, v := range t.Winners { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + return nil +} + +func (t *EPostProof) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.t.Proof ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.Proof: array too large (%d)", extra) + } + + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Proof = make([]byte, extra) + if _, err := io.ReadFull(br, t.Proof); err != nil { + return err + } + // t.t.PostRand ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.PostRand: array too large (%d)", extra) + } + + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.PostRand = make([]byte, extra) + if _, err := io.ReadFull(br, t.PostRand); err != nil { + return err + } + // t.t.Winners ([]types.EPostTicket) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.Winners: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + if extra > 0 { + t.Winners = make([]EPostTicket, extra) + } + for i := 0; i < int(extra); i++ { + + var v EPostTicket + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Winners[i] = v + } + + return nil +} + +func (t *EPostTicket) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{131}); err != nil { + return err + } + + // t.t.Partial ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil { + return err + } + if _, err := w.Write(t.Partial); err != nil { + return err + } + + // t.t.SectorID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil { + return err + } + + // t.t.ChallengeIndex (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ChallengeIndex))); err != nil { + return err + } + return nil +} + +func (t *EPostTicket) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.t.Partial ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.Partial: array too large (%d)", extra) + } + + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Partial = make([]byte, extra) + if _, err := io.ReadFull(br, t.Partial); err != nil { + return err + } + // t.t.SectorID (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.SectorID = uint64(extra) + // t.t.ChallengeIndex (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.ChallengeIndex = uint64(extra) + return nil +} + func (t *Message) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index 474d8a92b..37d2e8a53 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -34,8 +34,10 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types } return &types.BlockHeader{ - Miner: addr, - ElectionProof: []byte("cats won the election"), + Miner: addr, + EPostProof: types.EPostProof{ + Proof: []byte("election post proof proof"), + }, Ticket: &types.Ticket{ VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)), }, diff --git a/extern/go-bls-sigs b/extern/go-bls-sigs index 98479d3c7..1c177e24f 160000 --- a/extern/go-bls-sigs +++ b/extern/go-bls-sigs @@ -1 +1 @@ -Subproject commit 98479d3c79620f18783da0c2c6a15f8b8eb4fa2e +Subproject commit 1c177e24fd71669a1c8cc2e0ce4ba6e247e34d77 diff --git a/extern/go-sectorbuilder b/extern/go-sectorbuilder index 40278d4a6..33fb89c5e 160000 --- a/extern/go-sectorbuilder +++ b/extern/go-sectorbuilder @@ -1 +1 @@ -Subproject commit 40278d4a6623e4c81003e20444871c9362bedd61 +Subproject commit 33fb89c5efe02a250508e95114836bd13dd3067e diff --git a/gen/main.go b/gen/main.go index c74a10f0f..48668d6da 100644 --- a/gen/main.go +++ b/gen/main.go @@ -20,6 +20,8 @@ func main() { err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types", types.BlockHeader{}, types.Ticket{}, + types.EPostProof{}, + types.EPostTicket{}, types.Message{}, types.SignedMessage{}, types.MsgMeta{}, diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 4383ddb57..3f3eeac2d 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -47,6 +47,8 @@ type PublicPieceInfo = sectorbuilder.PublicPieceInfo type RawSealPreCommitOutput = sectorbuilder.RawSealPreCommitOutput +type EPostCandidate = sectorbuilder.Candidate + const CommLen = sectorbuilder.CommitmentBytesLen type SectorBuilder struct { @@ -333,16 +335,36 @@ func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) { return out, nil } +/* func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { // Wait, this is a blocking method with no way of interrupting it? // does it checkpoint itself? return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, challengeSeed, faults) } +*/ func (sb *SectorBuilder) SectorSize() uint64 { return sb.ssize } +func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedSectorInfo, challengeSeed []byte, winners []EPostCandidate) ([]byte, error) { + if len(challengeSeed) != CommLen { + return nil, xerrors.Errorf("given challenge seed was the wrong length: %d != %d", len(challengeSeed), CommLen) + } + var cseed [CommLen]byte + copy(cseed[:], challengeSeed) + + return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, winners) +} + +func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { + return sectorbuilder.GenerateCandidates(sb.handle, sectorInfo, challengeSeed, faults) +} + +func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { + panic("NYI") +} + var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address, ticket []byte, seed []byte, sectorID uint64, proof []byte) (bool, error) { @@ -360,10 +382,14 @@ func NewSortedSectorInfo(sectors []SectorInfo) SortedSectorInfo { return sectorbuilder.NewSortedSectorInfo(sectors...) } -func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, proof []byte, faults []uint64) (bool, error) { +func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) { + var challengeSeeda [CommLen]byte + copy(challengeSeeda[:], challengeSeed) + _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() - return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeed, proof, faults) + prover := addressToProverID(proverID) + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, proof, winners, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { diff --git a/miner/miner.go b/miner/miner.go index 1a394da2b..47958bab1 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -47,6 +47,8 @@ func NewMiner(api api) *Miner { type Miner struct { api api + epp gen.ElectionPoStProver + lk sync.Mutex addresses []address.Address stop chan struct{} @@ -248,12 +250,12 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) { log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids())) - ticket, err := m.scratchTicket(ctx, addr, base) + ticket, err := m.computeTicket(ctx, addr, base) if err != nil { return nil, errors.Wrap(err, "scratching ticket failed") } - win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, &m.api) + win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, &m.api) if err != nil { return nil, errors.Wrap(err, "failed to check if we win next round") } @@ -278,7 +280,7 @@ func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []by return nil, err } - return gen.ComputeVRF(ctx, m.api.WalletSign, w, input) + return gen.ComputeVRF(ctx, m.api.WalletSign, w, addr, gen.DSepTicket, input) } func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { @@ -303,10 +305,9 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty return w, nil } -func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { - round := base.ts.Height() + base.nullRounds + 1 +func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { - vrfBase := gen.TicketHash(base.ts.MinTicket(), round) + vrfBase := gen.TicketHash(base.ts.MinTicket(), addr) vrfOut, err := m.computeVRF(ctx, addr, vrfBase) if err != nil { @@ -318,7 +319,7 @@ func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *M }, nil } -func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof types.ElectionProof) (*types.BlockMsg, error) { +func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) { pending, err := m.api.MpoolPending(context.TODO(), base.ts) if err != nil { diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 38d9490b7..844220475 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -177,7 +177,7 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ } // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner -func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { +func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts) if err != nil { return nil, err diff --git a/storage/post.go b/storage/post.go index be2d06eac..4f73b8af2 100644 --- a/storage/post.go +++ b/storage/post.go @@ -193,7 +193,7 @@ func (p *post) runPost(ctx context.Context) error { var seed [32]byte copy(seed[:], p.r) - proof, err := p.m.sb.GeneratePoSt(p.sortedSectorInfo(), seed, faults) + proof, err := p.m.sb.GenerateFallbackPoSt(p.sortedSectorInfo(), seed, faults) if err != nil { return xerrors.Errorf("running post failed: %w", err) } @@ -209,8 +209,9 @@ func (p *post) commitPost(ctx context.Context) error { ctx, span := trace.StartSpan(ctx, "storage.commitPost") defer span.End() + panic("NYI") params := &actors.SubmitPoStParams{ - Proof: p.proof, + //Proof: p.proof, DoneSet: types.BitFieldFromSet(nil), } From f03198c8a04ba800008cb3bde4962f5b2b7834ac Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 22 Nov 2019 10:41:09 -0600 Subject: [PATCH 05/93] sync tests passing, still no vm integration --- build/testing_flags.go | 3 +++ chain/actors/actor_miner.go | 6 +++--- chain/gen/gen.go | 4 +++- chain/gen/utils.go | 9 +++++++++ chain/sync.go | 9 +++++++++ chain/sync_test.go | 4 ++++ chain/types/vmcontext.go | 10 +++++----- go.mod | 2 +- go.sum | 2 ++ miner/miner.go | 1 + 10 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 build/testing_flags.go diff --git a/build/testing_flags.go b/build/testing_flags.go new file mode 100644 index 000000000..1f26121e7 --- /dev/null +++ b/build/testing_flags.go @@ -0,0 +1,3 @@ +package build + +var InsecurePoStValidation = false diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index b5442b1fa..853d048af 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -345,7 +345,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC // Note: There must exist a unique index in the miner's sector set for each // sector ID. The `faults`, `recovered`, and `done` parameters of the // SubmitPoSt method express indices into this sector set. - nssroot, err := AddToSectorSet(ctx, vmctx.Storage(), self.Sectors, params.SectorID, us.Info.CommR, commD) + nssroot, err := AddToSectorSet(ctx, types.WrapStorage(vmctx.Storage()), self.Sectors, params.SectorID, us.Info.CommR, commD) if err != nil { return nil, err } @@ -593,8 +593,8 @@ func SectorIsUnique(ctx context.Context, s types.Storage, sroot cid.Cid, sid uin return !found, nil } -func AddToSectorSet(ctx context.Context, s types.Storage, ss cid.Cid, sectorID uint64, commR, commD []byte) (cid.Cid, ActorError) { - ssr, err := amt.LoadAMT(types.WrapStorage(s), ss) +func AddToSectorSet(ctx context.Context, blks amt.Blocks, ss cid.Cid, sectorID uint64, commR, commD []byte) (cid.Cid, ActorError) { + ssr, err := amt.LoadAMT(blks, ss) if err != nil { return cid.Undef, aerrors.HandleExternalError(err, "could not load sector set node") } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index e0db5e1ec..741af0351 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -408,6 +408,7 @@ type ElectionPoStProver interface { } type eppProvider struct { + sectors []sectorbuilder.SectorInfo } func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { @@ -422,7 +423,8 @@ func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ( } func (epp *eppProvider) ComputeProof(ctx context.Context, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { - return []byte("this is an election post proof"), nil + + return []byte("valid proof"), nil } func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *types.EPostProof, error) { diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 38591870d..754275208 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -291,6 +291,15 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid } mstate.Power = types.NewInt(5000) + commD := make([]byte, 32) + commR := make([]byte, 32) + blks := amt.WrapBlockstore(cs.Blockstore()) + nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, 1, commD, commR) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to add fake sector to sector set: %w", err) + } + mstate.Sectors = nssroot + nstate, err := cst.Put(ctx, &mstate) if err != nil { return cid.Undef, err diff --git a/chain/sync.go b/chain/sync.go index af915cfba..8608e717d 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -478,6 +478,9 @@ var ErrTemporal = errors.New("temporal error") func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error { ctx, span := trace.StartSpan(ctx, "validateBlock") defer span.End() + if build.InsecurePoStValidation { + log.Warn("insecure test validation is enabled, if you see this outside of a test, it is a severe bug!") + } h := b.Header @@ -634,6 +637,12 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc return xerrors.Errorf("getting election post sector set: %w", err) } + if build.InsecurePoStValidation { + if string(h.EPostProof.Proof) == "valid proof" { + return nil + } + return xerrors.Errorf("[TESTING] election post was invalid") + } ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, waddr) if err != nil { return xerrors.Errorf("failed to verify election post: %w", err) diff --git a/chain/sync_test.go b/chain/sync_test.go index c5cf21c1e..49e26774a 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -23,6 +23,10 @@ import ( "github.com/filecoin-project/lotus/node/repo" ) +func init() { + build.InsecurePoStValidation = true +} + const source = 0 func (tu *syncTestUtil) repoWithChain(t testing.TB, h int) (repo.Repo, []byte, []*store.FullTipSet) { diff --git a/chain/types/vmcontext.go b/chain/types/vmcontext.go index 388396881..5e2963483 100644 --- a/chain/types/vmcontext.go +++ b/chain/types/vmcontext.go @@ -3,7 +3,7 @@ package types import ( "context" - amt "github.com/filecoin-project/go-amt-ipld" + "github.com/filecoin-project/go-amt-ipld" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/address" cid "github.com/ipfs/go-cid" @@ -48,8 +48,8 @@ type storageWrapper struct { s Storage } -func (sw *storageWrapper) Put(i interface{}) (cid.Cid, error) { - c, err := sw.s.Put(i.(cbg.CBORMarshaler)) +func (sw *storageWrapper) Put(i cbg.CBORMarshaler) (cid.Cid, error) { + c, err := sw.s.Put(i) if err != nil { return cid.Undef, err } @@ -57,8 +57,8 @@ func (sw *storageWrapper) Put(i interface{}) (cid.Cid, error) { return c, nil } -func (sw *storageWrapper) Get(c cid.Cid, out interface{}) error { - if err := sw.s.Get(c, out.(cbg.CBORUnmarshaler)); err != nil { +func (sw *storageWrapper) Get(c cid.Cid, out cbg.CBORUnmarshaler) error { + if err := sw.s.Get(c, out); err != nil { return err } diff --git a/go.mod b/go.mod index 676e52615..37ef67f4d 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a // indirect github.com/fatih/color v1.7.0 // indirect github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7 - github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16 + github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 github.com/filecoin-project/go-bls-sigs v0.0.0-20190718224239-4bc4b8a7bbf8 github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 github.com/filecoin-project/go-sectorbuilder v0.0.0-00010101000000-000000000000 diff --git a/go.sum b/go.sum index 3e34b558a..f095026ec 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7 github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7/go.mod h1:0/0/QUNqpF/jVzLHFncGeT3NvGPODBhGzQlNgzmoZew= github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16 h1:NzojcJU1VbS6zdLG13JMYis/cQy/MrN3rxmZRq56jKA= github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= +github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 h1:lKSMm8Go6qI7+Dk3rWCNIh57wBOqVNJ21re/p7D58gc= +github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/miner/miner.go b/miner/miner.go index 47958bab1..56f78e5fe 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -36,6 +36,7 @@ type api struct { func NewMiner(api api) *Miner { return &Miner{ api: api, + epp: nil, waitFunc: func(ctx context.Context) error { // Wait around for half the block time in case other parents come in time.Sleep(build.BlockDelay * time.Second / 2) From 96023d415efcc3dd191c555ea48821ea5df0b809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 22 Nov 2019 23:51:44 +0100 Subject: [PATCH 06/93] actors: Implement cron actor --- chain/actors/actor_cron.go | 48 ++++++++++++++++++++++++++++++ chain/actors/actor_init.go | 2 +- chain/actors/actor_storagepower.go | 4 +-- chain/actors/actors.go | 3 ++ chain/actors/cbor_gen.go | 29 ++++++++++++++++++ chain/blocksync/cbor_gen.go | 2 +- chain/gen/utils.go | 26 ++++++++++++++++ chain/stmgr/stmgr.go | 13 ++++---- chain/types/cbor_gen.go | 2 +- chain/vm/invoker.go | 1 + gen/main.go | 1 + 11 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 chain/actors/actor_cron.go diff --git a/chain/actors/actor_cron.go b/chain/actors/actor_cron.go new file mode 100644 index 000000000..8f9a08ade --- /dev/null +++ b/chain/actors/actor_cron.go @@ -0,0 +1,48 @@ +package actors + +import ( + "github.com/filecoin-project/lotus/chain/actors/aerrors" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/types" +) + +type CronActor struct{} + +type callTuple struct { + addr address.Address + method uint64 +} + +var CronActors = []callTuple{ + {StoragePowerAddress, SPAMethods.CheckProofSubmissions}, +} + +type CronActorState struct{} + +type cAMethods struct { + EpochTick uint64 +} + +var CAMethods = cAMethods{2} + +func (ca CronActor) Exports() []interface{} { + return []interface{}{ + 1: nil, + 2: ca.EpochTick, + } +} + +func (ca CronActor) EpochTick(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) { + if vmctx.Message().From != CronAddress { + return nil, aerrors.New(1, "EpochTick is only callable as a part of tipset state computation") + } + + for _, call := range CronActors { + _, err := vmctx.Send(call.addr, call.method, types.NewInt(0), nil) + if err != nil { + return nil, err // todo: this very bad? + } + } + + return nil, nil +} diff --git a/chain/actors/actor_init.go b/chain/actors/actor_init.go index 66d9d98fa..e040e5899 100644 --- a/chain/actors/actor_init.go +++ b/chain/actors/actor_init.go @@ -170,7 +170,7 @@ func IsBuiltinActor(code cid.Cid) bool { } func IsSingletonActor(code cid.Cid) bool { - return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid + return code == StoragePowerCodeCid || code == StorageMarketCodeCid || code == InitCodeCid || code == CronCodeCid } func (ias *InitActorState) AddActor(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) { diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index e76cdd054..1e2b1915b 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -567,8 +567,8 @@ func pledgeCollateralForSize(vmctx types.VMContext, size, totalStorage types.Big } func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types.VMContext, param *struct{}) ([]byte, ActorError) { - if vmctx.Message().From != StoragePowerAddress { - return nil, aerrors.New(1, "CheckProofSubmissions is only callable as a part of tipset state computation") + if vmctx.Message().From != CronAddress { + return nil, aerrors.New(1, "CheckProofSubmissions is only callable from the cron actor") } var self StoragePowerState diff --git a/chain/actors/actors.go b/chain/actors/actors.go index fe111c125..19de6a383 100644 --- a/chain/actors/actors.go +++ b/chain/actors/actors.go @@ -8,6 +8,7 @@ import ( ) var AccountCodeCid cid.Cid +var CronCodeCid cid.Cid var StoragePowerCodeCid cid.Cid var StorageMarketCodeCid cid.Cid var StorageMinerCodeCid cid.Cid @@ -19,6 +20,7 @@ var InitAddress = mustIDAddress(0) var NetworkAddress = mustIDAddress(1) var StoragePowerAddress = mustIDAddress(2) var StorageMarketAddress = mustIDAddress(3) // TODO: missing from spec +var CronAddress = mustIDAddress(4) var BurntFundsAddress = mustIDAddress(99) func mustIDAddress(i uint64) address.Address { @@ -40,6 +42,7 @@ func init() { } AccountCodeCid = mustSum("fil/1/account") // TODO: spec + CronCodeCid = mustSum("fil/1/cron") StoragePowerCodeCid = mustSum("fil/1/power") StorageMarketCodeCid = mustSum("fil/1/market") StorageMinerCodeCid = mustSum("fil/1/miner") diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 53de185e1..2dee0debd 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -3976,3 +3976,32 @@ func (t *CheckMinerParams) UnmarshalCBOR(r io.Reader) error { } return nil } + +func (t *CronActorState) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{128}); err != nil { + return err + } + return nil +} + +func (t *CronActorState) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 0 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + return nil +} diff --git a/chain/blocksync/cbor_gen.go b/chain/blocksync/cbor_gen.go index 579b3f857..4af61a490 100644 --- a/chain/blocksync/cbor_gen.go +++ b/chain/blocksync/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "github.com/filecoin-project/lotus/chain/types" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index f60da262d..cd7f6834b 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -89,6 +89,15 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types return nil, xerrors.Errorf("set init actor: %w", err) } + cronact, err := SetupCronActor(bs) + if err != nil { + return nil, xerrors.Errorf("setup cron actor: %w", err) + } + + if err := state.SetActor(actors.CronAddress, cronact); err != nil { + return nil, xerrors.Errorf("set cron actor: %w", err) + } + spact, err := SetupStoragePowerActor(bs) if err != nil { return nil, xerrors.Errorf("setup storage market actor: %w", err) @@ -144,6 +153,23 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types return state, nil } +func SetupCronActor(bs bstore.Blockstore) (*types.Actor, error) { + cst := hamt.CSTFromBstore(bs) + cas := &actors.CronActorState{} + + stcid, err := cst.Put(context.TODO(), cas) + if err != nil { + return nil, err + } + + return &types.Actor{ + Code: actors.CronCodeCid, + Head: stcid, + Nonce: 0, + Balance: types.NewInt(0), + }, nil +} + func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) { cst := hamt.CSTFromBstore(bs) nd := hamt.NewNode(cst) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index eaaa4fc13..62efca8a6 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -197,21 +197,20 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl } } - // TODO: this nonce-getting is a ting bit ugly - spa, err := vmi.StateTree().GetActor(actors.StoragePowerAddress) + // TODO: this nonce-getting is a tiny bit ugly + ca, err := vmi.StateTree().GetActor(actors.CronAddress) if err != nil { return cid.Undef, cid.Undef, err } - // TODO: cron actor ret, err := vmi.ApplyMessage(ctx, &types.Message{ - To: actors.StoragePowerAddress, - From: actors.StoragePowerAddress, - Nonce: spa.Nonce, + To: actors.CronAddress, + From: actors.CronAddress, + Nonce: ca.Nonce, Value: types.NewInt(0), GasPrice: types.NewInt(0), GasLimit: types.NewInt(1 << 30), // Make super sure this is never too little - Method: actors.SPAMethods.CheckProofSubmissions, + Method: actors.CAMethods.EpochTick, Params: nil, }) if err != nil { diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index fa3cddaf4..1ebe94a13 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "math" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 3fa02d4c1..d33f70750 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -31,6 +31,7 @@ func newInvoker() *invoker { // add builtInCode using: register(cid, singleton) inv.register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{}) + inv.register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{}) inv.register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{}) inv.register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{}) inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{}) diff --git a/gen/main.go b/gen/main.go index c74a10f0f..98f4424ca 100644 --- a/gen/main.go +++ b/gen/main.go @@ -129,6 +129,7 @@ func main() { actors.ComputeDataCommitmentParams{}, actors.SectorProveCommitInfo{}, actors.CheckMinerParams{}, + actors.CronActorState{}, ) if err != nil { fmt.Println(err) From a0588d513d370fe7120c943155294be095d112d9 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sun, 24 Nov 2019 22:45:13 -0600 Subject: [PATCH 07/93] Add lotus-gen, rewire genesis mining --- api/api_full.go | 3 - api/struct.go | 15 -- build/params.go | 4 + chain/actors/actor_miner.go | 228 +++++++++++++++--------- chain/actors/cbor_gen.go | 44 +---- chain/gen/gen.go | 40 ++++- chain/gen/utils.go | 25 ++- chain/stmgr/stmgr.go | 26 ++- chain/stmgr/utils.go | 11 +- chain/store/weight.go | 1 + cli/cmd.go | 1 - cli/miner.go | 32 ---- cmd/lotus-seed/main.go | 162 +++++++++++++++++ cmd/lotus-storage-miner/init.go | 110 +++++++++--- cmd/lotus/daemon.go | 13 +- extern/go-sectorbuilder | 2 +- genesis/types.go | 15 ++ go.mod | 1 + go.sum | 1 + lib/sectorbuilder/sectorbuilder.go | 56 ++++-- lib/sectorbuilder/sectorbuilder_test.go | 36 ++-- miner/miner.go | 23 +-- miner/testminer.go | 6 +- node/builder.go | 7 +- node/impl/full.go | 18 -- node/impl/storminer.go | 6 +- node/modules/storageminer.go | 20 ++- node/modules/testing/genesis.go | 22 ++- storage/miner.go | 23 +++ storage/post.go | 57 +++--- 30 files changed, 675 insertions(+), 333 deletions(-) delete mode 100644 cli/miner.go create mode 100644 cmd/lotus-seed/main.go create mode 100644 genesis/types.go diff --git a/api/api_full.go b/api/api_full.go index 47e2f71d7..a5582b093 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -49,9 +49,6 @@ type FullNode interface { // miner - MinerRegister(context.Context, address.Address) error - MinerUnregister(context.Context, address.Address) error - MinerAddresses(context.Context) ([]address.Address, error) MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) // // UX ? diff --git a/api/struct.go b/api/struct.go index bbd200b7d..8ba0bc3b9 100644 --- a/api/struct.go +++ b/api/struct.go @@ -58,9 +58,6 @@ type FullNodeStruct struct { MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"` MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"` - MinerRegister func(context.Context, address.Address) error `perm:"admin"` - MinerUnregister func(context.Context, address.Address) error `perm:"admin"` - MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"` MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, *types.EPostProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"` WalletNew func(context.Context, string) (address.Address, error) `perm:"write"` @@ -225,18 +222,6 @@ func (c *FullNodeStruct) MpoolPushMessage(ctx context.Context, msg *types.Messag return c.Internal.MpoolPushMessage(ctx, msg) } -func (c *FullNodeStruct) MinerRegister(ctx context.Context, addr address.Address) error { - return c.Internal.MinerRegister(ctx, addr) -} - -func (c *FullNodeStruct) MinerUnregister(ctx context.Context, addr address.Address) error { - return c.Internal.MinerUnregister(ctx, addr) -} - -func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address, error) { - return c.Internal.MinerAddresses(ctx) -} - func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) { return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) } diff --git a/build/params.go b/build/params.go index 35ccd69f0..655a8ffc0 100644 --- a/build/params.go +++ b/build/params.go @@ -85,6 +85,10 @@ const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000 // Blocks const EcRandomnessLookback = 300 +const FallbackPoStBegin = 1000 +const SlashablePowerDelay = 2000 + + const PowerCollateralProportion = 5 const PerCapitaCollateralProportion = 1 const CollateralPrecision = 1000 diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 853d048af..885c24922 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -54,12 +54,6 @@ type StorageMinerActorState struct { // These become the currentFaultSet when a PoSt is submitted. NextFaultSet types.BitField - // Sectors reported during the last PoSt submission as being 'done'. - // The collateral for them is still being held until - // the next PoSt submission in case early sector - // removal penalization is needed. - NextDoneSet types.BitField - // Amount of power this miner has. Power types.BigInt @@ -69,7 +63,7 @@ type StorageMinerActorState struct { // The height at which this miner was slashed at. SlashedAt uint64 - ProvingPeriodEnd uint64 + ElectionPeriodStart uint64 } type MinerInfo struct { @@ -117,7 +111,7 @@ type maMethods struct { Constructor uint64 PreCommitSector uint64 ProveCommitSector uint64 - SubmitPoSt uint64 + SubmitFallbackPoSt uint64 SlashStorageFault uint64 GetCurrentProvingSet uint64 ArbitrateDeal uint64 @@ -133,16 +127,17 @@ type maMethods struct { CheckMiner uint64 DeclareFaults uint64 SlashConsensusFault uint64 + SubmitElectionPoSt uint64 } -var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} +var MAMethods = maMethods{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} func (sma StorageMinerActor) Exports() []interface{} { return []interface{}{ 1: sma.StorageMinerConstructor, 2: sma.PreCommitSector, 3: sma.ProveCommitSector, - 4: sma.SubmitPoSt, + 4: sma.SubmitFallbackPoSt, //5: sma.SlashStorageFault, //6: sma.GetCurrentProvingSet, //7: sma.ArbitrateDeal, @@ -158,6 +153,7 @@ func (sma StorageMinerActor) Exports() []interface{} { 17: sma.CheckMiner, 18: sma.DeclareFaults, 19: sma.SlashConsensusFault, + 20: sma.SubmitElectionPoSt, } } @@ -366,7 +362,9 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC if pss.Count == 0 { self.ProvingSet = self.Sectors - self.ProvingPeriodEnd = vmctx.BlockHeight() + build.ProvingPeriodDuration + // TODO: probably want to wait until the miner is above a certain + // threshold before starting this + self.ElectionPeriodStart = vmctx.BlockHeight() } nstate, err := vmctx.Storage().Put(self) @@ -389,8 +387,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC } type SubmitPoStParams struct { - Proof types.EPostProof - DoneSet types.BitField + Proof types.EPostProof } func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { @@ -401,7 +398,7 @@ func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { return end, period } -func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) { +func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) { oldstate, self, err := loadState(vmctx) if err != nil { return nil, err @@ -416,36 +413,28 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, return nil, aerrors.New(1, "not authorized to submit post for miner") } - currentProvingPeriodEnd, _ := ProvingPeriodEnd(self.ProvingPeriodEnd, vmctx.BlockHeight()) - - feesRequired := types.NewInt(0) - - if currentProvingPeriodEnd > self.ProvingPeriodEnd { - //TODO late fee calc - feesRequired = types.BigAdd(feesRequired, types.NewInt(1000)) - } - - //TODO temporary sector failure fees - - msgVal := vmctx.Message().Value - if msgVal.LessThan(feesRequired) { - return nil, aerrors.New(2, "not enough funds to pay post submission fees") - } - - if msgVal.GreaterThan(feesRequired) { - _, err := vmctx.Send(vmctx.Message().From, 0, - types.BigSub(msgVal, feesRequired), nil) - if err != nil { - return nil, aerrors.Wrap(err, "could not refund excess fees") + /* + // TODO: handle fees + msgVal := vmctx.Message().Value + if msgVal.LessThan(feesRequired) { + return nil, aerrors.New(2, "not enough funds to pay post submission fees") } - } + + if msgVal.GreaterThan(feesRequired) { + _, err := vmctx.Send(vmctx.Message().From, 0, + types.BigSub(msgVal, feesRequired), nil) + if err != nil { + return nil, aerrors.Wrap(err, "could not refund excess fees") + } + } + */ var seed [sectorbuilder.CommLen]byte { - randHeight := currentProvingPeriodEnd - build.PoStChallangeTime - build.PoStRandomnessLookback + randHeight := self.ElectionPeriodStart + build.FallbackPoStBegin if vmctx.BlockHeight() <= randHeight { // TODO: spec, retcode - return nil, aerrors.Newf(1, "submit PoSt called outside submission window (%d < %d)", vmctx.BlockHeight(), randHeight) + return nil, aerrors.Newf(1, "submit fallback PoSt called too early (%d < %d)", vmctx.BlockHeight(), randHeight) } rand, err := vmctx.GetRandomness(randHeight) @@ -465,13 +454,13 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, return nil, aerrors.HandleExternalError(lerr, "could not load proving set node") } - var sectorInfos []sectorbuilder.SectorInfo + var sectorInfos []sectorbuilder.PublicSectorInfo if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error { var comms [][]byte if err := cbor.DecodeInto(v.Raw, &comms); err != nil { return xerrors.New("could not decode comms") } - si := sectorbuilder.SectorInfo{ + si := sectorbuilder.PublicSectorInfo{ SectorID: id, } commR := comms[0] @@ -501,7 +490,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, proverID := vmctx.Message().To // TODO: normalize to ID address if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize, - sectorbuilder.NewSortedSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil { + sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil { if lerr != nil { // TODO: study PoST errors return nil, aerrors.Absorb(lerr, 4, "PoST error") @@ -510,26 +499,11 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, return nil, aerrors.New(4, "PoST invalid") } } + + // Post submission is successful! self.CurrentFaultSet = self.NextFaultSet self.NextFaultSet = types.NewBitField() - ss, lerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet) - if lerr != nil { - return nil, aerrors.HandleExternalError(lerr, "could not load proving set node") - } - - if err := ss.BatchDelete(params.DoneSet.All()); err != nil { - // TODO: this could fail for system reasons (block not found) or for - // bad user input reasons (e.g. bad doneset). The latter should be a - // non-fatal error - return nil, aerrors.HandleExternalError(err, "failed to delete sectors in done set") - } - - self.ProvingSet, lerr = ss.Flush() - if lerr != nil { - return nil, aerrors.HandleExternalError(lerr, "could not flush AMT") - } - oldPower := self.Power self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))), types.NewInt(mi.SectorSize)) @@ -540,16 +514,16 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, delta = self.Power } - prevPE := self.ProvingPeriodEnd + prevSlashingDeadline := self.ElectionPeriodStart + build.SlashablePowerDelay if !self.Active { self.Active = true - prevPE = 0 + prevSlashingDeadline = 0 } enc, err := SerializeParams(&UpdateStorageParams{ Delta: delta, - NextProvingPeriodEnd: currentProvingPeriodEnd + build.ProvingPeriodDuration, - PreviousProvingPeriodEnd: prevPE, + NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay, + PreviousProvingPeriodEnd: prevSlashingDeadline, }) if err != nil { return nil, err @@ -561,8 +535,7 @@ func (sma StorageMinerActor) SubmitPoSt(act *types.Actor, vmctx types.VMContext, } self.ProvingSet = self.Sectors - self.ProvingPeriodEnd = currentProvingPeriodEnd + build.ProvingPeriodDuration - self.NextDoneSet = params.DoneSet + self.ElectionPeriodStart = vmctx.BlockHeight() c, err := vmctx.Storage().Put(self) if err != nil { @@ -756,7 +729,7 @@ func (sma StorageMinerActor) GetSectorSize(act *types.Actor, vmctx types.VMConte } func isLate(height uint64, self *StorageMinerActorState) bool { - return self.ProvingPeriodEnd > 0 && height >= self.ProvingPeriodEnd // TODO: review: maybe > ? + return self.ElectionPeriodStart > 0 && height >= self.ElectionPeriodStart+build.SlashablePowerDelay } func (sma StorageMinerActor) IsSlashed(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) { @@ -824,32 +797,34 @@ type DeclareFaultsParams struct { } func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMContext, params *DeclareFaultsParams) ([]byte, ActorError) { - oldstate, self, aerr := loadState(vmctx) - if aerr != nil { - return nil, aerr - } - - challengeHeight := self.ProvingPeriodEnd - build.PoStChallangeTime - - if vmctx.BlockHeight() < challengeHeight { - // TODO: optimized bitfield methods - for _, v := range params.Faults.All() { - self.CurrentFaultSet.Set(v) + /* + oldstate, self, aerr := loadState(vmctx) + if aerr != nil { + return nil, aerr } - } else { - for _, v := range params.Faults.All() { - self.NextFaultSet.Set(v) + + challengeHeight := self.ProvingPeriodEnd - build.PoStChallangeTime + + if vmctx.BlockHeight() < challengeHeight { + // TODO: optimized bitfield methods + for _, v := range params.Faults.All() { + self.CurrentFaultSet.Set(v) + } + } else { + for _, v := range params.Faults.All() { + self.NextFaultSet.Set(v) + } } - } - nstate, err := vmctx.Storage().Put(self) - if err != nil { - return nil, err - } - if err := vmctx.Storage().Commit(oldstate, nstate); err != nil { - return nil, err - } + nstate, err := vmctx.Storage().Put(self) + if err != nil { + return nil, err + } + if err := vmctx.Storage().Commit(oldstate, nstate); err != nil { + return nil, err + } + */ return nil, nil } @@ -899,6 +874,85 @@ func (sma StorageMinerActor) SlashConsensusFault(act *types.Actor, vmctx types.V return nil, nil } +func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) { + if vmctx.Message().From != NetworkAddress { + return nil, aerrors.Newf(1, "submit election post can only be called by the storage power actor") + } + + oldstate, self, aerr := loadState(vmctx) + if aerr != nil { + return nil, aerr + } + + if err := onSuccessfulPoSt(self, vmctx); err != nil { + return nil, err + } + + ncid, err := vmctx.Storage().Put(self) + if err != nil { + return nil, err + } + if err := vmctx.Storage().Commit(oldstate, ncid); err != nil { + return nil, err + } + + return nil, nil +} + +func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerrors.ActorError { + // TODO: some sector upkeep stuff that is very haphazard and unclear in the spec + + var mi MinerInfo + if err := vmctx.Storage().Get(self.Info, &mi); err != nil { + return err + } + + pss, nerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingSet) + if nerr != nil { + return aerrors.HandleExternalError(nerr, "failed to load proving set") + } + + self.CurrentFaultSet = self.NextFaultSet + self.NextFaultSet = types.NewBitField() + + faults := []uint64{} // TODO + + oldPower := self.Power + self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))), + types.NewInt(mi.SectorSize)) + + delta := types.BigSub(self.Power, oldPower) + if self.SlashedAt != 0 { + self.SlashedAt = 0 + delta = self.Power + } + + prevSlashingDeadline := self.ElectionPeriodStart + build.SlashablePowerDelay + if !self.Active { + self.Active = true + prevSlashingDeadline = 0 + } + + fmt.Println("POWER UPDATE DELTA: ", delta) + enc, err := SerializeParams(&UpdateStorageParams{ + Delta: delta, + NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay, + PreviousProvingPeriodEnd: prevSlashingDeadline, + }) + if err != nil { + return err + } + + _, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc) + if err != nil { + return err + } + + self.ProvingSet = self.Sectors + self.ElectionPeriodStart = vmctx.BlockHeight() + return nil +} + func slasherShare(total types.BigInt, elapsed uint64) types.BigInt { // [int(pow(1.26, n) * 10) for n in range(30)] fracs := []uint64{10, 12, 15, 20, 25, 31, 40, 50, 63, 80, 100, 127, 160, 201, 254, 320, 403, 508, 640, 807, 1017, 1281, 1614, 2034, 2563, 3230, 4070, 5128, 6462, 8142} diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 522896008..8a8688208 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -198,7 +198,7 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{139}); err != nil { + if _, err := w.Write([]byte{138}); err != nil { return err } @@ -258,11 +258,6 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error { return err } - // t.t.NextDoneSet (types.BitField) (struct) - if err := t.NextDoneSet.MarshalCBOR(w); err != nil { - return err - } - // t.t.Power (types.BigInt) (struct) if err := t.Power.MarshalCBOR(w); err != nil { return err @@ -278,8 +273,8 @@ func (t *StorageMinerActorState) MarshalCBOR(w io.Writer) error { return err } - // t.t.ProvingPeriodEnd (uint64) (uint64) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ProvingPeriodEnd))); err != nil { + // t.t.ElectionPeriodStart (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ElectionPeriodStart))); err != nil { return err } return nil @@ -296,7 +291,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 11 { + if extra != 10 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -406,15 +401,6 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { return err } - } - // t.t.NextDoneSet (types.BitField) (struct) - - { - - if err := t.NextDoneSet.UnmarshalCBOR(br); err != nil { - return err - } - } // t.t.Power (types.BigInt) (struct) @@ -452,7 +438,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("wrong type for uint64 field") } t.SlashedAt = uint64(extra) - // t.t.ProvingPeriodEnd (uint64) (uint64) + // t.t.ElectionPeriodStart (uint64) (uint64) maj, extra, err = cbg.CborReadHeader(br) if err != nil { @@ -461,7 +447,7 @@ func (t *StorageMinerActorState) UnmarshalCBOR(r io.Reader) error { if maj != cbg.MajUnsignedInt { return fmt.Errorf("wrong type for uint64 field") } - t.ProvingPeriodEnd = uint64(extra) + t.ElectionPeriodStart = uint64(extra) return nil } @@ -832,7 +818,7 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{130}); err != nil { + if _, err := w.Write([]byte{129}); err != nil { return err } @@ -840,11 +826,6 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error { if err := t.Proof.MarshalCBOR(w); err != nil { return err } - - // t.t.DoneSet (types.BitField) (struct) - if err := t.DoneSet.MarshalCBOR(w); err != nil { - return err - } return nil } @@ -859,7 +840,7 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 2 { + if extra != 1 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -871,15 +852,6 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error { return err } - } - // t.t.DoneSet (types.BitField) (struct) - - { - - if err := t.DoneSet.UnmarshalCBOR(br); err != nil { - return err - } - } return nil } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 741af0351..c4eabdc18 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -366,6 +366,8 @@ type MiningCheckAPI interface { StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) + StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) + WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) } @@ -398,20 +400,24 @@ func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr) } +func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, ts *types.TipSet) ([]*api.ChainSectorInfo, error) { + return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr) +} + func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*types.Signature, error) { return mca.w.Sign(ctx, a, v) } type ElectionPoStProver interface { - GenerateCandidates(context.Context, []byte) ([]sectorbuilder.EPostCandidate, error) - ComputeProof(context.Context, []byte, []sectorbuilder.EPostCandidate) ([]byte, error) + GenerateCandidates(context.Context, sectorbuilder.SortedPublicSectorInfo, []byte) ([]sectorbuilder.EPostCandidate, error) + ComputeProof(context.Context, sectorbuilder.SortedPublicSectorInfo, []byte, []sectorbuilder.EPostCandidate) ([]byte, error) } type eppProvider struct { - sectors []sectorbuilder.SectorInfo + sectors []sectorbuilder.PublicSectorInfo } -func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { +func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { return []sectorbuilder.EPostCandidate{ sectorbuilder.EPostCandidate{ SectorID: 1, @@ -422,7 +428,7 @@ func (epp *eppProvider) GenerateCandidates(ctx context.Context, eprand []byte) ( }, nil } -func (epp *eppProvider) ComputeProof(ctx context.Context, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { +func (epp *eppProvider) ComputeProof(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { return []byte("valid proof"), nil } @@ -443,9 +449,27 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return false, nil, xerrors.Errorf("failed to compute VRF: %w", err) } - candidates, err := epp.GenerateCandidates(ctx, vrfout) + pset, err := a.StateMinerProvingSet(ctx, miner, ts) if err != nil { - return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates") + return false, nil, xerrors.Errorf("failed to load proving set for miner: %w", err) + } + log.Warningf("Proving set for miner %s: %s", miner, pset) + + var sinfos []sectorbuilder.PublicSectorInfo + for _, s := range pset { + var commRa [32]byte + copy(commRa[:], s.CommR) + sinfos = append(sinfos, sectorbuilder.PublicSectorInfo{ + SectorID: s.SectorID, + CommR: commRa, + }) + } + sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos) + + log.Info("Replicas: ", sectors) + candidates, err := epp.GenerateCandidates(ctx, sectors, vrfout) + if err != nil { + return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) } pow, err := a.StateMinerPower(ctx, miner, ts) @@ -470,7 +494,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return false, nil, nil } - proof, err := epp.ComputeProof(ctx, vrfout, winners) + proof, err := epp.ComputeProof(ctx, sectors, vrfout, winners) if err != nil { return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err) } diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 754275208..25185ad78 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -20,6 +20,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" + "github.com/filecoin-project/lotus/genesis" ) type GenesisBootstrap struct { @@ -215,8 +216,7 @@ type GenMinerCfg struct { Owners []address.Address Workers []address.Address - // not quite generating real sectors yet, but this will be necessary - //SectorDir string + PreSeals map[string]genesis.GenesisMiner // The addresses of the created miner, this is set by the genesis setup MinerAddrs []address.Address @@ -289,16 +289,23 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid if err := cst.Get(ctx, mact.Head, &mstate); err != nil { return cid.Undef, xerrors.Errorf("getting miner actor state failed: %w", err) } - mstate.Power = types.NewInt(5000) + mstate.Power = types.NewInt(build.SectorSizes[0]) - commD := make([]byte, 32) - commR := make([]byte, 32) blks := amt.WrapBlockstore(cs.Blockstore()) - nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, 1, commD, commR) - if err != nil { - return cid.Undef, xerrors.Errorf("failed to add fake sector to sector set: %w", err) + + ps, ok := gmcfg.PreSeals[maddr.String()] + if ok { + for _, s := range ps.Sectors { + nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommD[:], s.CommR[:]) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to add fake sector to sector set: %w", err) + } + mstate.Sectors = nssroot + mstate.ProvingSet = nssroot + } + } else { + log.Warning("No preseals for miner: ", maddr) } - mstate.Sectors = nssroot nstate, err := cst.Put(ctx, &mstate) if err != nil { diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 68c3ea24e..ad23f55f5 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -84,6 +84,7 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (cid. func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.BlockHeader, cb func(cid.Cid, *types.Message, *vm.ApplyRet) error) (cid.Cid, cid.Cid, error) { ctx, span := trace.StartSpan(ctx, "computeTipSetState") defer span.End() + fmt.Println("COMPUTE TIPSET STATE", len(blks)) for i := 0; i < len(blks); i++ { for j := i + 1; j < len(blks); j++ { @@ -113,9 +114,14 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err) } - reward := vm.MiningReward(netact.Balance) for _, b := range blks { + netact, err = vmi.StateTree().GetActor(actors.NetworkAddress) + if err != nil { + return cid.Undef, cid.Undef, xerrors.Errorf("failed to get network actor: %w", err) + } + vmi.SetBlockMiner(b.Miner) + owner, err := GetMinerOwner(ctx, sm, pstate, b.Miner) if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("failed to get owner for miner %s: %w", b.Miner, err) @@ -130,6 +136,24 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl return cid.Undef, cid.Undef, xerrors.Errorf("failed to deduct funds from network actor: %w", err) } + // all block miners created a valid post, go update the actor state + fmt.Println("SUBMIT ELECTION POST TIME", netact.Nonce, b.Height) + postSubmitMsg := &types.Message{ + From: actors.NetworkAddress, + Nonce: netact.Nonce, + To: b.Miner, + Method: actors.MAMethods.SubmitElectionPoSt, + GasPrice: types.NewInt(0), + GasLimit: types.NewInt(10000000000), + Value: types.NewInt(0), + } + ret, err := vmi.ApplyMessage(ctx, postSubmitMsg) + if err != nil { + return cid.Undef, cid.Undef, xerrors.Errorf("submit election post message invocation failed: %w", err) + } + if ret.ExitCode != 0 { + return cid.Undef, cid.Undef, xerrors.Errorf("submit election post invocation returned nonzero exit code: %d", ret.ExitCode) + } } // TODO: can't use method from chainstore because it doesnt let us know who the block miners were diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 6540e86ed..39017cb2d 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -155,7 +155,8 @@ func GetMinerProvingPeriodEnd(ctx context.Context, sm *StateManager, ts *types.T return 0, xerrors.Errorf("failed to load miner actor state: %w", err) } - return mas.ProvingPeriodEnd, nil + panic("idk what to do") + //return mas.ProvingPeriodEnd, nil } func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) { @@ -178,23 +179,23 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors) } -func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedSectorInfo, error) { +func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedPublicSectorInfo, error) { sectors, err := GetMinerSectorSet(ctx, sm, ts, maddr) if err != nil { return nil, xerrors.Errorf("failed to get sector set for miner: %w", err) } - var uselessOtherArray []sectorbuilder.SectorInfo + var uselessOtherArray []sectorbuilder.PublicSectorInfo for _, s := range sectors { var uselessBuffer [32]byte copy(uselessBuffer[:], s.CommR) - uselessOtherArray = append(uselessOtherArray, sectorbuilder.SectorInfo{ + uselessOtherArray = append(uselessOtherArray, sectorbuilder.PublicSectorInfo{ SectorID: s.SectorID, CommR: uselessBuffer, }) } - ssi := sectorbuilder.NewSortedSectorInfo(uselessOtherArray) + ssi := sectorbuilder.NewSortedPublicSectorInfo(uselessOtherArray) return &ssi, nil } diff --git a/chain/store/weight.go b/chain/store/weight.go index 901356728..72811ebec 100644 --- a/chain/store/weight.go +++ b/chain/store/weight.go @@ -40,6 +40,7 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn log2P = int64(tpow.BitLen() - 1) } else { // Not really expect to be here ... + panic("where are we") return types.EmptyInt, xerrors.Errorf("All power in the net is gone. You network might be disconnected, or the net is dead!") } diff --git a/cli/cmd.go b/cli/cmd.go index 30e9ba01a..f80c80453 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -122,7 +122,6 @@ var Commands = []*cli.Command{ sendCmd, stateCmd, syncCmd, - unregisterMinerCmd, versionCmd, walletCmd, } diff --git a/cli/miner.go b/cli/miner.go deleted file mode 100644 index 074faf962..000000000 --- a/cli/miner.go +++ /dev/null @@ -1,32 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/filecoin-project/lotus/chain/address" - "gopkg.in/urfave/cli.v2" -) - -var unregisterMinerCmd = &cli.Command{ - Name: "unregister-miner", - Usage: "Manually unregister miner actor", - Action: func(cctx *cli.Context) error { - api, closer, err := GetFullNodeAPI(cctx) - if err != nil { - return err - } - defer closer() - ctx := ReqContext(cctx) - - if !cctx.Args().Present() { - return fmt.Errorf("must pass address of miner to unregister") - } - - maddr, err := address.NewFromString(cctx.Args().First()) - if err != nil { - return err - } - - return api.MinerUnregister(ctx, maddr) - }, -} diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go new file mode 100644 index 000000000..8bbf4d9df --- /dev/null +++ b/cmd/lotus-seed/main.go @@ -0,0 +1,162 @@ +package main + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/lib/sectorbuilder" + + badger "github.com/ipfs/go-ds-badger" + logging "github.com/ipfs/go-log" + "github.com/mitchellh/go-homedir" + "gopkg.in/urfave/cli.v2" +) + +var log = logging.Logger("lotus-seed") + +func main() { + logging.SetLogLevel("*", "INFO") + + log.Info("Starting seed") + + local := []*cli.Command{ + preSealCmd, + } + + app := &cli.App{ + Name: "lotus-seed", + Usage: "Seal sectors for genesis miner", + Version: build.Version, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "sectorbuilder-dir", + Value: "~/.genesis-sectors", + }, + }, + + Commands: local, + } + + if err := app.Run(os.Args); err != nil { + log.Warn(err) + return + } +} + +var preSealCmd = &cli.Command{ + Name: "pre-seal", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "miner-addr", + Value: "t0101", + Usage: "specify the future address of your miner", + }, + &cli.Uint64Flag{ + Name: "sector-size", + Value: 1024, + Usage: "specify size of sectors to pre-seal", + }, + &cli.StringFlag{ + Name: "ticket-preimage", + Value: "lotus is fire", + Usage: "set the ticket preimage for sealing randomness", + }, + &cli.Uint64Flag{ + Name: "num-sectors", + Value: 1, + Usage: "select number of sectors to pre-seal", + }, + }, + Action: func(c *cli.Context) error { + sdir := c.String("sectorbuilder-dir") + sbroot, err := homedir.Expand(sdir) + if err != nil { + return err + } + + maddr, err := address.NewFromString(c.String("miner-addr")) + if err != nil { + return err + } + + cfg := §orbuilder.Config{ + Miner: maddr, + SectorSize: c.Uint64("sector-size"), + CacheDir: filepath.Join(sbroot, "cache"), + SealedDir: filepath.Join(sbroot, "sealed"), + StagedDir: filepath.Join(sbroot, "staging"), + MetadataDir: filepath.Join(sbroot, "meta"), + WorkerThreads: 2, + } + + for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { + if err := os.MkdirAll(d, 0775); err != nil { + return err + } + } + + mds, err := badger.NewDatastore(filepath.Join(sbroot, "badger"), nil) + if err != nil { + return err + } + + sb, err := sectorbuilder.New(cfg, mds) + if err != nil { + return err + } + + r := rand.New(rand.NewSource(101)) + size := sectorbuilder.UserBytesForSectorSize(c.Uint64("sector-size")) + + var sealedSectors []genesis.PreSeal + for i := uint64(1); i <= c.Uint64("num-sectors"); i++ { + pi, err := sb.AddPiece(size, i, r, nil) + if err != nil { + return err + } + + trand := sha256.Sum256([]byte(c.String("ticket-preimage"))) + ticket := sectorbuilder.SealTicket{ + TicketBytes: trand, + } + + fmt.Println("Piece info: ", pi) + + pco, err := sb.SealPreCommit(i, ticket, []sectorbuilder.PublicPieceInfo{pi}) + if err != nil { + return err + } + + sealedSectors = append(sealedSectors, genesis.PreSeal{ + CommR: pco.CommR, + CommD: pco.CommD, + SectorID: i, + }) + } + + output := map[string]genesis.GenesisMiner{ + maddr.String(): genesis.GenesisMiner{ + Sectors: sealedSectors, + }, + } + + out, err := json.MarshalIndent(output, "", " ") + if err != nil { + return err + } + + if err := ioutil.WriteFile("pre-seal-"+maddr.String()+".json", out, 0664); err != nil { + return err + } + + return nil + }, +} diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 06500af95..a14090f59 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "os" + "path/filepath" "github.com/ipfs/go-datastore" "github.com/libp2p/go-libp2p-core/crypto" @@ -18,7 +19,11 @@ import ( "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/lib/sectorbuilder" + "github.com/filecoin-project/lotus/miner" + "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/repo" + "github.com/filecoin-project/lotus/storage" ) var initCmd = &cli.Command{ @@ -53,6 +58,10 @@ var initCmd = &cli.Command{ Usage: "specify sector size to use", Value: build.SectorSizes[0], }, + &cli.StringFlag{ + Name: "pre-sealed-sectors", + Usage: "specify set of presealed sectors for starting as a genesis miner", + }, }, Action: func(cctx *cli.Context) error { log.Info("Initializing lotus storage miner") @@ -104,6 +113,13 @@ var initCmd = &cli.Command{ return err } + if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { + log.Infof("moving pre-sealed-sectors from %s into newly created storage miner repo", pssb) + if err := migratePreSealedSectors(pssb, repoPath); err != nil { + return err + } + } + if err := storageMinerInit(ctx, cctx, api, r); err != nil { log.Errorf("Failed to initialize lotus-storage-miner: %+v", err) path, err := homedir.Expand(repoPath) @@ -124,6 +140,35 @@ var initCmd = &cli.Command{ }, } +// TODO: this method should be a lot more robust for mainnet. For testnet, its +// fine if we mess things up a few times +func migratePreSealedSectors(presealsb string, repoPath string) error { + pspath, err := homedir.Expand(presealsb) + if err != nil { + return err + } + + expRepo, err := homedir.Expand(repoPath) + if err != nil { + return err + } + + if stat, err := os.Stat(pspath); err != nil { + return xerrors.Errorf("failed to stat presealed sectors directory: %w", err) + } else if !stat.IsDir() { + return xerrors.Errorf("given presealed sectors path was not a directory: %w", err) + } + + for _, dir := range []string{"meta", "sealed", "staging", "cache"} { + from := filepath.Join(pspath, dir) + to := filepath.Join(expRepo, dir) + if err := os.Rename(from, to); err != nil { + return err + } + } + return nil +} + func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, r repo.Repo) error { lr, err := r.Lock(repo.StorageMiner) if err != nil { @@ -150,8 +195,47 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, return xerrors.Errorf("failed parsing actor flag value (%q): %w", act, err) } - if err := configureStorageMiner(ctx, api, a, peerid, cctx.Bool("genesis-miner")); err != nil { - return xerrors.Errorf("failed to configure storage miner: %w", err) + if cctx.Bool("genesis-miner") { + mds, err := lr.Datastore("/metadata") + if err != nil { + return err + } + if err := mds.Put(datastore.NewKey("miner-address"), a.Bytes()); err != nil { + return err + } + + sbcfg, err := modules.SectorBuilderConfig(lr.Path(), 2)(mds, api) + if err != nil { + return xerrors.Errorf("getting genesis miner sector builder config: %w", err) + } + sb, err := sectorbuilder.New(sbcfg, mds) + if err != nil { + return xerrors.Errorf("failed to set up sectorbuilder for genesis mining: %w", err) + } + epp := storage.NewElectionPoStProver(sb) + + m := miner.NewMiner(api, epp) + { + if err := m.Register(a); err != nil { + return xerrors.Errorf("failed to start up genesis miner: %w", err) + } + + defer func() { + if err := m.Unregister(ctx, a); err != nil { + log.Error("failed to shut down storage miner: ", err) + } + }() + + if err := configureStorageMiner(ctx, api, a, peerid); err != nil { + return xerrors.Errorf("failed to configure storage miner: %w", err) + } + } + + return nil + } else { + if err := configureStorageMiner(ctx, api, a, peerid); err != nil { + return xerrors.Errorf("failed to configure storage miner: %w", err) + } } addr = a @@ -165,12 +249,11 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, } log.Infof("Created new storage miner: %s", addr) - - ds, err := lr.Datastore("/metadata") + mds, err := lr.Datastore("/metadata") if err != nil { return err } - if err := ds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil { + if err := mds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil { return err } @@ -203,22 +286,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) { return pk, nil } -func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID, genmine bool) error { - if genmine { - log.Warn("Starting genesis mining. This shouldn't happen when connecting to the real network.") - // We may be one of genesis miners, start mining before trying to do any chain operations - // (otherwise our messages won't be mined) - if err := api.MinerRegister(ctx, addr); err != nil { - return err - } - - defer func() { - if err := api.MinerUnregister(ctx, addr); err != nil { - log.Errorf("failed to call api.MinerUnregister: %s", err) - } - }() - } - +func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID) error { // This really just needs to be an api call at this point... recp, err := api.StateCall(ctx, &types.Message{ To: addr, diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 115970d54..87ff1f0ad 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -21,7 +21,8 @@ import ( ) const ( - makeGenFlag = "lotus-make-random-genesis" + makeGenFlag = "lotus-make-random-genesis" + preSealedSectorsFlag = "genesis-presealed-sectors" ) // DaemonCmd is the `go-lotus daemon` command @@ -38,6 +39,10 @@ var DaemonCmd = &cli.Command{ Value: "", Hidden: true, }, + &cli.StringFlag{ + Name: "genesis-presealed-sectors", + Hidden: true, + }, &cli.StringFlag{ Name: "genesis", Usage: "genesis file to use for first node run", @@ -69,7 +74,6 @@ var DaemonCmd = &cli.Command{ if err != nil { return err } - } genesis := node.Options() @@ -77,7 +81,10 @@ var DaemonCmd = &cli.Command{ genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genBytes)) } if cctx.String(makeGenFlag) != "" { - genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag))) + if cctx.String(preSealedSectorsFlag) == "" { + return xerrors.Errorf("must also pass file with miner preseal info to `--%s`", preSealedSectorsFlag) + } + genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag), cctx.String(preSealedSectorsFlag))) } var api api.FullNode diff --git a/extern/go-sectorbuilder b/extern/go-sectorbuilder index 33fb89c5e..e75744852 160000 --- a/extern/go-sectorbuilder +++ b/extern/go-sectorbuilder @@ -1 +1 @@ -Subproject commit 33fb89c5efe02a250508e95114836bd13dd3067e +Subproject commit e757448529bd87318e9b52b93661f6cda1a76a42 diff --git a/genesis/types.go b/genesis/types.go new file mode 100644 index 000000000..36abd8f28 --- /dev/null +++ b/genesis/types.go @@ -0,0 +1,15 @@ +package genesis + +import "github.com/filecoin-project/lotus/chain/address" + +type PreSeal struct { + CommR [32]byte + CommD [32]byte + SectorID uint64 +} + +type GenesisMiner struct { + Sectors []PreSeal + Owner address.Address + Worker address.Address +} diff --git a/go.mod b/go.mod index 37ef67f4d..5fb9e2754 100644 --- a/go.mod +++ b/go.mod @@ -89,6 +89,7 @@ require ( github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect github.com/stretchr/testify v1.4.0 + github.com/urfave/cli v1.20.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 diff --git a/go.sum b/go.sum index f095026ec..d9f303a61 100644 --- a/go.sum +++ b/go.sum @@ -538,6 +538,7 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 3f3eeac2d..eae5bec7a 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -31,9 +31,11 @@ type SectorSealingStatus = sectorbuilder.SectorSealingStatus type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata -type SortedSectorInfo = sectorbuilder.SortedSectorInfo +type SortedPublicSectorInfo = sectorbuilder.SortedPublicSectorInfo +type SortedPrivateSectorInfo = sectorbuilder.SortedPrivateSectorInfo -type SectorInfo = sectorbuilder.SectorInfo +type PrivateSectorInfo = sectorbuilder.SectorPrivateInfo +type PublicSectorInfo = sectorbuilder.SectorPublicInfo type SealTicket = sectorbuilder.SealTicket @@ -347,21 +349,49 @@ func (sb *SectorBuilder) SectorSize() uint64 { return sb.ssize } -func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedSectorInfo, challengeSeed []byte, winners []EPostCandidate) ([]byte, error) { +func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed []byte, winners []EPostCandidate) ([]byte, error) { if len(challengeSeed) != CommLen { return nil, xerrors.Errorf("given challenge seed was the wrong length: %d != %d", len(challengeSeed), CommLen) } var cseed [CommLen]byte copy(cseed[:], challengeSeed) - return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, winners) + return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, 1, winners) } -func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { - return sectorbuilder.GenerateCandidates(sb.handle, sectorInfo, challengeSeed, faults) +func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { + privsectors, err := sb.pubSectorToPriv(sectorInfo) + if err != nil { + return nil, err + } + proverID := addressToProverID(sb.Miner) + return sectorbuilder.StandaloneGenerateCandidates(sb.ssize, proverID, challengeSeed, 1, privsectors) } -func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { +func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) { + var out []PrivateSectorInfo + for _, s := range sectorInfo.Values() { + cachePath, err := sb.sectorCacheDir(s.SectorID) + if err != nil { + return SortedPrivateSectorInfo{}, xerrors.Errorf("getting cache path for sector %d: %w", s.SectorID, err) + } + + sealedPath, err := sb.sealedSectorPath(s.SectorID) + if err != nil { + return SortedPrivateSectorInfo{}, xerrors.Errorf("getting sealed path for sector %d: %w", s.SectorID, err) + } + + out = append(out, PrivateSectorInfo{ + SectorID: s.SectorID, + CommR: s.CommR, + CacheDirPath: cachePath, + SealedSectorPath: sealedPath, + }) + } + return NewSortedPrivateSectorInfo(out), nil +} + +func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPrivateSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { panic("NYI") } @@ -378,18 +408,22 @@ func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) } -func NewSortedSectorInfo(sectors []SectorInfo) SortedSectorInfo { - return sectorbuilder.NewSortedSectorInfo(sectors...) +func NewSortedPrivateSectorInfo(sectors []PrivateSectorInfo) SortedPrivateSectorInfo { + return sectorbuilder.NewSortedSectorPrivateInfo(sectors...) } -func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) { +func NewSortedPublicSectorInfo(sectors []PublicSectorInfo) SortedPublicSectorInfo { + return sectorbuilder.NewSortedSectorPublicInfo(sectors...) +} + +func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) { var challengeSeeda [CommLen]byte copy(challengeSeeda[:], challengeSeed) _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() prover := addressToProverID(proverID) - return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, proof, winners, prover) + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, 1, proof, winners, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 044c690bf..15f8beeed 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -1,7 +1,6 @@ package sectorbuilder_test import ( - "context" "io" "io/ioutil" "math/rand" @@ -77,25 +76,28 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() } func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) { - cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} + /* + // TODO: fixme + cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} - ssi := sectorbuilder.NewSortedSectorInfo([]sectorbuilder.SectorInfo{{ - SectorID: s.sid, - CommR: s.pco.CommR, - }}) + ssi := sectorbuilder.NewSortedPublicSectorInfo([]sectorbuilder.PublicSectorInfo{{ + SectorID: s.sid, + CommR: s.pco.CommR, + }}) - postProof, err := sb.GeneratePoSt(ssi, cSeed, []uint64{}) - if err != nil { - t.Fatalf("%+v", err) - } + postProof, err := sb.GeneratePoSt(ssi, cSeed, []uint64{}) + if err != nil { + t.Fatalf("%+v", err) + } - ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed, postProof, []uint64{}) - if err != nil { - t.Fatalf("%+v", err) - } - if !ok { - t.Fatal("bad post") - } + ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed, postProof, []uint64{}) + if err != nil { + t.Fatalf("%+v", err) + } + if !ok { + t.Fatal("bad post") + } + */ } func TestSealAndVerify(t *testing.T) { diff --git a/miner/miner.go b/miner/miner.go index 56f78e5fe..7fa0f63c2 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -5,17 +5,16 @@ import ( "sync" "time" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/node/impl/full" logging "github.com/ipfs/go-log" "github.com/pkg/errors" "go.opencensus.io/trace" - "go.uber.org/fx" "golang.org/x/xerrors" ) @@ -23,20 +22,10 @@ var log = logging.Logger("miner") type waitFunc func(ctx context.Context) error -type api struct { - fx.In - - full.ChainAPI - full.SyncAPI - full.MpoolAPI - full.WalletAPI - full.StateAPI -} - -func NewMiner(api api) *Miner { +func NewMiner(api api.FullNode, epp gen.ElectionPoStProver) *Miner { return &Miner{ api: api, - epp: nil, + epp: epp, waitFunc: func(ctx context.Context) error { // Wait around for half the block time in case other parents come in time.Sleep(build.BlockDelay * time.Second / 2) @@ -46,7 +35,7 @@ func NewMiner(api api) *Miner { } type Miner struct { - api api + api api.FullNode epp gen.ElectionPoStProver @@ -256,9 +245,9 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return nil, errors.Wrap(err, "scratching ticket failed") } - win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, &m.api) + win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api) if err != nil { - return nil, errors.Wrap(err, "failed to check if we win next round") + return nil, xerrors.Errorf("failed to check if we win next round: %w", err) } if !win { diff --git a/miner/testminer.go b/miner/testminer.go index 6adf02266..48fbd92a6 100644 --- a/miner/testminer.go +++ b/miner/testminer.go @@ -2,10 +2,12 @@ package miner import ( "context" + + "github.com/filecoin-project/lotus/api" ) -func NewTestMiner(nextCh <-chan struct{}) func(api api) *Miner { - return func(api api) *Miner { +func NewTestMiner(nextCh <-chan struct{}) func(api api.FullNode) *Miner { + return func(api api.FullNode) *Miner { return &Miner{ api: api, waitFunc: chanWaiter(nextCh), diff --git a/node/builder.go b/node/builder.go index 02082a3e5..3512354ec 100644 --- a/node/builder.go +++ b/node/builder.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/blocksync" "github.com/filecoin-project/lotus/chain/deals" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/metrics" "github.com/filecoin-project/lotus/chain/stmgr" @@ -92,7 +93,6 @@ const ( HandleDealsKey HandleRetrievalKey RunSectorServiceKey - RegisterMinerKey RegisterProviderValidatorKey // daemon @@ -231,8 +231,6 @@ func Online() Option { Override(new(*paych.Store), paych.NewStore), Override(new(*paych.Manager), paych.NewManager), Override(new(*market.FundMgr), market.NewFundMgr), - - Override(new(*miner.Miner), miner.NewMiner), ), // Storage miner @@ -252,7 +250,8 @@ func Online() Option { Override(RegisterProviderValidatorKey, modules.RegisterProviderValidator), Override(HandleRetrievalKey, modules.HandleRetrieval), Override(HandleDealsKey, modules.HandleDeals), - Override(RegisterMinerKey, modules.RegisterMiner), + Override(new(gen.ElectionPoStProver), storage.NewElectionPoStProver), + Override(new(*miner.Miner), modules.SetupBlockProducer), ), ) } diff --git a/node/impl/full.go b/node/impl/full.go index 76cdc5de4..2c01674fb 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -1,8 +1,6 @@ package impl import ( - "context" - logging "github.com/ipfs/go-log" "github.com/filecoin-project/lotus/node/impl/client" @@ -10,8 +8,6 @@ import ( "github.com/filecoin-project/lotus/node/impl/paych" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/address" - "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/impl/full" ) @@ -27,20 +23,6 @@ type FullNodeAPI struct { full.StateAPI full.WalletAPI full.SyncAPI - - Miner *miner.Miner -} - -func (a *FullNodeAPI) MinerAddresses(context.Context) ([]address.Address, error) { - return a.Miner.Addresses() -} - -func (a *FullNodeAPI) MinerRegister(ctx context.Context, addr address.Address) error { - return a.Miner.Register(addr) -} - -func (a *FullNodeAPI) MinerUnregister(ctx context.Context, addr address.Address) error { - return a.Miner.Unregister(ctx, addr) } var _ api.FullNode = &FullNodeAPI{} diff --git a/node/impl/storminer.go b/node/impl/storminer.go index f339fd66a..04f162c30 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -6,6 +6,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/lib/sectorbuilder" + "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/storage" "github.com/filecoin-project/lotus/storage/sectorblocks" ) @@ -17,8 +18,9 @@ type StorageMinerAPI struct { SectorBuilder *sectorbuilder.SectorBuilder SectorBlocks *sectorblocks.SectorBlocks - Miner *storage.Miner - Full api.FullNode + Miner *storage.Miner + BlockMiner *miner.Miner + Full api.FullNode } func (sm *StorageMinerAPI) WorkerStats(context.Context) (api.WorkerStats, error) { diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index a7cc98463..bf0a6b98a 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -2,7 +2,6 @@ package modules import ( "context" - "fmt" "math" "path/filepath" "reflect" @@ -24,9 +23,11 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/deals" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/datatransfer" "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/lib/statestore" + "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/modules/helpers" "github.com/filecoin-project/lotus/node/repo" @@ -176,26 +177,27 @@ func StagingDAG(mctx helpers.MetricsCtx, lc fx.Lifecycle, r repo.LockedRepo, rt return dag, nil } -func RegisterMiner(lc fx.Lifecycle, ds dtypes.MetadataDS, api api.FullNode) error { +func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api api.FullNode, epp gen.ElectionPoStProver) (*miner.Miner, error) { minerAddr, err := minerAddrFromDS(ds) if err != nil { - return err + return nil, err } + m := miner.NewMiner(api, epp) + lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { - log.Infof("Registering miner '%s' with full node", minerAddr) - if err := api.MinerRegister(ctx, minerAddr); err != nil { - return fmt.Errorf("Failed to register miner: %s\nIf you are certain no other storage miner instance is running, try running 'lotus unregister-miner %s' and restarting the storage miner", err, minerAddr) + if err := m.Register(minerAddr); err != nil { + return err } return nil }, OnStop: func(ctx context.Context) error { - log.Infof("Unregistering miner '%s' from full node", minerAddr) - return api.MinerUnregister(ctx, minerAddr) + return m.Unregister(ctx, minerAddr) }, }) - return nil + + return m, nil } func SectorBuilder(lc fx.Lifecycle, cfg *sectorbuilder.Config, ds dtypes.MetadataDS) (*sectorbuilder.SectorBuilder, error) { diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 6c81f68ba..5b6519e47 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -2,8 +2,10 @@ package testing import ( "context" + "encoding/json" "fmt" "io" + "io/ioutil" "os" "time" @@ -19,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/node/modules" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -61,19 +64,30 @@ func MakeGenesisMem(out io.Writer, minerPid peer.ID) func(bs dtypes.ChainBlockst } } -func MakeGenesis(outFile string) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { +func MakeGenesis(outFile, preseal string) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func() (*types.BlockHeader, error) { glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") + fdata, err := ioutil.ReadFile(preseal) + if err != nil { + return nil, err + } + + var preseal map[string]genesis.GenesisMiner + if err := json.Unmarshal(fdata, &preseal); err != nil { + return nil, err + } + minerAddr, err := w.GenerateKey(types.KTBLS) if err != nil { return nil, err } gmc := &gen.GenMinerCfg{ - Owners: []address.Address{minerAddr}, - Workers: []address.Address{minerAddr}, - PeerIDs: []peer.ID{"peer ID 1"}, + Owners: []address.Address{minerAddr}, + Workers: []address.Address{minerAddr}, + PeerIDs: []peer.ID{"peer ID 1"}, + PreSeals: preseal, } addrs := map[address.Address]types.BigInt{ diff --git a/storage/miner.go b/storage/miner.go index 3750d41fe..f8323b2ac 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -14,6 +14,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/events" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sectorbuilder" @@ -133,3 +134,25 @@ func (m *Miner) runPreflightChecks(ctx context.Context) error { log.Infof("starting up miner %s, worker addr %s", m.maddr, m.worker) return nil } + +type sectorBuilderEpp struct { + sb *sectorbuilder.SectorBuilder +} + +func NewElectionPoStProver(sb *sectorbuilder.SectorBuilder) *sectorBuilderEpp { + return §orBuilderEpp{sb} +} + +var _ (gen.ElectionPoStProver) = (*sectorBuilderEpp)(nil) + +func (epp *sectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) { + var faults []uint64 // TODO + + var randbuf [32]byte + copy(randbuf[:], rand) + return epp.sb.GenerateEPostCandidates(ssi, randbuf, faults) +} + +func (epp *sectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { + return epp.sb.ComputeElectionPoSt(ssi, rand, winners) +} diff --git a/storage/post.go b/storage/post.go index 4f73b8af2..270a66751 100644 --- a/storage/post.go +++ b/storage/post.go @@ -164,19 +164,20 @@ func (p *post) preparePost(ctx context.Context) error { return nil } -func (p *post) sortedSectorInfo() sectorbuilder.SortedSectorInfo { - sbsi := make([]sectorbuilder.SectorInfo, len(p.sset)) +func (p *post) sortedSectorInfo() sectorbuilder.SortedPrivateSectorInfo { + panic("NYI") + sbsi := make([]sectorbuilder.PrivateSectorInfo, len(p.sset)) for k, sector := range p.sset { var commR [sectorbuilder.CommLen]byte copy(commR[:], sector.CommR) - sbsi[k] = sectorbuilder.SectorInfo{ + sbsi[k] = sectorbuilder.PrivateSectorInfo{ SectorID: sector.SectorID, CommR: commR, } } - return sectorbuilder.NewSortedSectorInfo(sbsi) + return sectorbuilder.NewSortedPrivateSectorInfo(sbsi) } func (p *post) runPost(ctx context.Context) error { @@ -210,33 +211,35 @@ func (p *post) commitPost(ctx context.Context) error { defer span.End() panic("NYI") - params := &actors.SubmitPoStParams{ - //Proof: p.proof, - DoneSet: types.BitFieldFromSet(nil), - } + /* - enc, aerr := actors.SerializeParams(params) - if aerr != nil { - return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) - } + params := &actors.SubmitPoStParams{ + //Proof: p.proof, + } - msg := &types.Message{ - To: p.m.maddr, - From: p.m.worker, - Method: actors.MAMethods.SubmitPoSt, - Params: enc, - Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late - GasLimit: types.NewInt(1000000 /* i dont know help */), - GasPrice: types.NewInt(1), - } + enc, aerr := actors.SerializeParams(params) + if aerr != nil { + return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + } - log.Info("mpush") + msg := &types.Message{ + To: p.m.maddr, + From: p.m.worker, + Method: actors.MAMethods.SubmitPoSt, + Params: enc, + Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late + GasLimit: types.NewInt(1000000), // i dont know help + GasPrice: types.NewInt(1), + } - smsg, err := p.m.api.MpoolPushMessage(ctx, msg) - if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) - } - p.smsg = smsg.Cid() + log.Info("mpush") + + smsg, err := p.m.api.MpoolPushMessage(ctx, msg) + if err != nil { + return xerrors.Errorf("pushing message to mpool: %w", err) + } + p.smsg = smsg.Cid() + */ return nil } From df0be815aefe424a82089b8cdf45abfa57b884e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 25 Nov 2019 17:16:18 +0100 Subject: [PATCH 08/93] More correct challangeCount calc --- build/params.go | 3 +++ lib/sectorbuilder/sectorbuilder.go | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/build/params.go b/build/params.go index 655a8ffc0..5439e46d1 100644 --- a/build/params.go +++ b/build/params.go @@ -79,6 +79,9 @@ const SealRandomnessLookback = Finality // Blocks const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000 +// 1 / n +const SectorChallengeRatioDiv = 25 + // ///// // Mining diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index eae5bec7a..4299dd18d 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -16,6 +16,7 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -356,7 +357,9 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, var cseed [CommLen]byte copy(cseed[:], challengeSeed) - return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, 1, winners) + challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + + return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, challengeCount, winners) } func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { @@ -364,8 +367,11 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn if err != nil { return nil, err } + + challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + proverID := addressToProverID(sb.Miner) - return sectorbuilder.StandaloneGenerateCandidates(sb.ssize, proverID, challengeSeed, 1, privsectors) + return sectorbuilder.StandaloneGenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) } func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) { @@ -420,10 +426,12 @@ func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicS var challengeSeeda [CommLen]byte copy(challengeSeeda[:], challengeSeed) + challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() prover := addressToProverID(proverID) - return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, 1, proof, winners, prover) + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { @@ -443,3 +451,8 @@ func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen] func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]byte, error) { return sectorbuilder.GenerateDataCommitment(ssize, pieces) } + +func challangeCount(sectors uint64) uint64 { + // ceil(sectors / build.SectorChallengeRatioDiv) + return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv +} From 265b90e95bec3d79f53036d7388e2ef1dae09a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 25 Nov 2019 23:17:39 +0100 Subject: [PATCH 09/93] update parameters.json --- build/proof-params/parameters.json | 122 ++++++++++++++--------------- cmd/lotus/main.go | 2 +- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/build/proof-params/parameters.json b/build/proof-params/parameters.json index e12686127..544a8374b 100644 --- a/build/proof-params/parameters.json +++ b/build/proof-params/parameters.json @@ -1,82 +1,82 @@ { - "v15-proof-of-spacetime-rational-535d1050e3adca2a0dfe6c3c0c4fa12097c9a7835fb969042f82a507b13310e0.params": { - "cid": "QmT22f1Np1GpW29NXD7Zrv3Ae4poMYhmkDjyscqL8QrJXY", - "digest": "989fd8d989e0f7f1fe21bb010cf1b231", - "sector_size": 16777216 - }, - "v15-proof-of-spacetime-rational-535d1050e3adca2a0dfe6c3c0c4fa12097c9a7835fb969042f82a507b13310e0.vk": { - "cid": "QmVqSdc23to4UwduCCb25223rpSccvtcgPMfRKY1qjucDc", - "digest": "c6d258c37243b8544238a98100e3e399", - "sector_size": 16777216 - }, - "v15-proof-of-spacetime-rational-b99f15d0bdaaf4ffb68b2ca72b69ea8d915f66a2a56f667430ad69d87aa5febd.params": { - "cid": "QmRTCqgokEGTMfWVaSr7qFXTNotmpd2QBEi8RsvSQKmPLz", - "digest": "ff77a5e270afc6e1c7fbc19e48348fac", - "sector_size": 1073741824 - }, - "v15-proof-of-spacetime-rational-b99f15d0bdaaf4ffb68b2ca72b69ea8d915f66a2a56f667430ad69d87aa5febd.vk": { - "cid": "QmRssVAXRN3xp9VdSpTq1pNjkob3QiikoFZiM5hqrmh1VU", - "digest": "b41f35ac26224258e366327716a835a4", - "sector_size": 1073741824 - }, - "v15-proof-of-spacetime-rational-ba14a058a9dea194f68596f8ecf6537074f038a15c8d1a8550e10e31d4728912.params": { - "cid": "QmYNVRVzjXkuxJfnHTU5vmEcUBQf8dabXZ4m53SzqMkBv5", - "digest": "d156b685e4a1fe3a1f7230b6a39b5ad4", + "v17-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.params": { + "cid": "QmX1yk3iLPVd87nto2TjoR8ZRRUPS6VQrGjp6VGzJ5LMku", + "digest": "b77189b5fd4fdfb62aa10b711e2c07fe", "sector_size": 1024 }, - "v15-proof-of-spacetime-rational-ba14a058a9dea194f68596f8ecf6537074f038a15c8d1a8550e10e31d4728912.vk": { - "cid": "QmaCEcsCFVuepMKdC5WURbr5ucEyLMNGxQaB7HqSnr2KGh", - "digest": "06ff067ac78cdab5d7bbc82170882241", + "v17-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.vk": { + "cid": "QmQbm46eEM7iixdU3N412CGXz17tegn2J3Yv37MwsuXwUv", + "digest": "5d67b3241bfba6832cfe55c044a5627f", "sector_size": 1024 }, - "v15-proof-of-spacetime-rational-c2ae2b440e693ee69fd6da9e85c4294c5c70c1a46d5785ca5f2a676d6cd4c8de.params": { - "cid": "QmVuabRvJ797NwLisGKwRURASGxopBBgg4rfNsbZoSYzAc", - "digest": "0e1ceb79a459a60508f480e5b1fed7ac", + "v17-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.params": { + "cid": "QmVavKxo3kNt8TBvMUeicv4FvM9FJ2UhMYpUNExvwRTXEc", + "digest": "0c2acd67ae44c8c4d9b5bb20e1dedc1f", "sector_size": 268435456 }, - "v15-proof-of-spacetime-rational-c2ae2b440e693ee69fd6da9e85c4294c5c70c1a46d5785ca5f2a676d6cd4c8de.vk": { - "cid": "QmdWENZBAbuUty1vVNn9vmvj1XbJ5UC8qzpcVD35s5AJxG", - "digest": "1b755c74b9d6823c014f6a7ef76249f2", + "v17-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.vk": { + "cid": "QmS7kg73nQ6ErhhASi6AnwjnQT4PmGMxEFzCnsZYx3PUFf", + "digest": "259bbafc10bd5ad883e2b54f61780230", "sector_size": 268435456 }, - "v15-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.params": { - "cid": "QmZDVpWTw5Eti5pE7N5z1Cmqsw8hPXhUcvG3cQuceK56LH", - "digest": "6aa80306018ea1328f2d6faf8c080734", + "v17-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.params": { + "cid": "QmSz2YTybJDMCgW3ryvvNPQ2SJyBtASpWgzb5UfeTqQxJh", + "digest": "0ba0a7430cb9411e82cddd1b8a918428", "sector_size": 16777216 }, - "v15-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.vk": { - "cid": "QmaoXV7iVSJcfZ5qubYy7NBcXDSdnTzxH85d7M4bdDtfGZ", - "digest": "f6832eb736faf2960e920d32e9780b12", + "v17-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.vk": { + "cid": "QmWASM5eUWBaAqE6HAdjHWEHJKPW6veVgTuaJs45kKonwn", + "digest": "111a2ad1a6018ffc4e2a28644ed07f1b", "sector_size": 16777216 }, - "v15-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.params": { - "cid": "QmbUW3a3q5DHBb7Ufk8iSbnSCZgbwpe3serqfwKmcTd11w", - "digest": "64024e461b07c869df2463d33dd28035", - "sector_size": 268435456 - }, - "v15-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.vk": { - "cid": "Qme3QgBBE7hUgrK7G9ZfJhzkbvViN5HALFpFduYs5K1piv", - "digest": "32496f4dc434b0ed9ef49cb62497a7d1", - "sector_size": 268435456 - }, - "v15-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.params": { - "cid": "QmZzgJmb8WXYDKxS22HDgnoBYcZzXDC7s2c2zsV7kouNZ9", - "digest": "cd91f7ccb2ff57a06f3375946dcbdc68", + "v17-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.params": { + "cid": "QmYwZVdahZ7irXaW423AXwfr2sbuCq3ih9oPFTo3mQpL6Y", + "digest": "a0107d57e12c33bdaf586bb54311ec90", "sector_size": 1073741824 }, - "v15-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.vk": { - "cid": "QmRUMVzFnENbvyNb6aN2AJ2dnnewr1ESGA1UQLMVZZdsJM", - "digest": "92fc84b76dbe69c731518aebcb82ac82", + "v17-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.vk": { + "cid": "QmXHAwHcbpx31JFUeHs2mub4GPr4wsFSaCrxrxBHgy6adM", + "digest": "6e51dff3a3b51aef1ddf6b6f15c870f5", "sector_size": 1073741824 }, - "v15-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.params": { - "cid": "QmSixsGkxJXTAuFfWKy5aEXEDJEnpcb1GkdQVF8TCPWoHy", - "digest": "f8339ae93478ded3840d0bc7efa19953", + "v17-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.params": { + "cid": "QmU5eYfCwyjsJ4perRgVW6KTq1bDLfQ7XcBhg9Z1mH42kQ", + "digest": "3d6d4ba0b2eae2695dfd73c916a66c95", + "sector_size": 16777216 + }, + "v17-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.vk": { + "cid": "QmbB2Caq4muLCKbNJgH9KQddao5JYnB2JzYUMWwFq2Qm4Z", + "digest": "4a5efda7efb11b1af579baf30a41007f", + "sector_size": 16777216 + }, + "v17-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.params": { + "cid": "QmSh7aFgjutVthSCyDYDs7FjHKGtuZc9YaFnFBSpEvYE1Y", + "digest": "c92ebee7cfc2509b624736df083e790b", + "sector_size": 268435456 + }, + "v17-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.vk": { + "cid": "QmVL7fjQftCCPo6vRkVErspADjFCoVqdRCR179g9PyLbez", + "digest": "1ca0cd9c59df03621dfdf1427ea735dc", + "sector_size": 268435456 + }, + "v17-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.params": { + "cid": "QmRXZCQdzP2kFfdHse953CxgdTupwT8fWQA7YmeqtAjM9H", + "digest": "5539c3c55c9b409e5432bc61f34b5786", + "sector_size": 1073741824 + }, + "v17-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.vk": { + "cid": "QmdQGgWyYijAacJbRrdR42GYZz5QZhGQ1YY4kun2w27arx", + "digest": "716f20b705260ca43515a4bcff8e6f47", + "sector_size": 1073741824 + }, + "v17-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.params": { + "cid": "QmSkTjaq6X8jquVh6wsXrPVeMDMg7yC7fGJ1i3yeV54eiR", + "digest": "15fe50f23209ed875b4b44e3ee61c5c5", "sector_size": 1024 }, - "v15-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.vk": { - "cid": "QmTMC8hdZ2TkZ9BFuzHzRLM9SuR2PQdUrSAwABeCuHyV2f", - "digest": "f27f08ce1246ee6612c250bb12803ef1", + "v17-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.vk": { + "cid": "QmZCU4KBnTkAQuhuRDwyopjzXEXSs13n34QCXM5a5a6AdY", + "digest": "e50d458bef1c840d5f1deff018a0d702", "sector_size": 1024 } -} \ No newline at end of file +} diff --git a/cmd/lotus/main.go b/cmd/lotus/main.go index cd9a9e727..e2f32c0a0 100644 --- a/cmd/lotus/main.go +++ b/cmd/lotus/main.go @@ -69,7 +69,7 @@ func main() { Code: trace.StatusCodeFailedPrecondition, Message: err.Error(), }) - log.Warn(err) + log.Warnf("%+v", err) os.Exit(1) } return From 2421f5d589ca85b294c493b486a8c73479e8b16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 25 Nov 2019 23:25:33 +0100 Subject: [PATCH 10/93] make: lotus-seed target --- .gitignore | 1 + Makefile | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 1e4ce2d8e..67359f1ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /lotus /lotus-storage-miner +/lotus-seed /pond /townhall /fountain diff --git a/Makefile b/Makefile index b30f8712f..9574fc5f3 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,13 @@ lotus-storage-miner: $(BUILD_DEPS) .PHONY: lotus-storage-miner +lotus-seed: $(BUILD_DEPS) + rm -f lotus-seed + go build -o lotus-seed ./cmd/lotus-seed + go run github.com/GeertJohan/go.rice/rice append --exec lotus-seed -i ./build + +.PHONY: lotus-seed + CLEAN+=lotus-storage-miner build: lotus lotus-storage-miner From 7a3ffbf9fef01180f48f65f38868f11fb0dd3478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 00:31:34 +0100 Subject: [PATCH 11/93] WIP getting post in sectorbuilder_test to work --- lib/sectorbuilder/sectorbuilder.go | 4 +-- lib/sectorbuilder/sectorbuilder_test.go | 46 +++++++++++++++---------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 4299dd18d..6126db082 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -291,7 +291,7 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea } } - sealedPath, err := sb.sealedSectorPath(sectorID) +/* sealedPath, err := sb.sealedSectorPath(sectorID) if err != nil { return nil, err } @@ -312,7 +312,7 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea ) if err != nil { return nil, xerrors.Errorf("ImportSealedSector: %w", err) - } + }*/ return proof, nil } diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 15f8beeed..4f5c111fb 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -1,6 +1,8 @@ package sectorbuilder_test import ( + "context" + "fmt" "io" "io/ioutil" "math/rand" @@ -76,28 +78,30 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() } func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) { - /* - // TODO: fixme - cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} + cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} - ssi := sectorbuilder.NewSortedPublicSectorInfo([]sectorbuilder.PublicSectorInfo{{ - SectorID: s.sid, - CommR: s.pco.CommR, - }}) + ssi := sectorbuilder.NewSortedPublicSectorInfo([]sectorbuilder.PublicSectorInfo{{ + SectorID: s.sid, + CommR: s.pco.CommR, + }}) - postProof, err := sb.GeneratePoSt(ssi, cSeed, []uint64{}) - if err != nil { - t.Fatalf("%+v", err) - } + candndates, err := sb.GenerateEPostCandidates(ssi, cSeed, []uint64{}) + if err != nil { + t.Fatalf("%+v", err) + } - ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed, postProof, []uint64{}) - if err != nil { - t.Fatalf("%+v", err) - } - if !ok { - t.Fatal("bad post") - } - */ + postProof, err := sb.ComputeElectionPoSt(ssi, cSeed[:], candndates) + if err != nil { + t.Fatalf("%+v", err) + } + + ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner) + if err != nil { + t.Fatalf("%+v", err) + } + if !ok { + t.Fatal("bad post") + } } func TestSealAndVerify(t *testing.T) { @@ -126,6 +130,10 @@ func TestSealAndVerify(t *testing.T) { } cleanup := func() { sb.Destroy() + if t.Failed() { + fmt.Printf("not removing %s\n", dir) + return + } if err := os.RemoveAll(dir); err != nil { t.Error(err) } From a98295a747bcdb552fe9afd2b90b14618148813d Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 25 Nov 2019 20:43:43 -0600 Subject: [PATCH 12/93] use the correct sector sizes in places --- build/params.go | 1 + chain/actors/actor_miner.go | 1 + chain/gen/gen.go | 5 +-- chain/gen/utils.go | 2 +- lib/sectorbuilder/sectorbuilder.go | 50 ++++++++++++++++-------------- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/build/params.go b/build/params.go index 5439e46d1..63b6ef95f 100644 --- a/build/params.go +++ b/build/params.go @@ -13,6 +13,7 @@ const UnixfsChunkSize uint64 = 1 << 20 const UnixfsLinksPerLevel = 1024 var SectorSizes = []uint64{ + 1 << 10, 16 << 20, 256 << 20, 1 << 30, diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 885c24922..efbec6a82 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -184,6 +184,7 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ SectorSize: params.SectorSize, } + fmt.Println("NEW STORAGE MINER WITH SECTOR SIZE: ", params.SectorSize) minfocid, err := vmctx.Storage().Put(minerInfo) if err != nil { return nil, err diff --git a/chain/gen/gen.go b/chain/gen/gen.go index c4eabdc18..e8c662040 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -466,8 +466,9 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add } sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos) + hvrf := sha256.Sum256(vrfout) log.Info("Replicas: ", sectors) - candidates, err := epp.GenerateCandidates(ctx, sectors, vrfout) + candidates, err := epp.GenerateCandidates(ctx, sectors, hvrf[:]) if err != nil { return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) } @@ -494,7 +495,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return false, nil, nil } - proof, err := epp.ComputeProof(ctx, sectors, vrfout, winners) + proof, err := epp.ComputeProof(ctx, sectors, hvrf[:], winners) if err != nil { return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err) } diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 25185ad78..18292c1be 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -246,7 +246,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid params := mustEnc(&actors.CreateStorageMinerParams{ Owner: owner, Worker: worker, - SectorSize: build.SectorSizes[0], + SectorSize: 1024, // TODO: needs to come from preseals info PeerID: pid, }) diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 6126db082..28b7a71b9 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -291,28 +291,28 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea } } -/* sealedPath, err := sb.sealedSectorPath(sectorID) - if err != nil { - return nil, err - } + /* sealedPath, err := sb.sealedSectorPath(sectorID) + if err != nil { + return nil, err + } - err = sectorbuilder.ImportSealedSector( - sb.handle, - sectorID, - cacheDir, - sealedPath, - ticket, - seed, - rspco.CommR, - rspco.CommD, - rspco.CommC, - rspco.CommRLast, - proof, - pmeta, - ) - if err != nil { - return nil, xerrors.Errorf("ImportSealedSector: %w", err) - }*/ + err = sectorbuilder.ImportSealedSector( + sb.handle, + sectorID, + cacheDir, + sealedPath, + ticket, + seed, + rspco.CommR, + rspco.CommD, + rspco.CommC, + rspco.CommRLast, + proof, + pmeta, + ) + if err != nil { + return nil, xerrors.Errorf("ImportSealedSector: %w", err) + }*/ return proof, nil } @@ -357,9 +357,13 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, var cseed [CommLen]byte copy(cseed[:], challengeSeed) - challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + privsects, err := sb.pubSectorToPriv(sectorInfo) + if err != nil { + return nil, err + } - return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, cseed, challengeCount, winners) + proverID := addressToProverID(sb.Miner) + return sectorbuilder.StandaloneGeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) } func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { From 86cd28fa7ef73d89e64285a3b0c85cfbd9a87594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 13:29:42 +0100 Subject: [PATCH 13/93] sectorbuilder: Measure thigs in TestSealAndVerify --- lib/sectorbuilder/sectorbuilder.go | 31 ------------------------- lib/sectorbuilder/sectorbuilder_test.go | 26 ++++++++++++++++++--- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 28b7a71b9..b8c015cdc 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -282,37 +282,6 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea return nil, xerrors.Errorf("StandaloneSealCommit: %w", err) } - pmeta := make([]sectorbuilder.PieceMetadata, len(pieces)) - for i, piece := range pieces { - pmeta[i] = sectorbuilder.PieceMetadata{ - Key: pieceKeys[i], - Size: piece.Size, - CommP: piece.CommP, - } - } - - /* sealedPath, err := sb.sealedSectorPath(sectorID) - if err != nil { - return nil, err - } - - err = sectorbuilder.ImportSealedSector( - sb.handle, - sectorID, - cacheDir, - sealedPath, - ticket, - seed, - rspco.CommR, - rspco.CommD, - rspco.CommC, - rspco.CommRLast, - proof, - pmeta, - ) - if err != nil { - return nil, xerrors.Errorf("ImportSealedSector: %w", err) - }*/ return proof, nil } diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 4f5c111fb..39e0a2bd1 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -21,7 +21,6 @@ import ( ) const sectorSize = 1024 - type seal struct { sid uint64 @@ -77,7 +76,7 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() done() } -func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) { +func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) time.Time { cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} ssi := sectorbuilder.NewSortedPublicSectorInfo([]sectorbuilder.PublicSectorInfo{{ @@ -90,6 +89,12 @@ func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) { t.Fatalf("%+v", err) } + genCandidates := time.Now() + + if len(candndates) != 1 { + t.Fatal("expected 1 candidate") + } + postProof, err := sb.ComputeElectionPoSt(ssi, cSeed[:], candndates) if err != nil { t.Fatalf("%+v", err) @@ -102,6 +107,8 @@ func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) { if !ok { t.Fatal("bad post") } + + return genCandidates } func TestSealAndVerify(t *testing.T) { @@ -147,11 +154,19 @@ func TestSealAndVerify(t *testing.T) { s := seal{sid: si} + start := time.Now() + s.precommit(t, sb, 1, func() {}) + precommit := time.Now() + s.commit(t, sb, func() {}) - s.post(t, sb) + commit := time.Now() + + genCandidiates := s.post(t, sb) + + epost := time.Now() // Restart sectorbuilder, re-run post sb.Destroy() @@ -161,6 +176,11 @@ func TestSealAndVerify(t *testing.T) { } s.post(t, sb) + + fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String()) + fmt.Printf("Commit: %s\n", commit.Sub(precommit).String()) + fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(commit).String()) + fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String()) } func TestSealAndVerify2(t *testing.T) { From 72c7ec748fd15cae91b29f798fe2e8bc1a1933f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 14:52:59 +0100 Subject: [PATCH 14/93] seed: Get params --- cmd/lotus-seed/main.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index 8bbf4d9df..cb011a42b 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -9,15 +9,16 @@ import ( "os" "path/filepath" + badger "github.com/ipfs/go-ds-badger" + logging "github.com/ipfs/go-log" + "github.com/mitchellh/go-homedir" + "golang.org/x/xerrors" + "gopkg.in/urfave/cli.v2" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/lib/sectorbuilder" - - badger "github.com/ipfs/go-ds-badger" - logging "github.com/ipfs/go-log" - "github.com/mitchellh/go-homedir" - "gopkg.in/urfave/cli.v2" ) var log = logging.Logger("lotus-seed") @@ -108,6 +109,10 @@ var preSealCmd = &cli.Command{ return err } + if err := build.GetParams(true, false); err != nil { + return xerrors.Errorf("getting params: %w", err) + } + sb, err := sectorbuilder.New(cfg, mds) if err != nil { return err From 871c30d2a04b3bd4581ec4b0e545250cd41ef27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 16:15:32 +0100 Subject: [PATCH 15/93] WIP trying to get election post to compute --- build/bootstrap/bootstrappers.pi | 1 - build/bootstrap/root.pi | 1 - build/params.go | 3 +- cmd/lotus-seed/main.go | 13 ++++- lib/sectorbuilder/sectorbuilder.go | 2 +- lib/sectorbuilder/sectorbuilder_test.go | 68 ++++++++++++++++++++++++- miner/miner.go | 2 +- storage/miner.go | 2 +- storage/sector_states.go | 2 +- 9 files changed, 84 insertions(+), 10 deletions(-) delete mode 100644 build/bootstrap/bootstrappers.pi delete mode 100644 build/bootstrap/root.pi diff --git a/build/bootstrap/bootstrappers.pi b/build/bootstrap/bootstrappers.pi deleted file mode 100644 index 27abfeb3f..000000000 --- a/build/bootstrap/bootstrappers.pi +++ /dev/null @@ -1 +0,0 @@ -/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWFCkQdiJEMBVA6RrWq22ZXVFfM41YX8soQ5QVvNFjMJT8 diff --git a/build/bootstrap/root.pi b/build/bootstrap/root.pi deleted file mode 100644 index af18e8d88..000000000 --- a/build/bootstrap/root.pi +++ /dev/null @@ -1 +0,0 @@ -/ip4/147.75.80.29/tcp/1347/p2p/12D3KooWSw9h3e6YrYZfRWDcir8qMV7ctZG9VmtXwSaP2ntsKXYf diff --git a/build/params.go b/build/params.go index 63b6ef95f..d316d8b5e 100644 --- a/build/params.go +++ b/build/params.go @@ -90,8 +90,7 @@ const SectorChallengeRatioDiv = 25 const EcRandomnessLookback = 300 const FallbackPoStBegin = 1000 -const SlashablePowerDelay = 2000 - +const SlashablePowerDelay = 2000 const PowerCollateralProportion = 5 const PerCapitaCollateralProportion = 1 diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index cb011a42b..c84761831 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -137,7 +137,7 @@ var preSealCmd = &cli.Command{ pco, err := sb.SealPreCommit(i, ticket, []sectorbuilder.PublicPieceInfo{pi}) if err != nil { - return err + return xerrors.Errorf("commit: %w", err) } sealedSectors = append(sealedSectors, genesis.PreSeal{ @@ -145,6 +145,17 @@ var preSealCmd = &cli.Command{ CommD: pco.CommD, SectorID: i, }) + + srand := sha256.Sum256([]byte(c.String("seed-preimage"))) + seed := sectorbuilder.SealSeed{ + TicketBytes: srand, + } + + _, err = sb.SealCommit(i, ticket, seed, []sectorbuilder.PublicPieceInfo{pi}, pco) + if err != nil { + return xerrors.Errorf("commit: %w", err) + } + } output := map[string]genesis.GenesisMiner{ diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index b8c015cdc..b4dc9557f 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -258,7 +258,7 @@ func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, piece return rspco, nil } -func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed SealSeed, pieces []PublicPieceInfo, pieceKeys []string, rspco RawSealPreCommitOutput) (proof []byte, err error) { +func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed SealSeed, pieces []PublicPieceInfo, rspco RawSealPreCommitOutput) (proof []byte, err error) { ret := sb.RateLimit() defer ret() diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 39e0a2bd1..6ad7f96fe 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -21,6 +21,7 @@ import ( ) const sectorSize = 1024 + type seal struct { sid uint64 @@ -59,7 +60,7 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() TicketBytes: [32]byte{0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9}, } - proof, err := sb.SealCommit(s.sid, s.ticket, seed, []sectorbuilder.PublicPieceInfo{s.ppi}, []string{"foo"}, s.pco) + proof, err := sb.SealCommit(s.sid, s.ticket, seed, []sectorbuilder.PublicPieceInfo{s.ppi}, s.pco) if err != nil { t.Fatalf("%+v", err) } @@ -183,6 +184,71 @@ func TestSealAndVerify(t *testing.T) { fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String()) } +func TestSealPoStNoCommit(t *testing.T) { + if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware + t.Skip("this is slow") + } + os.Setenv("BELLMAN_NO_GPU", "1") + os.Setenv("RUST_LOG", "info") + + build.SectorSizes = []uint64{sectorSize} + + if err := build.GetParams(true, true); err != nil { + t.Fatalf("%+v", err) + } + + ds := datastore.NewMapDatastore() + + dir, err := ioutil.TempDir("", "sbtest") + if err != nil { + t.Fatal(err) + } + + sb, err := sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds) + if err != nil { + t.Fatalf("%+v", err) + } + cleanup := func() { + sb.Destroy() + if t.Failed() { + fmt.Printf("not removing %s\n", dir) + return + } + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + } + defer cleanup() + + si, err := sb.AcquireSectorId() + if err != nil { + t.Fatalf("%+v", err) + } + + s := seal{sid: si} + + start := time.Now() + + s.precommit(t, sb, 1, func() {}) + + precommit := time.Now() + + // Restart sectorbuilder, re-run post + sb.Destroy() + sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds) + if err != nil { + t.Fatalf("%+v", err) + } + + genCandidiates := s.post(t, sb) + + epost := time.Now() + + fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String()) + fmt.Printf("GenCandidates: %s\n", genCandidiates.Sub(precommit).String()) + fmt.Printf("EPoSt: %s\n", epost.Sub(genCandidiates).String()) +} + func TestSealAndVerify2(t *testing.T) { if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware t.Skip("this is slow") diff --git a/miner/miner.go b/miner/miner.go index 7fa0f63c2..aea344cc7 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -165,7 +165,7 @@ eventLoop: for _, addr := range addrs { b, err := m.mineOne(ctx, addr, base) if err != nil { - log.Errorf("mining block failed: %s", err) + log.Errorf("mining block failed: %+v", err) continue } if b != nil { diff --git a/storage/miner.go b/storage/miner.go index f8323b2ac..3721be65c 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -143,7 +143,7 @@ func NewElectionPoStProver(sb *sectorbuilder.SectorBuilder) *sectorBuilderEpp { return §orBuilderEpp{sb} } -var _ (gen.ElectionPoStProver) = (*sectorBuilderEpp)(nil) +var _ gen.ElectionPoStProver = (*sectorBuilderEpp)(nil) func (epp *sectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) { var faults []uint64 // TODO diff --git a/storage/sector_states.go b/storage/sector_states.go index 537ee2b1d..ec0810d26 100644 --- a/storage/sector_states.go +++ b/storage/sector_states.go @@ -176,7 +176,7 @@ func (m *Miner) preCommitted(ctx context.Context, sector SectorInfo) (func(*Sect func (m *Miner) committing(ctx context.Context, sector SectorInfo) (func(*SectorInfo), error) { log.Info("scheduling seal proof computation...") - proof, err := m.sb.SealCommit(sector.SectorID, sector.Ticket.SB(), sector.Seed.SB(), sector.pieceInfos(), sector.refs(), sector.rspco()) + proof, err := m.sb.SealCommit(sector.SectorID, sector.Ticket.SB(), sector.Seed.SB(), sector.pieceInfos(), sector.rspco()) if err != nil { return nil, xerrors.Errorf("computing seal proof failed: %w", err) } From 23900964a115a5c9be4d87623a2ca50d477c795f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 17:35:37 +0100 Subject: [PATCH 16/93] Fix mixed up CommD/R in genesis creation --- chain/gen/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 18292c1be..773ef83ab 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -296,7 +296,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid ps, ok := gmcfg.PreSeals[maddr.String()] if ok { for _, s := range ps.Sectors { - nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommD[:], s.CommR[:]) + nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:]) if err != nil { return cid.Undef, xerrors.Errorf("failed to add fake sector to sector set: %w", err) } From fc72da1d0cc08d0b5b1418c48944ab1e061edc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 18:06:05 +0100 Subject: [PATCH 17/93] chain: Pass correct prover to VerifyPost --- chain/sync.go | 2 +- cmd/lotus-seed/main.go | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index 8608e717d..73b45fe05 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -643,7 +643,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc } return xerrors.Errorf("[TESTING] election post was invalid") } - ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, waddr) + ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, h.Miner) if err != nil { return xerrors.Errorf("failed to verify election post: %w", err) } diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index c84761831..d9ea27013 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -145,17 +145,6 @@ var preSealCmd = &cli.Command{ CommD: pco.CommD, SectorID: i, }) - - srand := sha256.Sum256([]byte(c.String("seed-preimage"))) - seed := sectorbuilder.SealSeed{ - TicketBytes: srand, - } - - _, err = sb.SealCommit(i, ticket, seed, []sectorbuilder.PublicPieceInfo{pi}, pco) - if err != nil { - return xerrors.Errorf("commit: %w", err) - } - } output := map[string]genesis.GenesisMiner{ From 8297feb1d338767057a2c7ec4783d11c6ff33928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 18:29:18 +0100 Subject: [PATCH 18/93] Pass correct randomness to EPoSt Verification --- chain/sync.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chain/sync.go b/chain/sync.go index 73b45fe05..a99012030 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -3,6 +3,7 @@ package chain import ( "bytes" "context" + "crypto/sha256" "errors" "fmt" "sync" @@ -643,7 +644,8 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc } return xerrors.Errorf("[TESTING] election post was invalid") } - ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, h.EPostProof.PostRand, h.EPostProof.Proof, winners, h.Miner) + hvrf := sha256.Sum256(h.EPostProof.PostRand) + ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner) if err != nil { return xerrors.Errorf("failed to verify election post: %w", err) } From d5a632f644c6a8794aee80c01c7e2505ed0212ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 23:13:01 +0100 Subject: [PATCH 19/93] sectorbuilder: Drop stateful sectorbuilder refs --- lib/sectorbuilder/mock.go | 2 - lib/sectorbuilder/sectorbuilder.go | 70 ++++++------------------- lib/sectorbuilder/sectorbuilder_test.go | 4 -- node/modules/storageminer.go | 9 +--- 4 files changed, 18 insertions(+), 67 deletions(-) diff --git a/lib/sectorbuilder/mock.go b/lib/sectorbuilder/mock.go index e9661ada1..de2009b46 100644 --- a/lib/sectorbuilder/mock.go +++ b/lib/sectorbuilder/mock.go @@ -17,8 +17,6 @@ func TempSectorbuilder(sectorSize uint64, ds dtypes.MetadataDS) (*SectorBuilder, sb, err := TempSectorbuilderDir(dir, sectorSize, ds) return sb, func() { - sb.Destroy() - if err := os.RemoveAll(dir); err != nil { log.Warn("failed to clean up temp sectorbuilder: ", err) } diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index b4dc9557f..a08df7ea8 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -3,18 +3,15 @@ package sectorbuilder import ( "context" "fmt" - "io" - "os" - "sort" - "strconv" - "sync" - "unsafe" - sectorbuilder "github.com/filecoin-project/go-sectorbuilder" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log" "go.opencensus.io/trace" "golang.org/x/xerrors" + "io" + "os" + "strconv" + "sync" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" @@ -55,11 +52,11 @@ type EPostCandidate = sectorbuilder.Candidate const CommLen = sectorbuilder.CommitmentBytesLen type SectorBuilder struct { - handle unsafe.Pointer - ds dtypes.MetadataDS - idLk sync.Mutex + ds dtypes.MetadataDS + idLk sync.Mutex - ssize uint64 + ssize uint64 + lastID uint64 Miner address.Address @@ -87,8 +84,6 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { return nil, xerrors.Errorf("minimum worker threads is %d, specified %d", PoStReservedWorkers+1, cfg.WorkerThreads) } - proverId := addressToProverID(cfg.Miner) - for _, dir := range []string{cfg.StagedDir, cfg.SealedDir, cfg.CacheDir, cfg.MetadataDir} { if err := os.Mkdir(dir, 0755); err != nil { if os.IsExist(err) { @@ -112,16 +107,11 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { return nil, err } - sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, PoRepProofPartitions, lastUsedID, cfg.MetadataDir, proverId, cfg.SealedDir, cfg.StagedDir, cfg.CacheDir, 16, cfg.WorkerThreads) - if err != nil { - return nil, err - } - sb := &SectorBuilder{ - handle: sbp, - ds: ds, + ds: ds, - ssize: cfg.SectorSize, + ssize: cfg.SectorSize, + lastID: lastUsedID, stagedDir: cfg.StagedDir, sealedDir: cfg.SealedDir, @@ -155,19 +145,14 @@ func addressToProverID(a address.Address) [32]byte { return proverId } -func (sb *SectorBuilder) Destroy() { - sectorbuilder.DestroySectorBuilder(sb.handle) -} - func (sb *SectorBuilder) AcquireSectorId() (uint64, error) { sb.idLk.Lock() defer sb.idLk.Unlock() - id, err := sectorbuilder.AcquireSectorId(sb.handle) - if err != nil { - return 0, err - } - err = sb.ds.Put(lastSectorIdKey, []byte(fmt.Sprint(id))) + sb.lastID++ + id := sb.lastID + + err := sb.ds.Put(lastSectorIdKey, []byte(fmt.Sprint(id))) if err != nil { return 0, err } @@ -212,7 +197,8 @@ func (sb *SectorBuilder) ReadPieceFromSealedSector(pieceKey string) ([]byte, err ret := sb.RateLimit() defer ret() - return sectorbuilder.ReadPieceFromSealedSector(sb.handle, pieceKey) + panic("fixme") + //return sectorbuilder.StandaloneUnseal(sb.handle, pieceKey) } func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, pieces []PublicPieceInfo) (RawSealPreCommitOutput, error) { @@ -285,28 +271,6 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea return proof, nil } -func (sb *SectorBuilder) SealStatus(sector uint64) (SectorSealingStatus, error) { - return sectorbuilder.GetSectorSealingStatusByID(sb.handle, sector) -} - -func (sb *SectorBuilder) GetAllStagedSectors() ([]uint64, error) { - sectors, err := sectorbuilder.GetAllStagedSectors(sb.handle) - if err != nil { - return nil, err - } - - out := make([]uint64, len(sectors)) - for i, v := range sectors { - out[i] = v.SectorID - } - - sort.Slice(out, func(i, j int) bool { - return out[i] < out[j] - }) - - return out, nil -} - /* func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { // Wait, this is a blocking method with no way of interrupting it? diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 6ad7f96fe..0148898fb 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -137,7 +137,6 @@ func TestSealAndVerify(t *testing.T) { t.Fatalf("%+v", err) } cleanup := func() { - sb.Destroy() if t.Failed() { fmt.Printf("not removing %s\n", dir) return @@ -170,7 +169,6 @@ func TestSealAndVerify(t *testing.T) { epost := time.Now() // Restart sectorbuilder, re-run post - sb.Destroy() sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds) if err != nil { t.Fatalf("%+v", err) @@ -209,7 +207,6 @@ func TestSealPoStNoCommit(t *testing.T) { t.Fatalf("%+v", err) } cleanup := func() { - sb.Destroy() if t.Failed() { fmt.Printf("not removing %s\n", dir) return @@ -234,7 +231,6 @@ func TestSealPoStNoCommit(t *testing.T) { precommit := time.Now() // Restart sectorbuilder, re-run post - sb.Destroy() sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds) if err != nil { t.Fatalf("%+v", err) diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index bf0a6b98a..5be351323 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -200,19 +200,12 @@ func SetupBlockProducer(lc fx.Lifecycle, ds dtypes.MetadataDS, api api.FullNode, return m, nil } -func SectorBuilder(lc fx.Lifecycle, cfg *sectorbuilder.Config, ds dtypes.MetadataDS) (*sectorbuilder.SectorBuilder, error) { +func SectorBuilder(cfg *sectorbuilder.Config, ds dtypes.MetadataDS) (*sectorbuilder.SectorBuilder, error) { sb, err := sectorbuilder.New(cfg, ds) if err != nil { return nil, err } - lc.Append(fx.Hook{ - OnStop: func(context.Context) error { - sb.Destroy() - return nil - }, - }) - return sb, nil } From 407f6fa6f897a792b977fb602b580689c62be84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 26 Nov 2019 23:53:52 +0100 Subject: [PATCH 20/93] sync: correct vrfBase for ticket check --- chain/sync.go | 6 +++++- lib/sectorbuilder/sectorbuilder_test.go | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index a99012030..6254872c7 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -575,7 +575,11 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) tktsCheck := async.Err(func() error { - if err := syncer.validateTicket(ctx, h.Miner, waddr, h.Ticket, baseTs); err != nil { + vrfBase := gen.TicketHash(baseTs.MinTicket(), h.Miner) + + err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof) + + if err != nil { return xerrors.Errorf("validating block tickets failed: %w", err) } return nil diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 0148898fb..3018ebe58 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -270,7 +270,6 @@ func TestSealAndVerify2(t *testing.T) { t.Fatalf("%+v", err) } cleanup := func() { - sb.Destroy() if err := os.RemoveAll(dir); err != nil { t.Error(err) } @@ -327,8 +326,6 @@ func TestAcquireID(t *testing.T) { assertAcquire(2) assertAcquire(3) - sb.Destroy() - sb, err = sectorbuilder.TempSectorbuilderDir(dir, sectorSize, ds) if err != nil { t.Fatalf("%+v", err) @@ -338,7 +335,6 @@ func TestAcquireID(t *testing.T) { assertAcquire(5) assertAcquire(6) - sb.Destroy() if err := os.RemoveAll(dir); err != nil { t.Error(err) } From 249bd8389f4379af007c27062810d1f7afcb8cdd Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 26 Nov 2019 19:39:07 -0600 Subject: [PATCH 21/93] Copy over last sector ID key when migrating sectorbuilder --- cmd/lotus-storage-miner/init.go | 34 ++++++++++++++++++++++++++++-- lib/sectorbuilder/sectorbuilder.go | 15 +++++++------ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index a14090f59..3408bce17 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/ipfs/go-datastore" + badger "github.com/ipfs/go-ds-badger" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" "github.com/mitchellh/go-homedir" @@ -22,6 +23,7 @@ import ( "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/modules" + "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo" "github.com/filecoin-project/lotus/storage" ) @@ -115,9 +117,21 @@ var initCmd = &cli.Command{ if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { log.Infof("moving pre-sealed-sectors from %s into newly created storage miner repo", pssb) - if err := migratePreSealedSectors(pssb, repoPath); err != nil { + lr, err := r.Lock(repo.StorageMiner) + if err != nil { return err } + mds, err := lr.Datastore("/metadata") + if err != nil { + return err + } + + if err := migratePreSealedSectors(pssb, repoPath, mds); err != nil { + return err + } + if err := lr.Close(); err != nil { + return xerrors.Errorf("unlocking repo after preseal migration: %w", err) + } } if err := storageMinerInit(ctx, cctx, api, r); err != nil { @@ -142,12 +156,18 @@ var initCmd = &cli.Command{ // TODO: this method should be a lot more robust for mainnet. For testnet, its // fine if we mess things up a few times -func migratePreSealedSectors(presealsb string, repoPath string) error { +// Also probably makes sense for this method to be in the sectorbuilder package +func migratePreSealedSectors(presealsb string, repoPath string, mds dtypes.MetadataDS) error { pspath, err := homedir.Expand(presealsb) if err != nil { return err } + srcds, err := badger.NewDatastore(filepath.Join(pspath, "badger"), nil) + if err != nil { + return err + } + expRepo, err := homedir.Expand(repoPath) if err != nil { return err @@ -166,6 +186,16 @@ func migratePreSealedSectors(presealsb string, repoPath string) error { return err } } + + val, err := srcds.Get(sectorbuilder.LastSectorIdKey) + if err != nil { + return xerrors.Errorf("getting source last sector ID: %w", err) + } + + if err := mds.Put(sectorbuilder.LastSectorIdKey, val); err != nil { + return xerrors.Errorf("failed to write last sector ID key to target datastore: %w", err) + } + return nil } diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index a08df7ea8..1b43cc974 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -3,15 +3,16 @@ package sectorbuilder import ( "context" "fmt" + "io" + "os" + "strconv" + "sync" + sectorbuilder "github.com/filecoin-project/go-sectorbuilder" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log" "go.opencensus.io/trace" "golang.org/x/xerrors" - "io" - "os" - "strconv" - "sync" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" @@ -21,7 +22,7 @@ import ( const PoStReservedWorkers = 1 const PoRepProofPartitions = 2 -var lastSectorIdKey = datastore.NewKey("/sectorbuilder/last") +var LastSectorIdKey = datastore.NewKey("/sectorbuilder/last") var log = logging.Logger("sectorbuilder") @@ -94,7 +95,7 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { } var lastUsedID uint64 - b, err := ds.Get(lastSectorIdKey) + b, err := ds.Get(LastSectorIdKey) switch err { case nil: i, err := strconv.ParseInt(string(b), 10, 64) @@ -152,7 +153,7 @@ func (sb *SectorBuilder) AcquireSectorId() (uint64, error) { sb.lastID++ id := sb.lastID - err := sb.ds.Put(lastSectorIdKey, []byte(fmt.Sprint(id))) + err := sb.ds.Put(LastSectorIdKey, []byte(fmt.Sprint(id))) if err != nil { return 0, err } From 3623925f6655a0aab5a2571097127b5ed4f8d36c Mon Sep 17 00:00:00 2001 From: laser Date: Tue, 26 Nov 2019 17:46:17 -0800 Subject: [PATCH 22/93] replace go-bls-sigs and go-sectorbuilder with filecoin-ffi - remove old submodules and add new submodule - update build tooling to consume new unified static library - update consumers of old libs to use new package --- .gitmodules | 10 +++----- Makefile | 39 +++++++++--------------------- chain/actors/actor_miner.go | 5 ++-- chain/address/address.go | 2 +- chain/address/address_test.go | 2 +- chain/gen/gen.go | 7 +++--- chain/gen/mining.go | 2 +- chain/stmgr/stmgr.go | 2 +- chain/stmgr/utils.go | 5 ++-- chain/sync.go | 2 +- chain/types/signature_cgo.go | 2 +- chain/wallet/wallet.go | 2 +- extern/filecoin-ffi | 1 + extern/go-bls-sigs | 1 - extern/go-sectorbuilder | 1 - go.mod | 10 +++----- go.sum | 12 ++++++--- lib/padreader/padreader.go | 2 +- lib/sectorbuilder/sectorbuilder.go | 35 +++++++++++---------------- storage/post.go | 5 ++-- 20 files changed, 62 insertions(+), 85 deletions(-) create mode 160000 extern/filecoin-ffi delete mode 160000 extern/go-bls-sigs delete mode 160000 extern/go-sectorbuilder diff --git a/.gitmodules b/.gitmodules index d8e0ccfa6..c50b68575 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,4 @@ -[submodule "extern/go-bls-sigs"] - path = extern/go-bls-sigs - url = https://github.com/filecoin-project/go-bls-sigs.git -[submodule "extern/go-sectorbuilder"] - path = extern/go-sectorbuilder - url = https://github.com/filecoin-project/go-sectorbuilder +[submodule "extern/filecoin-ffi"] + path = extern/filecoin-ffi + url = git@github.com:filecoin-project/filecoin-ffi + branch = master diff --git a/Makefile b/Makefile index 9574fc5f3..af80fb0e6 100644 --- a/Makefile +++ b/Makefile @@ -12,37 +12,21 @@ MODULES:= CLEAN:= -## BLS +## FFI -BLS_PATH:=extern/go-bls-sigs/ -BLS_DEPS:=libbls_signatures.a libbls_signatures.pc libbls_signatures.h -BLS_DEPS:=$(addprefix $(BLS_PATH),$(BLS_DEPS)) +FFI_PATH:=extern/filecoin-ffi/ +FFI_DEPS:=libfilecoin.a filecoin.pc filecoin.h +FFI_DEPS:=$(addprefix $(FFI_PATH),$(FFI_DEPS)) -$(BLS_DEPS): build/.bls-install ; +$(FFI_DEPS): build/.filecoin-install ; -build/.bls-install: $(BLS_PATH) - $(MAKE) -C $(BLS_PATH) $(BLS_DEPS:$(BLS_PATH)%=%) +build/.filecoin-install: $(FFI_PATH) + $(MAKE) -C $(FFI_PATH) $(FFI_DEPS:$(FFI_PATH)%=%) @touch $@ -MODULES+=$(BLS_PATH) -BUILD_DEPS+=build/.bls-install -CLEAN+=build/.bls-install - -## SECTOR BUILDER - -SECTOR_BUILDER_PATH:=extern/go-sectorbuilder/ -SECTOR_BUILDER_DEPS:=libsector_builder_ffi.a sector_builder_ffi.pc sector_builder_ffi.h -SECTOR_BUILDER_DEPS:=$(addprefix $(SECTOR_BUILDER_PATH),$(SECTOR_BUILDER_DEPS)) - -$(SECTOR_BUILDER_DEPS): build/.sector-builder-install ; - -build/.sector-builder-install: $(SECTOR_BUILDER_PATH) - $(MAKE) -C $(SECTOR_BUILDER_PATH) $(SECTOR_BUILDER_DEPS:$(SECTOR_BUILDER_PATH)%=%) - @touch $@ - -MODULES+=$(SECTOR_BUILDER_PATH) -BUILD_DEPS+=build/.sector-builder-install -CLEAN+=build/.sector-builder-install +MODULES+=$(FFI_PATH) +BUILD_DEPS+=build/.filecoin-install +CLEAN+=build/.filecoin-install $(MODULES): build/.update-modules ; @@ -123,8 +107,7 @@ stats: clean: rm -rf $(CLEAN) - -$(MAKE) -C $(BLS_PATH) clean - -$(MAKE) -C $(SECTOR_BUILDER_PATH) clean + -$(MAKE) -C $(FFI_PATH) clean .PHONY: clean dist-clean: diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index efbec6a82..6661f7bc0 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -5,6 +5,7 @@ import ( "context" "encoding/binary" "fmt" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/aerrors" @@ -455,13 +456,13 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM return nil, aerrors.HandleExternalError(lerr, "could not load proving set node") } - var sectorInfos []sectorbuilder.PublicSectorInfo + var sectorInfos []ffi.PublicSectorInfo if err := pss.ForEach(func(id uint64, v *cbg.Deferred) error { var comms [][]byte if err := cbor.DecodeInto(v.Raw, &comms); err != nil { return xerrors.New("could not decode comms") } - si := sectorbuilder.PublicSectorInfo{ + si := ffi.PublicSectorInfo{ SectorID: id, } commR := comms[0] diff --git a/chain/address/address.go b/chain/address/address.go index 4264371d3..c2c6c5943 100644 --- a/chain/address/address.go +++ b/chain/address/address.go @@ -7,7 +7,7 @@ import ( "io" "strconv" - "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-leb128" cbor "github.com/ipfs/go-ipld-cbor" "github.com/minio/blake2b-simd" diff --git a/chain/address/address_test.go b/chain/address/address_test.go index 1c666ee7c..33e69312f 100644 --- a/chain/address/address_test.go +++ b/chain/address/address_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/filecoin-project/go-bls-sigs" + "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-leb128" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/chain/gen/gen.go b/chain/gen/gen.go index e8c662040..5121bdc7b 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/binary" "fmt" + ffi "github.com/filecoin-project/filecoin-ffi" "sync/atomic" "github.com/ipfs/go-blockservice" @@ -414,7 +415,7 @@ type ElectionPoStProver interface { } type eppProvider struct { - sectors []sectorbuilder.PublicSectorInfo + sectors []ffi.PublicSectorInfo } func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { @@ -455,11 +456,11 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add } log.Warningf("Proving set for miner %s: %s", miner, pset) - var sinfos []sectorbuilder.PublicSectorInfo + var sinfos []ffi.PublicSectorInfo for _, s := range pset { var commRa [32]byte copy(commRa[:], s.CommR) - sinfos = append(sinfos, sectorbuilder.PublicSectorInfo{ + sinfos = append(sinfos, ffi.PublicSectorInfo{ SectorID: s.SectorID, CommR: commRa, }) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 5789de2a2..a2548c5ab 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -4,7 +4,7 @@ import ( "context" amt "github.com/filecoin-project/go-amt-ipld" - bls "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" cid "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" cbg "github.com/whyrusleeping/cbor-gen" diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index ad23f55f5..a1a656d7f 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -15,7 +15,7 @@ import ( cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - bls "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" logging "github.com/ipfs/go-log" diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 39017cb2d..1a1a46ad0 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -2,6 +2,7 @@ package stmgr import ( "context" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors" @@ -185,11 +186,11 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types. return nil, xerrors.Errorf("failed to get sector set for miner: %w", err) } - var uselessOtherArray []sectorbuilder.PublicSectorInfo + var uselessOtherArray []ffi.PublicSectorInfo for _, s := range sectors { var uselessBuffer [32]byte copy(uselessBuffer[:], s.CommR) - uselessOtherArray = append(uselessOtherArray, sectorbuilder.PublicSectorInfo{ + uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{ SectorID: s.SectorID, CommR: uselessBuffer, }) diff --git a/chain/sync.go b/chain/sync.go index 6254872c7..baecf3002 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -11,7 +11,7 @@ import ( "github.com/Gurpartap/async" amt "github.com/filecoin-project/go-amt-ipld" - "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" diff --git a/chain/types/signature_cgo.go b/chain/types/signature_cgo.go index 901cab944..4b5a262f6 100644 --- a/chain/types/signature_cgo.go +++ b/chain/types/signature_cgo.go @@ -5,7 +5,7 @@ package types import ( "fmt" - bls "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/lib/crypto" "github.com/minio/blake2b-simd" diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index eeb1af1cb..9dec1864e 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "github.com/filecoin-project/go-bls-sigs" + bls "github.com/filecoin-project/filecoin-ffi" logging "github.com/ipfs/go-log" "github.com/minio/blake2b-simd" diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi new file mode 160000 index 000000000..3de4c1567 --- /dev/null +++ b/extern/filecoin-ffi @@ -0,0 +1 @@ +Subproject commit 3de4c1567da6cea906a95b87a179c85dbec16c6d diff --git a/extern/go-bls-sigs b/extern/go-bls-sigs deleted file mode 160000 index 1c177e24f..000000000 --- a/extern/go-bls-sigs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1c177e24fd71669a1c8cc2e0ce4ba6e247e34d77 diff --git a/extern/go-sectorbuilder b/extern/go-sectorbuilder deleted file mode 160000 index e75744852..000000000 --- a/extern/go-sectorbuilder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e757448529bd87318e9b52b93661f6cda1a76a42 diff --git a/go.mod b/go.mod index 5fb9e2754..d3e0ea533 100644 --- a/go.mod +++ b/go.mod @@ -11,10 +11,9 @@ require ( github.com/btcsuite/btcd v0.0.0-20190807005414-4063feeff79a // indirect github.com/fatih/color v1.7.0 // indirect github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7 + github.com/filecoin-project/filecoin-ffi v0.0.0-00010101000000-000000000000 github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 - github.com/filecoin-project/go-bls-sigs v0.0.0-20190718224239-4bc4b8a7bbf8 github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 - github.com/filecoin-project/go-sectorbuilder v0.0.0-00010101000000-000000000000 github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/go-ole/go-ole v1.2.4 // indirect github.com/google/go-cmp v0.3.1 // indirect @@ -43,7 +42,7 @@ require ( github.com/ipfs/go-ipfs-routing v0.1.0 github.com/ipfs/go-ipld-cbor v0.0.3 github.com/ipfs/go-ipld-format v0.0.2 - github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144 + github.com/ipfs/go-log v1.0.0 github.com/ipfs/go-merkledag v0.2.4 github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb github.com/ipld/go-ipld-prime v0.0.2-0.20191025154717-8dff1cbec43b @@ -89,7 +88,6 @@ require ( github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect github.com/stretchr/testify v1.4.0 - github.com/urfave/cli v1.20.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 @@ -113,6 +111,4 @@ require ( replace github.com/golangci/golangci-lint => github.com/golangci/golangci-lint v1.18.0 -replace github.com/filecoin-project/go-bls-sigs => ./extern/go-bls-sigs - -replace github.com/filecoin-project/go-sectorbuilder => ./extern/go-sectorbuilder +replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi diff --git a/go.sum b/go.sum index d9f303a61..dc802c681 100644 --- a/go.sum +++ b/go.sum @@ -78,12 +78,11 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7 h1:Ags/z6ZubzKonQ9PsY9fO439yGdVg07qpdxfv/AEUno= github.com/filecoin-project/chain-validation v0.0.0-20191106200742-11986803c0f7/go.mod h1:0/0/QUNqpF/jVzLHFncGeT3NvGPODBhGzQlNgzmoZew= -github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16 h1:NzojcJU1VbS6zdLG13JMYis/cQy/MrN3rxmZRq56jKA= -github.com/filecoin-project/go-amt-ipld v0.0.0-20190919045431-3650716fff16/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 h1:lKSMm8Go6qI7+Dk3rWCNIh57wBOqVNJ21re/p7D58gc= github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8= +github.com/filecoin-project/go-sectorbuilder v0.0.0-20191125152826-0aeff9f9485d/go.mod h1:NulUuak/mLUOIX+p5p6E9fCaR9VekiU1wpTgUB+DPgw= 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= @@ -220,8 +219,8 @@ github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dC github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144 h1:5WM8S1nwquWQ3zEuNhK82NE5Di6Pd41qz9JxxvxTAIA= -github.com/ipfs/go-log v0.0.2-0.20190920042044-a609c1ae5144/go.mod h1:azGN5dH7ailfREknDDNYB0Eq4qZ/4I4Y3gO0ivjJNyM= +github.com/ipfs/go-log v1.0.0 h1:BW3LQIiZzpNyolt84yvKNCd3FU+AK4VDw1hnHR+1aiI= +github.com/ipfs/go-log v1.0.0/go.mod h1:JO7RzlMK6rA+CIxFMLOuB6Wf5b81GDiKElL7UPSIKjA= github.com/ipfs/go-merkledag v0.1.0/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.3/go.mod h1:SQiXrtSts3KGNmgOzMICy5c0POOpUNQLvB3ClKnBAlk= github.com/ipfs/go-merkledag v0.2.4 h1:ZSHQSe9BENfixUjT+MaLeHEeZGxrZQfgo3KT3SLosF8= @@ -417,6 +416,7 @@ github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNA github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -635,6 +635,7 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -667,6 +668,7 @@ golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -709,6 +711,7 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -723,6 +726,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0YB3n5fVYggzysUmiUQ89SnX6Y= gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/lib/padreader/padreader.go b/lib/padreader/padreader.go index 135e35b57..179ae305b 100644 --- a/lib/padreader/padreader.go +++ b/lib/padreader/padreader.go @@ -4,7 +4,7 @@ import ( "io" "math/bits" - sectorbuilder "github.com/filecoin-project/go-sectorbuilder" + sectorbuilder "github.com/filecoin-project/filecoin-ffi" ) func PaddedSize(size uint64) uint64 { diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 1b43cc974..ea6e43977 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -8,7 +8,7 @@ import ( "strconv" "sync" - sectorbuilder "github.com/filecoin-project/go-sectorbuilder" + sectorbuilder "github.com/filecoin-project/filecoin-ffi" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log" "go.opencensus.io/trace" @@ -26,16 +26,9 @@ var LastSectorIdKey = datastore.NewKey("/sectorbuilder/last") var log = logging.Logger("sectorbuilder") -type SectorSealingStatus = sectorbuilder.SectorSealingStatus - -type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata - type SortedPublicSectorInfo = sectorbuilder.SortedPublicSectorInfo type SortedPrivateSectorInfo = sectorbuilder.SortedPrivateSectorInfo -type PrivateSectorInfo = sectorbuilder.SectorPrivateInfo -type PublicSectorInfo = sectorbuilder.SectorPublicInfo - type SealTicket = sectorbuilder.SealTicket type SealSeed = sectorbuilder.SealSeed @@ -174,7 +167,7 @@ func (sb *SectorBuilder) AddPiece(pieceSize uint64, sectorId uint64, file io.Rea return PublicPieceInfo{}, err } - _, _, commP, err := sectorbuilder.StandaloneWriteWithAlignment(f, pieceSize, stagedFile, existingPieceSizes) + _, _, commP, err := sectorbuilder.WriteWithAlignment(f, pieceSize, stagedFile, existingPieceSizes) if err != nil { return PublicPieceInfo{}, err } @@ -199,7 +192,7 @@ func (sb *SectorBuilder) ReadPieceFromSealedSector(pieceKey string) ([]byte, err defer ret() panic("fixme") - //return sectorbuilder.StandaloneUnseal(sb.handle, pieceKey) + //return sectorbuilder.Unseal(sb.handle, pieceKey) } func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, pieces []PublicPieceInfo) (RawSealPreCommitOutput, error) { @@ -227,7 +220,7 @@ func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, piece stagedPath := sb.stagedSectorPath(sectorID) - rspco, err := sectorbuilder.StandaloneSealPreCommit( + rspco, err := sectorbuilder.SealPreCommit( sb.ssize, PoRepProofPartitions, cacheDir, @@ -254,7 +247,7 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea return nil, err } - proof, err = sectorbuilder.StandaloneSealCommit( + proof, err = sectorbuilder.SealCommit( sb.ssize, PoRepProofPartitions, cacheDir, @@ -266,7 +259,7 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea rspco, ) if err != nil { - return nil, xerrors.Errorf("StandaloneSealCommit: %w", err) + return nil, xerrors.Errorf("SealCommit: %w", err) } return proof, nil @@ -297,7 +290,7 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, } proverID := addressToProverID(sb.Miner) - return sectorbuilder.StandaloneGeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) + return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) } func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { @@ -309,11 +302,11 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) - return sectorbuilder.StandaloneGenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) + return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) } func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) { - var out []PrivateSectorInfo + var out []sectorbuilder.PrivateSectorInfo for _, s := range sectorInfo.Values() { cachePath, err := sb.sectorCacheDir(s.SectorID) if err != nil { @@ -325,7 +318,7 @@ func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (Sor return SortedPrivateSectorInfo{}, xerrors.Errorf("getting sealed path for sector %d: %w", s.SectorID, err) } - out = append(out, PrivateSectorInfo{ + out = append(out, sectorbuilder.PrivateSectorInfo{ SectorID: s.SectorID, CommR: s.CommR, CacheDirPath: cachePath, @@ -352,12 +345,12 @@ func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) } -func NewSortedPrivateSectorInfo(sectors []PrivateSectorInfo) SortedPrivateSectorInfo { - return sectorbuilder.NewSortedSectorPrivateInfo(sectors...) +func NewSortedPrivateSectorInfo(sectors []sectorbuilder.PrivateSectorInfo) SortedPrivateSectorInfo { + return sectorbuilder.NewSortedPrivateSectorInfo(sectors...) } -func NewSortedPublicSectorInfo(sectors []PublicSectorInfo) SortedPublicSectorInfo { - return sectorbuilder.NewSortedSectorPublicInfo(sectors...) +func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedPublicSectorInfo { + return sectorbuilder.NewSortedPublicSectorInfo(sectors...) } func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) { diff --git a/storage/post.go b/storage/post.go index 270a66751..072b9615c 100644 --- a/storage/post.go +++ b/storage/post.go @@ -2,6 +2,7 @@ package storage import ( "context" + ffi "github.com/filecoin-project/filecoin-ffi" "time" "github.com/ipfs/go-cid" @@ -166,12 +167,12 @@ func (p *post) preparePost(ctx context.Context) error { func (p *post) sortedSectorInfo() sectorbuilder.SortedPrivateSectorInfo { panic("NYI") - sbsi := make([]sectorbuilder.PrivateSectorInfo, len(p.sset)) + sbsi := make([]ffi.PrivateSectorInfo, len(p.sset)) for k, sector := range p.sset { var commR [sectorbuilder.CommLen]byte copy(commR[:], sector.CommR) - sbsi[k] = sectorbuilder.PrivateSectorInfo{ + sbsi[k] = ffi.PrivateSectorInfo{ SectorID: sector.SectorID, CommR: commR, } From 718d681f73fb6d5c0fd3b67a4f226d08802e98d6 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 26 Nov 2019 20:47:08 -0600 Subject: [PATCH 23/93] Add lotus-bench for testing hardware specs --- cmd/lotus-bench/main.go | 208 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 cmd/lotus-bench/main.go diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go new file mode 100644 index 000000000..da4ecf8f0 --- /dev/null +++ b/cmd/lotus-bench/main.go @@ -0,0 +1,208 @@ +package main + +import ( + "crypto/sha256" + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + "time" + + "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log" + "github.com/mitchellh/go-homedir" + "golang.org/x/xerrors" + "gopkg.in/urfave/cli.v2" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/lib/sectorbuilder" +) + +var log = logging.Logger("lotus-bench") + +type BenchResults struct { + SectorSize uint64 + + SealingResults []SealingResult + + PostGenerateCandidates time.Duration + PostEProof time.Duration +} + +type SealingResult struct { + AddPiece time.Duration + PreCommit time.Duration + Commit time.Duration +} + +func main() { + logging.SetLogLevel("*", "INFO") + + log.Info("Starting lotus-bench") + + app := &cli.App{ + Name: "lotus-bench", + Usage: "Benchmark performance of lotus on your hardware", + Version: build.Version, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "storage-dir", + Value: "~/.lotus-bench", + Usage: "Path to the storage directory that will store sectors long term", + }, + &cli.Uint64Flag{ + Name: "sector-size", + Value: 1024, + }, + }, + Action: func(c *cli.Context) error { + sdir, err := homedir.Expand(c.String("storage-dir")) + if err != nil { + return err + } + + os.MkdirAll(sdir, 0775) + + tsdir, err := ioutil.TempDir(sdir, "bench") + if err != nil { + return err + } + defer func() { + if err := os.RemoveAll(tsdir); err != nil { + log.Warn("remove all: ", err) + } + }() + + maddr, err := address.NewFromString("t0101") + if err != nil { + return err + } + + mds := datastore.NewMapDatastore() + cfg := §orbuilder.Config{ + Miner: maddr, + SectorSize: c.Uint64("sector-size"), + WorkerThreads: 2, + CacheDir: filepath.Join(tsdir, "cache"), + SealedDir: filepath.Join(tsdir, "sealed"), + StagedDir: filepath.Join(tsdir, "staged"), + MetadataDir: filepath.Join(tsdir, "meta"), + } + for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { + if err := os.MkdirAll(d, 0775); err != nil { + return err + } + } + + if err := build.GetParams(true, false); err != nil { + return xerrors.Errorf("getting params: %w", err) + } + sb, err := sectorbuilder.New(cfg, mds) + if err != nil { + return err + } + + r := rand.New(rand.NewSource(101)) + size := sectorbuilder.UserBytesForSectorSize(c.Uint64("sector-size")) + + var sealTimings []SealingResult + var sealedSectors []sectorbuilder.PublicSectorInfo + numSectors := uint64(1) + for i := uint64(1); i <= numSectors; i++ { + start := time.Now() + log.Info("Writing piece into sector...") + pi, err := sb.AddPiece(size, i, r, nil) + if err != nil { + return err + } + + addpiece := time.Now() + + trand := sha256.Sum256([]byte(c.String("ticket-preimage"))) + ticket := sectorbuilder.SealTicket{ + TicketBytes: trand, + } + + log.Info("Running replication...") + pieces := []sectorbuilder.PublicPieceInfo{pi} + pco, err := sb.SealPreCommit(i, ticket, pieces) + if err != nil { + return xerrors.Errorf("commit: %w", err) + } + + precommit := time.Now() + + sealedSectors = append(sealedSectors, sectorbuilder.PublicSectorInfo{ + CommR: pco.CommR, + SectorID: i, + }) + + seed := sectorbuilder.SealSeed{ + BlockHeight: 101, + TicketBytes: [32]byte{1, 2, 3, 4, 5}, + } + + log.Info("Generating PoRep for sector") + proof, err := sb.SealCommit(i, ticket, seed, pieces, pco) + if err != nil { + return err + } + _ = proof // todo verify + + sealcommit := time.Now() + + sealTimings = append(sealTimings, SealingResult{ + AddPiece: addpiece.Sub(start), + PreCommit: precommit.Sub(addpiece), + Commit: sealcommit.Sub(precommit), + }) + } + + beforePost := time.Now() + + var challenge [32]byte + rand.Read(challenge[:]) + + log.Info("generating election post candidates") + sinfos := sectorbuilder.NewSortedPublicSectorInfo(sealedSectors) + candidates, err := sb.GenerateEPostCandidates(sinfos, challenge, []uint64{}) + if err != nil { + return err + } + + gencandidates := time.Now() + + log.Info("computing election post snark") + proof, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1]) + if err != nil { + return err + } + _ = proof // todo verify + + epost := time.Now() + + benchout := BenchResults{ + SectorSize: cfg.SectorSize, + SealingResults: sealTimings, + + PostGenerateCandidates: gencandidates.Sub(beforePost), + PostEProof: epost.Sub(gencandidates), + } // TODO: optionally write this as json to a file + + fmt.Println("results") + fmt.Printf("seal: addPiece: %s\n", benchout.SealingResults[0].AddPiece) // TODO: average across multiple sealings + fmt.Printf("seal: preCommit: %s\n", benchout.SealingResults[0].PreCommit) + fmt.Printf("seal: Commit: %s\n", benchout.SealingResults[0].Commit) + fmt.Printf("generate candidates: %s\n", benchout.PostGenerateCandidates) + fmt.Printf("compute epost proof: %s\n", benchout.PostEProof) + return nil + }, + } + + if err := app.Run(os.Args); err != nil { + log.Warn(err) + return + } +} From 11502ccfcf4fed42c1381bb1f5773d748b6d22f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 12:35:16 +0100 Subject: [PATCH 24/93] Use https in gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index c50b68575..a655f05b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "extern/filecoin-ffi"] path = extern/filecoin-ffi - url = git@github.com:filecoin-project/filecoin-ffi + url = https://github.com/filecoin-project/filecoin-ffi.git branch = master From 03b1d2329fb71f6d85344015bb2015a8fa9659e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 12:57:52 +0100 Subject: [PATCH 25/93] seed: Call AcquireID for sectorIDs --- chain/gen/mining.go | 2 +- chain/sync.go | 2 +- cmd/lotus-seed/main.go | 15 ++++++++++++--- cmd/lotus-storage-miner/init.go | 2 +- cmd/lotus-storage-miner/main.go | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index a2548c5ab..e9aeaef7d 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -3,8 +3,8 @@ package gen import ( "context" - amt "github.com/filecoin-project/go-amt-ipld" bls "github.com/filecoin-project/filecoin-ffi" + amt "github.com/filecoin-project/go-amt-ipld" cid "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" cbg "github.com/whyrusleeping/cbor-gen" diff --git a/chain/sync.go b/chain/sync.go index baecf3002..4ec8b153a 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -10,8 +10,8 @@ import ( "time" "github.com/Gurpartap/async" - amt "github.com/filecoin-project/go-amt-ipld" bls "github.com/filecoin-project/filecoin-ffi" + amt "github.com/filecoin-project/go-amt-ipld" "github.com/hashicorp/go-multierror" "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index d9ea27013..2ec30ab38 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -123,7 +123,12 @@ var preSealCmd = &cli.Command{ var sealedSectors []genesis.PreSeal for i := uint64(1); i <= c.Uint64("num-sectors"); i++ { - pi, err := sb.AddPiece(size, i, r, nil) + sid, err := sb.AcquireSectorId() + if err != nil { + return err + } + + pi, err := sb.AddPiece(size, sid, r, nil) if err != nil { return err } @@ -135,7 +140,7 @@ var preSealCmd = &cli.Command{ fmt.Println("Piece info: ", pi) - pco, err := sb.SealPreCommit(i, ticket, []sectorbuilder.PublicPieceInfo{pi}) + pco, err := sb.SealPreCommit(sid, ticket, []sectorbuilder.PublicPieceInfo{pi}) if err != nil { return xerrors.Errorf("commit: %w", err) } @@ -143,7 +148,7 @@ var preSealCmd = &cli.Command{ sealedSectors = append(sealedSectors, genesis.PreSeal{ CommR: pco.CommR, CommD: pco.CommD, - SectorID: i, + SectorID: sid, }) } @@ -162,6 +167,10 @@ var preSealCmd = &cli.Command{ return err } + if err := mds.Close(); err != nil { + return xerrors.Errorf("closing datastore: %w", err) + } + return nil }, } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 3408bce17..87d51769d 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -165,7 +165,7 @@ func migratePreSealedSectors(presealsb string, repoPath string, mds dtypes.Metad srcds, err := badger.NewDatastore(filepath.Join(pspath, "badger"), nil) if err != nil { - return err + return xerrors.Errorf("openning presealed sectors datastore: %w", err) } expRepo, err := homedir.Expand(repoPath) diff --git a/cmd/lotus-storage-miner/main.go b/cmd/lotus-storage-miner/main.go index ca83189b9..26913a17a 100644 --- a/cmd/lotus-storage-miner/main.go +++ b/cmd/lotus-storage-miner/main.go @@ -70,7 +70,7 @@ func main() { } if err := app.Run(os.Args); err != nil { - log.Warn(err) + log.Warnf("%+v", err) os.Exit(1) } } From 4a77fdac4c9d58b5a49f1c6f2ffb3522691a14fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 13:12:42 +0100 Subject: [PATCH 26/93] bench: Fix after filecoin-ffi switch --- cmd/lotus-bench/main.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index da4ecf8f0..a4ed62fd1 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -9,6 +9,7 @@ import ( "path/filepath" "time" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log" "github.com/mitchellh/go-homedir" @@ -108,7 +109,7 @@ func main() { size := sectorbuilder.UserBytesForSectorSize(c.Uint64("sector-size")) var sealTimings []SealingResult - var sealedSectors []sectorbuilder.PublicSectorInfo + var sealedSectors []ffi.PublicSectorInfo numSectors := uint64(1) for i := uint64(1); i <= numSectors; i++ { start := time.Now() @@ -134,7 +135,7 @@ func main() { precommit := time.Now() - sealedSectors = append(sealedSectors, sectorbuilder.PublicSectorInfo{ + sealedSectors = append(sealedSectors, ffi.PublicSectorInfo{ CommR: pco.CommR, SectorID: i, }) From d2412f4f0085007bf4625add5d04406903354068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 15:18:51 +0100 Subject: [PATCH 27/93] Fix pond --- cmd/lotus-seed/main.go | 96 +---------------------------- cmd/lotus-seed/seed/seed.go | 106 ++++++++++++++++++++++++++++++++ lotuspond/front/src/FullNode.js | 10 --- lotuspond/spawn.go | 23 ++++++- miner/miner.go | 5 ++ storage/post.go | 50 +++++++-------- 6 files changed, 159 insertions(+), 131 deletions(-) create mode 100644 cmd/lotus-seed/seed/seed.go diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index 2ec30ab38..f17e11bf3 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -1,24 +1,15 @@ package main import ( - "crypto/sha256" - "encoding/json" - "fmt" - "io/ioutil" - "math/rand" "os" - "path/filepath" - badger "github.com/ipfs/go-ds-badger" logging "github.com/ipfs/go-log" "github.com/mitchellh/go-homedir" - "golang.org/x/xerrors" "gopkg.in/urfave/cli.v2" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" - "github.com/filecoin-project/lotus/genesis" - "github.com/filecoin-project/lotus/lib/sectorbuilder" + "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" ) var log = logging.Logger("lotus-seed") @@ -88,89 +79,6 @@ var preSealCmd = &cli.Command{ return err } - cfg := §orbuilder.Config{ - Miner: maddr, - SectorSize: c.Uint64("sector-size"), - CacheDir: filepath.Join(sbroot, "cache"), - SealedDir: filepath.Join(sbroot, "sealed"), - StagedDir: filepath.Join(sbroot, "staging"), - MetadataDir: filepath.Join(sbroot, "meta"), - WorkerThreads: 2, - } - - for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { - if err := os.MkdirAll(d, 0775); err != nil { - return err - } - } - - mds, err := badger.NewDatastore(filepath.Join(sbroot, "badger"), nil) - if err != nil { - return err - } - - if err := build.GetParams(true, false); err != nil { - return xerrors.Errorf("getting params: %w", err) - } - - sb, err := sectorbuilder.New(cfg, mds) - if err != nil { - return err - } - - r := rand.New(rand.NewSource(101)) - size := sectorbuilder.UserBytesForSectorSize(c.Uint64("sector-size")) - - var sealedSectors []genesis.PreSeal - for i := uint64(1); i <= c.Uint64("num-sectors"); i++ { - sid, err := sb.AcquireSectorId() - if err != nil { - return err - } - - pi, err := sb.AddPiece(size, sid, r, nil) - if err != nil { - return err - } - - trand := sha256.Sum256([]byte(c.String("ticket-preimage"))) - ticket := sectorbuilder.SealTicket{ - TicketBytes: trand, - } - - fmt.Println("Piece info: ", pi) - - pco, err := sb.SealPreCommit(sid, ticket, []sectorbuilder.PublicPieceInfo{pi}) - if err != nil { - return xerrors.Errorf("commit: %w", err) - } - - sealedSectors = append(sealedSectors, genesis.PreSeal{ - CommR: pco.CommR, - CommD: pco.CommD, - SectorID: sid, - }) - } - - output := map[string]genesis.GenesisMiner{ - maddr.String(): genesis.GenesisMiner{ - Sectors: sealedSectors, - }, - } - - out, err := json.MarshalIndent(output, "", " ") - if err != nil { - return err - } - - if err := ioutil.WriteFile("pre-seal-"+maddr.String()+".json", out, 0664); err != nil { - return err - } - - if err := mds.Close(); err != nil { - return xerrors.Errorf("closing datastore: %w", err) - } - - return nil + return seed.PreSeal(maddr, c.Uint64("sector-size"), c.Uint64("num-sectors"), sbroot, []byte(c.String("ticket-preimage"))) }, } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go new file mode 100644 index 000000000..790897800 --- /dev/null +++ b/cmd/lotus-seed/seed/seed.go @@ -0,0 +1,106 @@ +package seed + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + + badger "github.com/ipfs/go-ds-badger" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/lib/sectorbuilder" +) + +func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, preimage []byte) error { + cfg := §orbuilder.Config{ + Miner: maddr, + SectorSize: ssize, + CacheDir: filepath.Join(sbroot, "cache"), + SealedDir: filepath.Join(sbroot, "sealed"), + StagedDir: filepath.Join(sbroot, "staging"), + MetadataDir: filepath.Join(sbroot, "meta"), + WorkerThreads: 2, + } + + for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { + if err := os.MkdirAll(d, 0775); err != nil { + return err + } + } + + mds, err := badger.NewDatastore(filepath.Join(sbroot, "badger"), nil) + if err != nil { + return err + } + + if err := build.GetParams(true, false); err != nil { + return xerrors.Errorf("getting params: %w", err) + } + + sb, err := sectorbuilder.New(cfg, mds) + if err != nil { + return err + } + + r := rand.New(rand.NewSource(101)) + size := sectorbuilder.UserBytesForSectorSize(ssize) + + var sealedSectors []genesis.PreSeal + for i := uint64(1); i <= sectors; i++ { + sid, err := sb.AcquireSectorId() + if err != nil { + return err + } + + pi, err := sb.AddPiece(size, sid, r, nil) + if err != nil { + return err + } + + trand := sha256.Sum256(preimage) + ticket := sectorbuilder.SealTicket{ + TicketBytes: trand, + } + + fmt.Println("Piece info: ", pi) + + pco, err := sb.SealPreCommit(sid, ticket, []sectorbuilder.PublicPieceInfo{pi}) + if err != nil { + return xerrors.Errorf("commit: %w", err) + } + + sealedSectors = append(sealedSectors, genesis.PreSeal{ + CommR: pco.CommR, + CommD: pco.CommD, + SectorID: sid, + }) + } + + output := map[string]genesis.GenesisMiner{ + maddr.String(): genesis.GenesisMiner{ + Sectors: sealedSectors, + }, + } + + out, err := json.MarshalIndent(output, "", " ") + if err != nil { + return err + } + + if err := ioutil.WriteFile(filepath.Join(sbroot, "pre-seal-"+maddr.String()+".json"), out, 0664); err != nil { + return err + } + + if err := mds.Close(); err != nil { + return xerrors.Errorf("closing datastore: %w", err) + } + + return nil +} diff --git a/lotuspond/front/src/FullNode.js b/lotuspond/front/src/FullNode.js index 874288261..eb530dee3 100644 --- a/lotuspond/front/src/FullNode.js +++ b/lotuspond/front/src/FullNode.js @@ -45,8 +45,6 @@ class FullNode extends React.Component { return this.props.client.call('Filecoin.PaychVoucherList', [paych]) })) - let minerList = await this.props.client.call('Filecoin.MinerAddresses', []) - let mpoolPending = (await this.props.client.call('Filecoin.MpoolPending', [tipset])).length this.setState(() => ({ @@ -62,8 +60,6 @@ class FullNode extends React.Component { vouchers: vouchers, defaultAddr: defaultAddr, - - minerList: minerList, })) } @@ -110,11 +106,6 @@ class FullNode extends React.Component { ) } - let miners = - if(this.state.minerList.length > 0) { - miners = this.state.minerList.map((a, k) =>
) - } - let storageMine = let addresses = this.state.addrs.map((addr) => { @@ -153,7 +144,6 @@ class FullNode extends React.Component {
Balances: [New [Secp256k1] [BLS]]
{addresses}
-
{miners}
{paychannels}
diff --git a/lotuspond/spawn.go b/lotuspond/spawn.go index a4f4c0b36..5f0faa35c 100644 --- a/lotuspond/spawn.go +++ b/lotuspond/spawn.go @@ -11,6 +11,10 @@ import ( "time" "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" ) func (api *api) Spawn() (nodeInfo, error) { @@ -19,9 +23,24 @@ func (api *api) Spawn() (nodeInfo, error) { return nodeInfo{}, err } + params := []string{"daemon", "--bootstrap=false"} genParam := "--genesis=" + api.genesis + id := atomic.AddInt32(&api.cmds, 1) if id == 1 { + // preseal + + genMiner, err := address.NewIDAddress(101) + if err != nil { + return nodeInfo{}, err + } + + err = seed.PreSeal(genMiner, build.SectorSizes[0], 1, filepath.Join(dir, "preseal"), []byte("8")) + if err != nil { + return nodeInfo{}, xerrors.Errorf("preseal failed: %w", err) + } + params = append(params, "--genesis-presealed-sectors="+filepath.Join(dir, "preseal", "pre-seal-t0101.json")) + // make genesis genf, err := ioutil.TempFile(os.TempDir(), "lotus-genesis-") if err != nil { @@ -54,7 +73,7 @@ func (api *api) Spawn() (nodeInfo, error) { return nodeInfo{}, err } - cmd := exec.Command("./lotus", "daemon", "--bootstrap=false", genParam) + cmd := exec.Command("./lotus", append(params, genParam)...) cmd.Stderr = io.MultiWriter(os.Stderr, errlogfile, mux.errpw) cmd.Stdout = io.MultiWriter(os.Stdout, logfile, mux.outpw) @@ -114,7 +133,7 @@ func (api *api) SpawnStorage(fullNodeRepo string) (nodeInfo, error) { initArgs := []string{"init"} if fullNodeRepo == api.running[1].meta.Repo { - initArgs = []string{"init", "--actor=t0101", "--genesis-miner"} + initArgs = []string{"init", "--actor=t0101", "--genesis-miner", "--pre-sealed-sectors=" + filepath.Join(fullNodeRepo, "preseal")} } id := atomic.AddInt32(&api.cmds, 1) diff --git a/miner/miner.go b/miner/miner.go index 6da666002..f8004240a 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -239,6 +239,8 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) { log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids())) + start := time.Now() + ticket, err := m.computeTicket(ctx, addr, base) if err != nil { return nil, xerrors.Errorf("scratching ticket failed: %w", err) @@ -260,6 +262,9 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB } log.Infow("mined new block", "cid", b.Cid()) + dur := time.Now().Sub(start) + log.Infof("Creating block took %s", dur) + return b, nil } diff --git a/storage/post.go b/storage/post.go index 628f7b94c..22163dfc8 100644 --- a/storage/post.go +++ b/storage/post.go @@ -219,32 +219,32 @@ func (p *post) commitPost(ctx context.Context) (err error) { panic("NYI") /* - params := &actors.SubmitPoStParams{ - //Proof: p.proof, + params := &actors.SubmitPoStParams{ + //Proof: p.proof, + } + + enc, aerr := actors.SerializeParams(params) + if aerr != nil { + return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + } + + msg := &types.Message{ + To: p.m.maddr, + From: p.m.worker, + Method: actors.MAMethods.SubmitPoSt, + Params: enc, + Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late + GasLimit: types.NewInt(1000000), // i dont know help + GasPrice: types.NewInt(1), + } + + log.Info("mpush") + + p.smsg, err = p.m.api.MpoolPushMessage(ctx, msg) + if err != nil { + return xerrors.Errorf("pushing message to mpool: %w", err) } - - enc, aerr := actors.SerializeParams(params) - if aerr != nil { - return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) - } - - msg := &types.Message{ - To: p.m.maddr, - From: p.m.worker, - Method: actors.MAMethods.SubmitPoSt, - Params: enc, - Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late - GasLimit: types.NewInt(1000000), // i dont know help - GasPrice: types.NewInt(1), - } - - log.Info("mpush") - - p.smsg, err = p.m.api.MpoolPushMessage(ctx, msg) - if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) - } - */ + */ return nil } From 1ccfe7d8f7b21293e43a661700820ddd6174d85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 16:00:04 +0100 Subject: [PATCH 28/93] update filecoin-ffi to v18 params --- build/params_shared.go | 14 ++++++++++++++ extern/filecoin-ffi | 2 +- lib/sectorbuilder/sectorbuilder.go | 12 +++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/build/params_shared.go b/build/params_shared.go index 44b66248d..48a30a530 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -19,6 +19,20 @@ var SectorSizes = []uint64{ 1 << 30, } +const nodeSize = 32 + +// sector size -> winSzNodes +// +// https://github.com/filecoin-project/rust-fil-proofs/blob/master/filecoin-proofs/src/constants.rs#L16-L20 +var WindowSizeNodes = map[uint64]uint32{ + 1 << 10: 512 / nodeSize, + + 16 << 20: (4 << 20) / nodeSize, + 256 << 20: (64 << 20) / nodeSize, + + 1 << 30: (128 << 20) / nodeSize, +} + func SupportedSectorSize(ssize uint64) bool { for _, ss := range SectorSizes { if ssize == ss { diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 3de4c1567..dbe28c13b 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 3de4c1567da6cea906a95b87a179c85dbec16c6d +Subproject commit dbe28c13b59755d7c004f33db9f71eee0e93b5be diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index fae3db3b9..4b9b922a0 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -222,6 +222,7 @@ func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, piece rspco, err := sectorbuilder.SealPreCommit( sb.ssize, + build.WindowSizeNodes[sb.ssize], PoRepProofPartitions, cacheDir, stagedPath, @@ -249,6 +250,7 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea proof, err = sectorbuilder.SealCommit( sb.ssize, + build.WindowSizeNodes[sb.ssize], PoRepProofPartitions, cacheDir, sectorID, @@ -290,7 +292,7 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, } proverID := addressToProverID(sb.Miner) - return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) + return sectorbuilder.GeneratePoSt(sb.ssize, build.WindowSizeNodes[sb.ssize], proverID, privsects, cseed, winners) } func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { @@ -302,7 +304,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) - return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) + return sectorbuilder.GenerateCandidates(sb.ssize, build.WindowSizeNodes[sb.ssize], proverID, challengeSeed, challengeCount, privsectors) } func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) { @@ -342,7 +344,7 @@ func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address copy(seeda[:], seed) proverIDa := addressToProverID(proverID) - return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) + return sectorbuilder.VerifySeal(sectorSize, build.WindowSizeNodes[sectorSize], commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) } func NewSortedPrivateSectorInfo(sectors []sectorbuilder.PrivateSectorInfo) SortedPrivateSectorInfo { @@ -362,7 +364,7 @@ func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicS _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() prover := addressToProverID(proverID) - return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) + return sectorbuilder.VerifyPoSt(sectorSize, build.WindowSizeNodes[sectorSize], sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { @@ -380,7 +382,7 @@ func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen] } func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]byte, error) { - return sectorbuilder.GenerateDataCommitment(ssize, pieces) + return sectorbuilder.GenerateDataCommitment(ssize, build.WindowSizeNodes[ssize], pieces) } func challangeCount(sectors uint64) uint64 { From 5d30106f5a736fb654d4a0e9d7190085fdcf106b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 18:10:34 +0100 Subject: [PATCH 29/93] More v18 updates --- build/paramfetch.go | 2 + build/proof-params/parameters.json | 122 ++++++++++++------------ cmd/lotus/daemon.go | 10 +- lib/sectorbuilder/sectorbuilder_test.go | 3 +- 4 files changed, 70 insertions(+), 67 deletions(-) diff --git a/build/paramfetch.go b/build/paramfetch.go index 21d590f2c..b167f1ca5 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -156,6 +156,8 @@ func doFetch(out string, info paramFile) error { if err != nil { return err } + log.Infof("GET %s", url) + req := http.Request{ Method: "GET", URL: url, diff --git a/build/proof-params/parameters.json b/build/proof-params/parameters.json index 544a8374b..7c62f82d5 100644 --- a/build/proof-params/parameters.json +++ b/build/proof-params/parameters.json @@ -1,82 +1,82 @@ { - "v17-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.params": { - "cid": "QmX1yk3iLPVd87nto2TjoR8ZRRUPS6VQrGjp6VGzJ5LMku", - "digest": "b77189b5fd4fdfb62aa10b711e2c07fe", + "v18-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.params": { + "cid": "QmPhNP5h6W2VjraH76Mqt9Knt5aKWwKz9y2AKAAn128hz3", + "digest": "7c9913cb96717672347fa91a6daf3d3e", "sector_size": 1024 }, - "v17-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.vk": { - "cid": "QmQbm46eEM7iixdU3N412CGXz17tegn2J3Yv37MwsuXwUv", - "digest": "5d67b3241bfba6832cfe55c044a5627f", + "v18-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.vk": { + "cid": "QmVoeBVUruL9rsM6FwgqaZWuq2nnWVeMxcWfpKQfUAV6z8", + "digest": "394a355e08107de25fabe6bf4f055065", "sector_size": 1024 }, - "v17-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.params": { - "cid": "QmVavKxo3kNt8TBvMUeicv4FvM9FJ2UhMYpUNExvwRTXEc", - "digest": "0c2acd67ae44c8c4d9b5bb20e1dedc1f", + "v18-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.params": { + "cid": "QmXN1msCQwChwNQiniQFepEQfkvM881FEkNinDQyybwEoH", + "digest": "3245eed51a7738a9d2055e57f4cffad1", "sector_size": 268435456 }, - "v17-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.vk": { - "cid": "QmS7kg73nQ6ErhhASi6AnwjnQT4PmGMxEFzCnsZYx3PUFf", - "digest": "259bbafc10bd5ad883e2b54f61780230", + "v18-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.vk": { + "cid": "QmTtz4j6WhvLcnq45H6pPL1gnu47ppf3pqFJNjMcb4ftU7", + "digest": "a6b5ed26e61ee1ba6d0157e2f4a00f91", "sector_size": 268435456 }, - "v17-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.params": { - "cid": "QmSz2YTybJDMCgW3ryvvNPQ2SJyBtASpWgzb5UfeTqQxJh", - "digest": "0ba0a7430cb9411e82cddd1b8a918428", + "v18-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.params": { + "cid": "QmSNwSUEAp4eJC2UWo1HgmQZELiZVUErWceRed9vT7WQKS", + "digest": "52ac57808d3c5132ee66c9693f8af5ee", "sector_size": 16777216 }, - "v17-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.vk": { - "cid": "QmWASM5eUWBaAqE6HAdjHWEHJKPW6veVgTuaJs45kKonwn", - "digest": "111a2ad1a6018ffc4e2a28644ed07f1b", + "v18-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.vk": { + "cid": "Qmeg26ZQ57oi8bHkkgeYuafKjyZMGDXJhbg2ZSJW1zbAb5", + "digest": "1a5fc7b62c09a6d96455dcba83ceb9af", "sector_size": 16777216 }, - "v17-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.params": { - "cid": "QmYwZVdahZ7irXaW423AXwfr2sbuCq3ih9oPFTo3mQpL6Y", - "digest": "a0107d57e12c33bdaf586bb54311ec90", + "v18-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.params": { + "cid": "QmQy5eJwSTyWhRj3eTofVKs7TF1c9FdXUKMKjfwniiLJDE", + "digest": "a88c8497274ca648d7f4e1c25b4c9cb8", "sector_size": 1073741824 }, - "v17-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.vk": { - "cid": "QmXHAwHcbpx31JFUeHs2mub4GPr4wsFSaCrxrxBHgy6adM", - "digest": "6e51dff3a3b51aef1ddf6b6f15c870f5", + "v18-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.vk": { + "cid": "QmR5HvUPWfoB1zJmG87dZdD8NrwseUgAkjau7j99RJrvVZ", + "digest": "499db4ed613683f430ba7fafd01f52e6", "sector_size": 1073741824 }, - "v17-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.params": { - "cid": "QmU5eYfCwyjsJ4perRgVW6KTq1bDLfQ7XcBhg9Z1mH42kQ", - "digest": "3d6d4ba0b2eae2695dfd73c916a66c95", - "sector_size": 16777216 - }, - "v17-stacked-proof-of-replication-0c0b444c6f31d11c8e98003cc99a3b938db26b77a296d4253cda8945c234266d.vk": { - "cid": "QmbB2Caq4muLCKbNJgH9KQddao5JYnB2JzYUMWwFq2Qm4Z", - "digest": "4a5efda7efb11b1af579baf30a41007f", - "sector_size": 16777216 - }, - "v17-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.params": { - "cid": "QmSh7aFgjutVthSCyDYDs7FjHKGtuZc9YaFnFBSpEvYE1Y", - "digest": "c92ebee7cfc2509b624736df083e790b", - "sector_size": 268435456 - }, - "v17-stacked-proof-of-replication-967b11bb59be11b7dc6f2b627520ba450a3aa50846dbbf886cb8b735fe25c4e7.vk": { - "cid": "QmVL7fjQftCCPo6vRkVErspADjFCoVqdRCR179g9PyLbez", - "digest": "1ca0cd9c59df03621dfdf1427ea735dc", - "sector_size": 268435456 - }, - "v17-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.params": { - "cid": "QmRXZCQdzP2kFfdHse953CxgdTupwT8fWQA7YmeqtAjM9H", - "digest": "5539c3c55c9b409e5432bc61f34b5786", - "sector_size": 1073741824 - }, - "v17-stacked-proof-of-replication-d01cd22091627b721c60a3375b5219af653fb9f6928c70aa7400587d396bc07a.vk": { - "cid": "QmdQGgWyYijAacJbRrdR42GYZz5QZhGQ1YY4kun2w27arx", - "digest": "716f20b705260ca43515a4bcff8e6f47", - "sector_size": 1073741824 - }, - "v17-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.params": { - "cid": "QmSkTjaq6X8jquVh6wsXrPVeMDMg7yC7fGJ1i3yeV54eiR", - "digest": "15fe50f23209ed875b4b44e3ee61c5c5", + "v18-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.params": { + "cid": "QmQb5mc3ksZh2K5GsNwJrkwuHoWXh8adBdJV3qTbFaRvGe", + "digest": "a187287b1d03cd7ec4f1fccd57f3f3d1", "sector_size": 1024 }, - "v17-stacked-proof-of-replication-f464b92d805d03de6e2c20e2530135b2c8ec96045ec58f342d6feb90282bff8a.vk": { - "cid": "QmZCU4KBnTkAQuhuRDwyopjzXEXSs13n34QCXM5a5a6AdY", - "digest": "e50d458bef1c840d5f1deff018a0d702", + "v18-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.vk": { + "cid": "QmYUjFHzeX22dfzv9wQxF4Qn8wS67bqBwr1Wcz2rga9rAZ", + "digest": "747792363f08d7b53be1a2f51f91582a", "sector_size": 1024 + }, + "v18-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.params": { + "cid": "QmRUZqCwYdcVfQ49Z97g2xkJnaSh4b9SHWwfB3kgZiPo9L", + "digest": "b9494e0ae432a0ebde9c8c877c914583", + "sector_size": 16777216 + }, + "v18-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.vk": { + "cid": "QmXngrBy74h8LYhYrbBpefXsXQFWLU3WX3LTXnVQnu1Sdc", + "digest": "af2c0d6834fa581b6f507f8266244dfb", + "sector_size": 16777216 + }, + "v18-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.params": { + "cid": "QmfNstuJFKnBt4yJHsNfoKahn1LafBdpJju23U5UNZd9Xy", + "digest": "3911d84ca2b86f491bc7c6372d7d9285", + "sector_size": 268435456 + }, + "v18-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.vk": { + "cid": "QmQgSRQBbp7udHDp5pNA3GSCjSyXktUHBw15wx9meL4wgc", + "digest": "ecd2a9bdd178b0ebc9110f568fd70d07", + "sector_size": 268435456 + }, + "v18-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.params": { + "cid": "QmV5mAkhohUHPRWoNtS3Uo4yvmF23CR2u8JxeeCqthMCdX", + "digest": "9306d91c3518b87016d5efc19428b25e", + "sector_size": 1073741824 + }, + "v18-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.vk": { + "cid": "QmPjwPdUQJmqp2rQuJX2dy57AC9YCwYtMHdpZzW5BG9JWh", + "digest": "a2004fca043da423df51f6c4bb65788c", + "sector_size": 1073741824 } -} +} \ No newline at end of file diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index 87ff1f0ad..c20ec7e6e 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -56,11 +56,11 @@ var DaemonCmd = &cli.Command{ ctx := context.Background() r, err := repo.NewFS(cctx.String("repo")) if err != nil { - return err + return xerrors.Errorf("opening fs repo: %w", err) } if err := r.Init(repo.FullNode); err != nil && err != repo.ErrRepoExists { - return err + return xerrors.Errorf("repo init error: %w", err) } if err := build.GetParams(false, false); err != nil { @@ -72,7 +72,7 @@ var DaemonCmd = &cli.Command{ if cctx.String("genesis") != "" { genBytes, err = ioutil.ReadFile(cctx.String("genesis")) if err != nil { - return err + return xerrors.Errorf("reading genesis: %w", err) } } @@ -112,12 +112,12 @@ var DaemonCmd = &cli.Command{ ), ) if err != nil { - return err + return xerrors.Errorf("initializing node: %w", err) } endpoint, err := r.APIEndpoint() if err != nil { - return err + return xerrors.Errorf("getting api endpoint: %w", err) } // TODO: properly parse api endpoint (or make it a URL) diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 3018ebe58..b55b6c5bf 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/lib/sectorbuilder" ) @@ -80,7 +81,7 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) time.Time { cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} - ssi := sectorbuilder.NewSortedPublicSectorInfo([]sectorbuilder.PublicSectorInfo{{ + ssi := sectorbuilder.NewSortedPublicSectorInfo([]ffi.PublicSectorInfo{{ SectorID: s.sid, CommR: s.pco.CommR, }}) From ce27cf965650fd29258d94c3377fc975503f2ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 21:08:52 +0100 Subject: [PATCH 30/93] v19 parameters --- build/proof-params/parameters.json | 76 +++++++++++++++--------------- extern/filecoin-ffi | 2 +- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/build/proof-params/parameters.json b/build/proof-params/parameters.json index 7c62f82d5..0fc8abffb 100644 --- a/build/proof-params/parameters.json +++ b/build/proof-params/parameters.json @@ -1,80 +1,80 @@ { - "v18-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.params": { - "cid": "QmPhNP5h6W2VjraH76Mqt9Knt5aKWwKz9y2AKAAn128hz3", - "digest": "7c9913cb96717672347fa91a6daf3d3e", - "sector_size": 1024 - }, - "v18-proof-of-spacetime-election-54266a3979de672c5f59a521e8e4a3fc2108da1eb019af74089ff6d05bfe83aa.vk": { - "cid": "QmVoeBVUruL9rsM6FwgqaZWuq2nnWVeMxcWfpKQfUAV6z8", - "digest": "394a355e08107de25fabe6bf4f055065", - "sector_size": 1024 - }, - "v18-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.params": { - "cid": "QmXN1msCQwChwNQiniQFepEQfkvM881FEkNinDQyybwEoH", - "digest": "3245eed51a7738a9d2055e57f4cffad1", + "v19-proof-of-spacetime-election-09ae025de08399327e14f0cb6b4c907b6fe1e8b77046e31de8921bde588de900.params": { + "cid": "QmZEKhzKbC7SPngjL85ghyuxabPmiEuUh4fpkC7CDK1J5q", + "digest": "1c81338b8afeaae514fd5d6c08c9c6e5", "sector_size": 268435456 }, - "v18-proof-of-spacetime-election-5dafbb8a1d6802f3b68f0dd2d3eff36d203263b4a867df986b1d434f1852726c.vk": { - "cid": "QmTtz4j6WhvLcnq45H6pPL1gnu47ppf3pqFJNjMcb4ftU7", - "digest": "a6b5ed26e61ee1ba6d0157e2f4a00f91", + "v19-proof-of-spacetime-election-09ae025de08399327e14f0cb6b4c907b6fe1e8b77046e31de8921bde588de900.vk": { + "cid": "Qmf5XQuM58jNmxudXeZMuZtGGiNzcd56Fiyn9h76wpX5dN", + "digest": "bb0f07b6071cd28e9348223c6a9c46d1", "sector_size": 268435456 }, - "v18-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.params": { - "cid": "QmSNwSUEAp4eJC2UWo1HgmQZELiZVUErWceRed9vT7WQKS", - "digest": "52ac57808d3c5132ee66c9693f8af5ee", - "sector_size": 16777216 + "v19-proof-of-spacetime-election-4a2342062706429612fac099694f77294e355c6c9265b80feaff12a0268b0a92.params": { + "cid": "QmaHs5CHcSD6QhaGAp4ysJP4HTZaxPxybCGmUVDk3TNocA", + "digest": "727fb2896a5668d04ba6e0ce71eb50d7", + "sector_size": 1024 }, - "v18-proof-of-spacetime-election-8923799c7eba68497833a94802c1f687aca037964aacbec838188c6d3912b718.vk": { - "cid": "Qmeg26ZQ57oi8bHkkgeYuafKjyZMGDXJhbg2ZSJW1zbAb5", - "digest": "1a5fc7b62c09a6d96455dcba83ceb9af", - "sector_size": 16777216 + "v19-proof-of-spacetime-election-4a2342062706429612fac099694f77294e355c6c9265b80feaff12a0268b0a92.vk": { + "cid": "QmVg8mUXMb6MiZQseAyCmHzEgNkPbV72xQoRmdFr1yJA4w", + "digest": "3fdf4e65a7baf1a2bab5b8a717f3379a", + "sector_size": 1024 }, - "v18-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.params": { - "cid": "QmQy5eJwSTyWhRj3eTofVKs7TF1c9FdXUKMKjfwniiLJDE", - "digest": "a88c8497274ca648d7f4e1c25b4c9cb8", + "v19-proof-of-spacetime-election-512f5e6dc00a37fa13c8b0e468188f85957b7bf1ab36d17fb9fe9ed49ae8d657.params": { + "cid": "QmYf1532WoeXhy8AoduWNxpBuwn5DEkpU6YFDGCXh1mqBX", + "digest": "983e641f9df01799bc33d5fb3c3020b2", "sector_size": 1073741824 }, - "v18-proof-of-spacetime-election-8ac1992c7b71f15757f62e11af51abc3d3b9db8ed8ed6804f4f06842d6d23bc5.vk": { - "cid": "QmR5HvUPWfoB1zJmG87dZdD8NrwseUgAkjau7j99RJrvVZ", - "digest": "499db4ed613683f430ba7fafd01f52e6", + "v19-proof-of-spacetime-election-512f5e6dc00a37fa13c8b0e468188f85957b7bf1ab36d17fb9fe9ed49ae8d657.vk": { + "cid": "QmVig7LUpNSXUcfjkSxUKsFaxqYxEZdaEARWvi14sbihJ4", + "digest": "e1f7a46b60217f1dddf56671dd86e6a7", "sector_size": 1073741824 }, - "v18-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.params": { + "v19-proof-of-spacetime-election-6c7cbfe7eed40b6c0b23a213a70648770aed65d9ca03ae85451573c18532304b.params": { + "cid": "QmSTF7C6vQbV6qjEQknXpBDuixBkxYeMshX25NonjJxjbi", + "digest": "b434ece6a37e588ca11ed117f1c14325", + "sector_size": 16777216 + }, + "v19-proof-of-spacetime-election-6c7cbfe7eed40b6c0b23a213a70648770aed65d9ca03ae85451573c18532304b.vk": { + "cid": "QmaFV9n5scuYxKc9QpJnbBUf4sjhkUzpZ7QkoTqL8XsNQz", + "digest": "9c2e40b6635470d3674324b01c9a3976", + "sector_size": 16777216 + }, + "v19-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.params": { "cid": "QmQb5mc3ksZh2K5GsNwJrkwuHoWXh8adBdJV3qTbFaRvGe", "digest": "a187287b1d03cd7ec4f1fccd57f3f3d1", "sector_size": 1024 }, - "v18-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.vk": { + "v19-stacked-proof-of-replication-5a438611c880423c4f5199787cd531b197846ef46af40af69222467ab9073226.vk": { "cid": "QmYUjFHzeX22dfzv9wQxF4Qn8wS67bqBwr1Wcz2rga9rAZ", "digest": "747792363f08d7b53be1a2f51f91582a", "sector_size": 1024 }, - "v18-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.params": { + "v19-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.params": { "cid": "QmRUZqCwYdcVfQ49Z97g2xkJnaSh4b9SHWwfB3kgZiPo9L", "digest": "b9494e0ae432a0ebde9c8c877c914583", "sector_size": 16777216 }, - "v18-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.vk": { + "v19-stacked-proof-of-replication-6ae8ae8998ef393ffd171487bc5141fa3642e9fd39e3a7dbada4f6e7bacffb9b.vk": { "cid": "QmXngrBy74h8LYhYrbBpefXsXQFWLU3WX3LTXnVQnu1Sdc", "digest": "af2c0d6834fa581b6f507f8266244dfb", "sector_size": 16777216 }, - "v18-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.params": { + "v19-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.params": { "cid": "QmfNstuJFKnBt4yJHsNfoKahn1LafBdpJju23U5UNZd9Xy", "digest": "3911d84ca2b86f491bc7c6372d7d9285", "sector_size": 268435456 }, - "v18-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.vk": { + "v19-stacked-proof-of-replication-d2ca0f634aebcecba88904612ff82f2349b080b1290879f3fba73c1d9a13d84e.vk": { "cid": "QmQgSRQBbp7udHDp5pNA3GSCjSyXktUHBw15wx9meL4wgc", "digest": "ecd2a9bdd178b0ebc9110f568fd70d07", "sector_size": 268435456 }, - "v18-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.params": { + "v19-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.params": { "cid": "QmV5mAkhohUHPRWoNtS3Uo4yvmF23CR2u8JxeeCqthMCdX", "digest": "9306d91c3518b87016d5efc19428b25e", "sector_size": 1073741824 }, - "v18-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.vk": { + "v19-stacked-proof-of-replication-f7b95455d6b7a5e967388a97c2ddc01807eff4c1736e84be4554853bf7783105.vk": { "cid": "QmPjwPdUQJmqp2rQuJX2dy57AC9YCwYtMHdpZzW5BG9JWh", "digest": "a2004fca043da423df51f6c4bb65788c", "sector_size": 1073741824 diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index dbe28c13b..0e3c18829 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit dbe28c13b59755d7c004f33db9f71eee0e93b5be +Subproject commit 0e3c18829e42c95e2c92242e612f77781d5825ea From 99b9dfe18df830ab19c91e0fb7dca518b8d2992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 27 Nov 2019 23:34:48 +0100 Subject: [PATCH 31/93] filecoin-ffi master --- build/params_shared.go | 14 -------------- extern/filecoin-ffi | 2 +- lib/sectorbuilder/sectorbuilder.go | 12 +++++------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/build/params_shared.go b/build/params_shared.go index 48a30a530..44b66248d 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -19,20 +19,6 @@ var SectorSizes = []uint64{ 1 << 30, } -const nodeSize = 32 - -// sector size -> winSzNodes -// -// https://github.com/filecoin-project/rust-fil-proofs/blob/master/filecoin-proofs/src/constants.rs#L16-L20 -var WindowSizeNodes = map[uint64]uint32{ - 1 << 10: 512 / nodeSize, - - 16 << 20: (4 << 20) / nodeSize, - 256 << 20: (64 << 20) / nodeSize, - - 1 << 30: (128 << 20) / nodeSize, -} - func SupportedSectorSize(ssize uint64) bool { for _, ss := range SectorSizes { if ssize == ss { diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 0e3c18829..0e71b164c 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 0e3c18829e42c95e2c92242e612f77781d5825ea +Subproject commit 0e71b164cf4b2e1c0f53ca25145e3ea57cc53e90 diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 4b9b922a0..fae3db3b9 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -222,7 +222,6 @@ func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, piece rspco, err := sectorbuilder.SealPreCommit( sb.ssize, - build.WindowSizeNodes[sb.ssize], PoRepProofPartitions, cacheDir, stagedPath, @@ -250,7 +249,6 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea proof, err = sectorbuilder.SealCommit( sb.ssize, - build.WindowSizeNodes[sb.ssize], PoRepProofPartitions, cacheDir, sectorID, @@ -292,7 +290,7 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, } proverID := addressToProverID(sb.Miner) - return sectorbuilder.GeneratePoSt(sb.ssize, build.WindowSizeNodes[sb.ssize], proverID, privsects, cseed, winners) + return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) } func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, error) { @@ -304,7 +302,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) - return sectorbuilder.GenerateCandidates(sb.ssize, build.WindowSizeNodes[sb.ssize], proverID, challengeSeed, challengeCount, privsectors) + return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) } func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (SortedPrivateSectorInfo, error) { @@ -344,7 +342,7 @@ func VerifySeal(sectorSize uint64, commR, commD []byte, proverID address.Address copy(seeda[:], seed) proverIDa := addressToProverID(proverID) - return sectorbuilder.VerifySeal(sectorSize, build.WindowSizeNodes[sectorSize], commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) + return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, proverIDa, ticketa, seeda, sectorID, proof) } func NewSortedPrivateSectorInfo(sectors []sectorbuilder.PrivateSectorInfo) SortedPrivateSectorInfo { @@ -364,7 +362,7 @@ func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicS _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() prover := addressToProverID(proverID) - return sectorbuilder.VerifyPoSt(sectorSize, build.WindowSizeNodes[sectorSize], sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { @@ -382,7 +380,7 @@ func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen] } func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]byte, error) { - return sectorbuilder.GenerateDataCommitment(ssize, build.WindowSizeNodes[ssize], pieces) + return sectorbuilder.GenerateDataCommitment(ssize, pieces) } func challangeCount(sectors uint64) uint64 { From 8fae155cf61f03c43ecd2b347bae4009584fb49d Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 27 Nov 2019 19:43:36 -0600 Subject: [PATCH 32/93] Add timings for proof verification --- chain/stmgr/stmgr.go | 1 - cmd/lotus-bench/main.go | 29 +++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index c13a894a2..d2ef66327 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -84,7 +84,6 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (cid. func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.BlockHeader, cb func(cid.Cid, *types.Message, *vm.ApplyRet) error) (cid.Cid, cid.Cid, error) { ctx, span := trace.StartSpan(ctx, "computeTipSetState") defer span.End() - fmt.Println("COMPUTE TIPSET STATE", len(blks)) for i := 0; i < len(blks); i++ { for j := i + 1; j < len(blks); j++ { diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index a4ed62fd1..03aa60658 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "crypto/sha256" "fmt" "io/ioutil" @@ -30,12 +31,14 @@ type BenchResults struct { PostGenerateCandidates time.Duration PostEProof time.Duration + VerifyEPost time.Duration } type SealingResult struct { AddPiece time.Duration PreCommit time.Duration Commit time.Duration + Verify time.Duration } func main() { @@ -81,10 +84,12 @@ func main() { return err } + sectorSize := c.Uint64("sector-size") + mds := datastore.NewMapDatastore() cfg := §orbuilder.Config{ Miner: maddr, - SectorSize: c.Uint64("sector-size"), + SectorSize: sectorSize, WorkerThreads: 2, CacheDir: filepath.Join(tsdir, "cache"), SealedDir: filepath.Join(tsdir, "sealed"), @@ -106,7 +111,7 @@ func main() { } r := rand.New(rand.NewSource(101)) - size := sectorbuilder.UserBytesForSectorSize(c.Uint64("sector-size")) + size := sectorbuilder.UserBytesForSectorSize(sectorSize) var sealTimings []SealingResult var sealedSectors []ffi.PublicSectorInfo @@ -150,14 +155,18 @@ func main() { if err != nil { return err } - _ = proof // todo verify sealcommit := time.Now() + commD := pi.CommP + sectorbuilder.VerifySeal(sectorSize, pco.CommR[:], commD[:], maddr, ticket.TicketBytes[:], seed.TicketBytes[:], i, proof) + + verifySeal := time.Now() sealTimings = append(sealTimings, SealingResult{ AddPiece: addpiece.Sub(start), PreCommit: precommit.Sub(addpiece), Commit: sealcommit.Sub(precommit), + Verify: verifySeal.Sub(sealcommit), }) } @@ -180,24 +189,36 @@ func main() { if err != nil { return err } - _ = proof // todo verify epost := time.Now() + ok, err := sectorbuilder.VerifyPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr) + if err != nil { + return err + } + if !ok { + log.Error("post verification failed") + } + + verifypost := time.Now() + benchout := BenchResults{ SectorSize: cfg.SectorSize, SealingResults: sealTimings, PostGenerateCandidates: gencandidates.Sub(beforePost), PostEProof: epost.Sub(gencandidates), + VerifyEPost: verifypost.Sub(epost), } // TODO: optionally write this as json to a file fmt.Println("results") fmt.Printf("seal: addPiece: %s\n", benchout.SealingResults[0].AddPiece) // TODO: average across multiple sealings fmt.Printf("seal: preCommit: %s\n", benchout.SealingResults[0].PreCommit) fmt.Printf("seal: Commit: %s\n", benchout.SealingResults[0].Commit) + fmt.Printf("seal: Verify: %s\n", benchout.SealingResults[0].Verify) fmt.Printf("generate candidates: %s\n", benchout.PostGenerateCandidates) fmt.Printf("compute epost proof: %s\n", benchout.PostEProof) + fmt.Printf("verify epost proof: %s\n", benchout.VerifyEPost) return nil }, } From 45288b8810eba42d3228ce97d01caf3a87515c38 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 27 Nov 2019 21:36:34 -0600 Subject: [PATCH 33/93] WIP: uncomment out windowed post code, try to make it work --- chain/actors/actor_miner.go | 3 +- lib/sectorbuilder/sectorbuilder.go | 26 +++++++++++--- storage/post.go | 57 ++++++++++++++---------------- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 6661f7bc0..f358fafc2 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -5,6 +5,7 @@ import ( "context" "encoding/binary" "fmt" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/build" @@ -389,7 +390,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC } type SubmitPoStParams struct { - Proof types.EPostProof + Proof []byte } func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index fae3db3b9..53f2a672c 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -299,7 +299,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn return nil, err } - challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) @@ -328,8 +328,24 @@ func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (Sor return NewSortedPrivateSectorInfo(out), nil } -func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPrivateSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { - panic("NYI") +func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { + privsectors, err := sb.pubSectorToPriv(sectorInfo) + if err != nil { + return nil, err + } + + challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) + if challengeCount > 10 { + challengeCount = 10 + } + + proverID := addressToProverID(sb.Miner) + candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) + if err != nil { + return nil, err + } + + return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsectors, challengeSeed, candidates) } var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector @@ -357,7 +373,7 @@ func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicS var challengeSeeda [CommLen]byte copy(challengeSeeda[:], challengeSeed) - challengeCount := challangeCount(uint64(len(sectorInfo.Values()))) + challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() @@ -383,7 +399,7 @@ func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]by return sectorbuilder.GenerateDataCommitment(ssize, pieces) } -func challangeCount(sectors uint64) uint64 { +func challengeCount(sectors uint64) uint64 { // ceil(sectors / build.SectorChallengeRatioDiv) return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv } diff --git a/storage/post.go b/storage/post.go index 22163dfc8..541d23b25 100644 --- a/storage/post.go +++ b/storage/post.go @@ -2,9 +2,10 @@ package storage import ( "context" - ffi "github.com/filecoin-project/filecoin-ffi" "time" + ffi "github.com/filecoin-project/filecoin-ffi" + "go.opencensus.io/trace" "golang.org/x/xerrors" @@ -170,20 +171,20 @@ func (p *post) preparePost(ctx context.Context) error { return nil } -func (p *post) sortedSectorInfo() sectorbuilder.SortedPrivateSectorInfo { +func (p *post) sortedSectorInfo() sectorbuilder.SortedPublicSectorInfo { panic("NYI") - sbsi := make([]ffi.PrivateSectorInfo, len(p.sset)) + sbsi := make([]ffi.PublicSectorInfo, len(p.sset)) for k, sector := range p.sset { var commR [sectorbuilder.CommLen]byte copy(commR[:], sector.CommR) - sbsi[k] = ffi.PrivateSectorInfo{ + sbsi[k] = ffi.PublicSectorInfo{ SectorID: sector.SectorID, CommR: commR, } } - return sectorbuilder.NewSortedPrivateSectorInfo(sbsi) + return sectorbuilder.NewSortedPublicSectorInfo(sbsi) } func (p *post) runPost(ctx context.Context) error { @@ -216,35 +217,31 @@ func (p *post) commitPost(ctx context.Context) (err error) { ctx, span := trace.StartSpan(ctx, "storage.commitPost") defer span.End() - panic("NYI") - /* + params := &actors.SubmitPoStParams{ + Proof: p.proof, + } - params := &actors.SubmitPoStParams{ - //Proof: p.proof, - } + enc, aerr := actors.SerializeParams(params) + if aerr != nil { + return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + } - enc, aerr := actors.SerializeParams(params) - if aerr != nil { - return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) - } + msg := &types.Message{ + To: p.m.maddr, + From: p.m.worker, + Method: actors.MAMethods.SubmitPoSt, + Params: enc, + Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late + GasLimit: types.NewInt(1000000), // i dont know help + GasPrice: types.NewInt(1), + } - msg := &types.Message{ - To: p.m.maddr, - From: p.m.worker, - Method: actors.MAMethods.SubmitPoSt, - Params: enc, - Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late - GasLimit: types.NewInt(1000000), // i dont know help - GasPrice: types.NewInt(1), - } + log.Info("mpush") - log.Info("mpush") - - p.smsg, err = p.m.api.MpoolPushMessage(ctx, msg) - if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) - } - */ + p.smsg, err = p.m.api.MpoolPushMessage(ctx, msg) + if err != nil { + return xerrors.Errorf("pushing message to mpool: %w", err) + } return nil } From 7afc0d4dbea6e31b929e0593bc514ed61415e5d3 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 27 Nov 2019 21:38:00 -0600 Subject: [PATCH 34/93] dedupe some code --- chain/actors/actor_miner.go | 39 +------------------------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index f358fafc2..c6ab993e3 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -485,11 +485,6 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM _ = seed //VerifyPoStRandomness() - convertToCandidates := func(wins []types.EPostTicket) []sectorbuilder.EPostCandidate { - panic("NYI") - } - winners := convertToCandidates(params.Proof.Winners) - proverID := vmctx.Message().To // TODO: normalize to ID address if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize, @@ -504,42 +499,10 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM } // Post submission is successful! - self.CurrentFaultSet = self.NextFaultSet - self.NextFaultSet = types.NewBitField() - - oldPower := self.Power - self.Power = types.BigMul(types.NewInt(pss.Count-uint64(len(faults))), - types.NewInt(mi.SectorSize)) - - delta := types.BigSub(self.Power, oldPower) - if self.SlashedAt != 0 { - self.SlashedAt = 0 - delta = self.Power - } - - prevSlashingDeadline := self.ElectionPeriodStart + build.SlashablePowerDelay - if !self.Active { - self.Active = true - prevSlashingDeadline = 0 - } - - enc, err := SerializeParams(&UpdateStorageParams{ - Delta: delta, - NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay, - PreviousProvingPeriodEnd: prevSlashingDeadline, - }) - if err != nil { + if err := onSuccessfulPoSt(self, vmctx); err != nil { return nil, err } - _, err = vmctx.Send(StoragePowerAddress, SPAMethods.UpdateStorage, types.NewInt(0), enc) - if err != nil { - return nil, err - } - - self.ProvingSet = self.Sectors - self.ElectionPeriodStart = vmctx.BlockHeight() - c, err := vmctx.Storage().Put(self) if err != nil { return nil, err From b75767e67841cf1fd2df2bc4f229d4d82bb86eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 11:55:34 +0100 Subject: [PATCH 35/93] seed: get default sector size from build.SectorSizes --- chain/gen/utils.go | 2 +- cmd/lotus-seed/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 773ef83ab..aaf31c09a 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -246,7 +246,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid params := mustEnc(&actors.CreateStorageMinerParams{ Owner: owner, Worker: worker, - SectorSize: 1024, // TODO: needs to come from preseals info + SectorSize: build.SectorSizes[0], // TODO: needs to come from preseals info PeerID: pid, }) diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index f17e11bf3..603a346b4 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -53,7 +53,7 @@ var preSealCmd = &cli.Command{ }, &cli.Uint64Flag{ Name: "sector-size", - Value: 1024, + Value: build.SectorSizes[0], Usage: "specify size of sectors to pre-seal", }, &cli.StringFlag{ From aefd432422e85c43cc182b4bc9a399d549b78629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 13:46:56 +0100 Subject: [PATCH 36/93] actors: Fallback post progress --- build/params_shared.go | 41 ++++++++++++++----------- chain/actors/actor_miner.go | 31 ++++++++++--------- chain/gen/gen.go | 2 +- chain/sync.go | 6 ++-- chain/types/blockheader.go | 6 ++-- chain/types/cbor_gen.go | 14 ++++----- chain/vm/vm_test.go | 2 +- cmd/lotus-bench/main.go | 2 +- lib/sectorbuilder/sectorbuilder.go | 38 +++++++++++++++++------ lib/sectorbuilder/sectorbuilder_test.go | 2 +- 10 files changed, 84 insertions(+), 60 deletions(-) diff --git a/build/params_shared.go b/build/params_shared.go index 44b66248d..c101d8db9 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -31,7 +31,7 @@ func SupportedSectorSize(ssize uint64) bool { // ///// // Payments -// Blocks +// Epochs const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours // ///// @@ -40,13 +40,13 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours // Seconds const AllowableClockDrift = BlockDelay * 2 -// Blocks +// Epochs const ForkLengthThreshold = Finality // Blocks (e) const BlocksPerEpoch = 5 -// Blocks +// Epochs const Finality = 500 // constants for Weight calculation @@ -57,40 +57,45 @@ const WRatioDen = 2 // ///// // Proofs -// PoStChallangeTime sets the window in which post computation should happen -// Blocks -const PoStChallangeTime = ProvingPeriodDuration - 6 - // PoStRandomnessLookback is additional randomness lookback for PoSt computation // To compute randomness epoch in a given proving period: // RandH = PPE - PoStChallangeTime - PoStRandomnessLookback // -// Blocks +// Epochs const PoStRandomnessLookback = 1 -// Blocks +// Epochs const SealRandomnessLookback = Finality -// Blocks +// Epochs const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000 // 1 / n const SectorChallengeRatioDiv = 25 +const MaxFallbackPostChallengeCount = 10 + +// FallbackPoStBegin is the number of epochs the miner needs to wait after +// ElectionPeriodStart before starting fallback post computation +// +// Epochs +const FallbackPoStBegin = 1000 + +// SlashablePowerDelay is the number of epochs +// Epochs +const SlashablePowerDelay = 2000 + // ///// // Mining -// Blocks +// Epochs const EcRandomnessLookback = 300 -const FallbackPoStBegin = 1000 -const SlashablePowerDelay = 2000 - const PowerCollateralProportion = 5 const PerCapitaCollateralProportion = 1 const CollateralPrecision = 1000 -// Blocks +// Epochs const InteractivePoRepDelay = 10 // ///// @@ -106,8 +111,8 @@ var InitialReward *big.Int const FilecoinPrecision = 1_000_000_000_000_000_000 // six years -// Blocks -const HalvingPeriodBlocks = 6 * 365 * 24 * 60 * 2 +// Epochs +const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2 // TODO: Move other important consts here @@ -125,6 +130,6 @@ func init() { // Sync const BadBlockCacheSize = 1 << 15 -// assuming 4000 blocks per round, this lets us not lose any messages across a +// assuming 4000 messages per round, this lets us not lose any messages across a // 10 block reorg. const BlsSignatureCacheSize = 40000 diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index c6ab993e3..b1fe46fb7 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -366,7 +366,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC if pss.Count == 0 { self.ProvingSet = self.Sectors // TODO: probably want to wait until the miner is above a certain - // threshold before starting this + // threshold before starting this self.ElectionPeriodStart = vmctx.BlockHeight() } @@ -390,15 +390,8 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC } type SubmitPoStParams struct { - Proof []byte -} - -func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) { - offset := setPeriodEnd % build.ProvingPeriodDuration - period := ((height - offset - 1) / build.ProvingPeriodDuration) + 1 - end := (period * build.ProvingPeriodDuration) + offset - - return end, period + Proof []byte + Candidates []types.EPostTicket } func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) { @@ -482,13 +475,21 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM faults := self.CurrentFaultSet.All() _ = faults - _ = seed - //VerifyPoStRandomness() - proverID := vmctx.Message().To // TODO: normalize to ID address - if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize, - sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil { + var candidates []sectorbuilder.EPostCandidate + for _, t := range params.Candidates { + var partial [32]byte + copy(partial[:], t.Partial) + candidates = append(candidates, sectorbuilder.EPostCandidate{ + PartialTicket: partial, + SectorID: t.SectorID, + SectorChallengeIndex: t.ChallengeIndex, + }) + } + + if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize, + sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID); !ok || lerr != nil { if lerr != nil { // TODO: study PoST errors return nil, aerrors.Absorb(lerr, 4, "PoST error") diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 5121bdc7b..9189f76c6 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -506,7 +506,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add PostRand: vrfout, } for _, win := range winners { - ept.Winners = append(ept.Winners, types.EPostTicket{ + ept.Candidates = append(ept.Candidates, types.EPostTicket{ Partial: win.PartialTicket[:], SectorID: win.SectorID, ChallengeIndex: win.SectorChallengeIndex, diff --git a/chain/sync.go b/chain/sync.go index 4b299f504..abedd2ff0 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -555,7 +555,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err return xerrors.Errorf("failed to get sector size for block miner: %w", err) } - for _, t := range h.EPostProof.Winners { + for _, t := range h.EPostProof.Candidates { if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) { return xerrors.Errorf("miner created a block but was not a winner") } @@ -667,7 +667,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc } var winners []sectorbuilder.EPostCandidate - for _, t := range h.EPostProof.Winners { + for _, t := range h.EPostProof.Candidates { var partial [32]byte copy(partial[:], t.Partial) winners = append(winners, sectorbuilder.EPostCandidate{ @@ -689,7 +689,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc return xerrors.Errorf("[TESTING] election post was invalid") } hvrf := sha256.Sum256(h.EPostProof.PostRand) - ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner) + ok, err := sectorbuilder.VerifyElectionPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner) if err != nil { return xerrors.Errorf("failed to verify election post: %w", err) } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 9cac4fd42..79585f1d2 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -27,9 +27,9 @@ type EPostTicket struct { } type EPostProof struct { - Proof []byte - PostRand []byte - Winners []EPostTicket + Proof []byte + PostRand []byte + Candidates []EPostTicket } type BlockHeader struct { diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index aa821245c..d2b60f268 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -349,11 +349,11 @@ func (t *EPostProof) MarshalCBOR(w io.Writer) error { return err } - // t.t.Winners ([]types.EPostTicket) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Winners)))); err != nil { + // t.t.Candidates ([]types.EPostTicket) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil { return err } - for _, v := range t.Winners { + for _, v := range t.Candidates { if err := v.MarshalCBOR(w); err != nil { return err } @@ -410,21 +410,21 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error { if _, err := io.ReadFull(br, t.PostRand); err != nil { return err } - // t.t.Winners ([]types.EPostTicket) (slice) + // t.t.Candidates ([]types.EPostTicket) (slice) maj, extra, err = cbg.CborReadHeader(br) if err != nil { return err } if extra > 8192 { - return fmt.Errorf("t.Winners: array too large (%d)", extra) + return fmt.Errorf("t.Candidates: array too large (%d)", extra) } if maj != cbg.MajArray { return fmt.Errorf("expected cbor array") } if extra > 0 { - t.Winners = make([]EPostTicket, extra) + t.Candidates = make([]EPostTicket, extra) } for i := 0; i < int(extra); i++ { @@ -433,7 +433,7 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error { return err } - t.Winners[i] = v + t.Candidates[i] = v } return nil diff --git a/chain/vm/vm_test.go b/chain/vm/vm_test.go index 7e4dd3e12..862bb4acf 100644 --- a/chain/vm/vm_test.go +++ b/chain/vm/vm_test.go @@ -12,7 +12,7 @@ import ( func TestBlockReward(t *testing.T) { coffer := types.FromFil(build.MiningRewardTotal).Int sum := new(big.Int) - N := build.HalvingPeriodBlocks + N := build.HalvingPeriodEpochs for i := 0; i < N; i++ { a := MiningReward(types.BigInt{coffer}) sum = sum.Add(sum, a.Int) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index 03aa60658..cbdaa3048 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -192,7 +192,7 @@ func main() { epost := time.Now() - ok, err := sectorbuilder.VerifyPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr) + ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr) if err != nil { return err } diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 53f2a672c..156bf4389 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -299,7 +299,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn return nil, err } - challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) + challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) @@ -334,10 +334,7 @@ func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, return nil, err } - challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) - if challengeCount > 10 { - challengeCount = 10 - } + challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) @@ -369,16 +366,29 @@ func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedP return sectorbuilder.NewSortedPublicSectorInfo(sectors...) } -func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) { +func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) { + challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values()))) + return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID) +} + +func VerifyFallbackPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) { + challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values()))) + return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID) +} + +func verifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeCount uint64, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) { + if challengeCount != uint64(len(candidates)) { + log.Warnf("verifyPost with wrong candidate count: expected %d, got %d", challengeCount, len(candidates)) + return false, nil // user input, dont't error + } + var challengeSeeda [CommLen]byte copy(challengeSeeda[:], challengeSeed) - challengeCount := challengeCount(uint64(len(sectorInfo.Values()))) - _, span := trace.StartSpan(ctx, "VerifyPoSt") defer span.End() prover := addressToProverID(proverID) - return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, winners, prover) + return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, candidates, prover) } func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) { @@ -399,7 +409,15 @@ func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]by return sectorbuilder.GenerateDataCommitment(ssize, pieces) } -func challengeCount(sectors uint64) uint64 { +func electionPostChallengeCount(sectors uint64) uint64 { // ceil(sectors / build.SectorChallengeRatioDiv) return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv } + +func fallbackPostChallengeCount(sectors uint64) uint64 { + challengeCount := electionPostChallengeCount(sectors) + if challengeCount > build.MaxFallbackPostChallengeCount { + return build.MaxFallbackPostChallengeCount + } + return challengeCount +} diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index b55b6c5bf..17398d482 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -102,7 +102,7 @@ func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) time.Time { t.Fatalf("%+v", err) } - ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner) + ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner) if err != nil { t.Fatalf("%+v", err) } From 920fd3ba9bdbdc1ad8057ad138d8583c27cc5311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 18:44:49 +0100 Subject: [PATCH 37/93] storageminer: New fallback post scheduler --- api/api_full.go | 2 +- api/struct.go | 2 +- build/params_shared.go | 4 +- chain/actors/actor_miner.go | 6 +- chain/actors/cbor_gen.go | 11 +- chain/stmgr/utils.go | 5 +- cmd/lotus-storage-miner/info.go | 2 +- gen/main.go | 2 +- lib/sectorbuilder/sectorbuilder.go | 9 +- node/impl/full/state.go | 4 +- storage/fpost_run.go | 138 +++++++++++++ storage/fpost_sched.go | 141 ++++++++++++++ storage/miner.go | 11 +- storage/post.go | 298 ----------------------------- storage/sector_states.go | 2 - 15 files changed, 308 insertions(+), 329 deletions(-) create mode 100644 storage/fpost_run.go create mode 100644 storage/fpost_sched.go delete mode 100644 storage/post.go diff --git a/api/api_full.go b/api/api_full.go index fc23cf43b..2e0b81d1a 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -99,7 +99,7 @@ type FullNode interface { StateMinerPower(context.Context, address.Address, *types.TipSet) (MinerPower, error) StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) StateMinerPeerID(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) - StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) + StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) StatePledgeCollateral(context.Context, *types.TipSet) (types.BigInt, error) StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error) diff --git a/api/struct.go b/api/struct.go index 1356bff2f..e8f27680f 100644 --- a/api/struct.go +++ b/api/struct.go @@ -362,7 +362,7 @@ func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address return c.Internal.StateMinerPeerID(ctx, m, ts) } -func (c *FullNodeStruct) StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { +func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { return c.Internal.StateMinerProvingPeriodEnd(ctx, actor, ts) } diff --git a/build/params_shared.go b/build/params_shared.go index c101d8db9..e482ca9eb 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -75,11 +75,11 @@ const SectorChallengeRatioDiv = 25 const MaxFallbackPostChallengeCount = 10 -// FallbackPoStBegin is the number of epochs the miner needs to wait after +// FallbackPoStDelay is the number of epochs the miner needs to wait after // ElectionPeriodStart before starting fallback post computation // // Epochs -const FallbackPoStBegin = 1000 +const FallbackPoStDelay = 1000 // SlashablePowerDelay is the number of epochs // Epochs diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index b1fe46fb7..1de5ae2f1 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -389,12 +389,12 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC return nil, err } -type SubmitPoStParams struct { +type SubmitFallbackPoStParams struct { Proof []byte Candidates []types.EPostTicket } -func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) { +func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitFallbackPoStParams) ([]byte, ActorError) { oldstate, self, err := loadState(vmctx) if err != nil { return nil, err @@ -427,7 +427,7 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM var seed [sectorbuilder.CommLen]byte { - randHeight := self.ElectionPeriodStart + build.FallbackPoStBegin + randHeight := self.ElectionPeriodStart + build.FallbackPoStDelay if vmctx.BlockHeight() <= randHeight { // TODO: spec, retcode return nil, aerrors.Newf(1, "submit fallback PoSt called too early (%d < %d)", vmctx.BlockHeight(), randHeight) diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 8a8688208..1666adeb2 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -813,7 +813,7 @@ func (t *MinerInfo) UnmarshalCBOR(r io.Reader) error { return nil } -func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error { +func (t *SubmitFallbackPoStParams) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err @@ -823,13 +823,10 @@ func (t *SubmitPoStParams) MarshalCBOR(w io.Writer) error { } // t.t.Proof (types.EPostProof) (struct) - if err := t.Proof.MarshalCBOR(w); err != nil { - return err - } return nil } -func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error { +func (t *SubmitFallbackPoStParams) UnmarshalCBOR(r io.Reader) error { br := cbg.GetPeeker(r) maj, extra, err := cbg.CborReadHeader(br) @@ -848,10 +845,6 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error { { - if err := t.Proof.UnmarshalCBOR(br); err != nil { - return err - } - } return nil } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 1a1a46ad0..a8c5378c1 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -149,15 +149,14 @@ func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, mad return address.NewFromBytes(recp.Return) } -func GetMinerProvingPeriodEnd(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { +func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) { var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { return 0, xerrors.Errorf("failed to load miner actor state: %w", err) } - panic("idk what to do") - //return mas.ProvingPeriodEnd, nil + return mas.ElectionPeriodStart, nil } func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) { diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index b1df59cb3..900a7c611 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -60,7 +60,7 @@ var infoCmd = &cli.Command{ } fmt.Printf("Worker use: %d / %d (+%d)\n", wstat.Total-wstat.Reserved-wstat.Free, wstat.Total, wstat.Reserved) - ppe, err := api.StateMinerProvingPeriodEnd(ctx, maddr, nil) + ppe, err := api.StateMinerElectionPeriodStart(ctx, maddr, nil) if err != nil { return err } diff --git a/gen/main.go b/gen/main.go index 48668d6da..4aad7622c 100644 --- a/gen/main.go +++ b/gen/main.go @@ -93,7 +93,7 @@ func main() { actors.SectorPreCommitInfo{}, actors.PreCommittedSector{}, actors.MinerInfo{}, - actors.SubmitPoStParams{}, + actors.SubmitFallbackPoStParams{}, actors.PaymentVerifyParams{}, actors.UpdatePeerIDParams{}, actors.MultiSigActorState{}, diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 156bf4389..f953dea14 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -328,10 +328,10 @@ func (sb *SectorBuilder) pubSectorToPriv(sectorInfo SortedPublicSectorInfo) (Sor return NewSortedPrivateSectorInfo(out), nil } -func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { +func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]EPostCandidate, []byte, error) { privsectors, err := sb.pubSectorToPriv(sectorInfo) if err != nil { - return nil, err + return nil, nil, err } challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values()))) @@ -339,10 +339,11 @@ func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo, proverID := addressToProverID(sb.Miner) candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) if err != nil { - return nil, err + return nil, nil, err } - return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsectors, challengeSeed, candidates) + proof, err := sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsectors, challengeSeed, candidates) + return candidates, proof, err } var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector diff --git a/node/impl/full/state.go b/node/impl/full/state.go index a51276d6c..04037c079 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -76,8 +76,8 @@ func (a *StateAPI) StateMinerPeerID(ctx context.Context, m address.Address, ts * return stmgr.GetMinerPeerID(ctx, a.StateManager, ts, m) } -func (a *StateAPI) StateMinerProvingPeriodEnd(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { - return stmgr.GetMinerProvingPeriodEnd(ctx, a.StateManager, ts, actor) +func (a *StateAPI) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { + return stmgr.GetMinerElectionPeriodStart(ctx, a.StateManager, ts, actor) } func (a *StateAPI) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { diff --git a/storage/fpost_run.go b/storage/fpost_run.go new file mode 100644 index 000000000..ba0990ef3 --- /dev/null +++ b/storage/fpost_run.go @@ -0,0 +1,138 @@ +package storage + +import ( + "context" + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sectorbuilder" + "go.opencensus.io/trace" + "golang.org/x/xerrors" + "time" +) + +func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSet) { + ctx, abort := context.WithCancel(ctx) + + s.abort = abort + s.activeEPS = eps + + go func() { + defer abort() + + ctx, span := trace.StartSpan(ctx, "fpostScheduler.doPost") + defer span.End() + + proof, err := s.runPost(ctx, eps, ts) + if err != nil { + log.Errorf("runPost failed: %+v", err) + return + } + + if err := s.submitPost(ctx, proof); err != nil { + log.Errorf("submitPost failed: %+v", err) + return + } + }() +} + +func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipSet) (*actors.SubmitFallbackPoStParams, error) { + ctx, span := trace.StartSpan(ctx, "storage.runPost") + defer span.End() + + challengeRound := int64(eps + build.FallbackPoStDelay) + + rand, err := s.api.ChainGetRandomness(ctx, ts.Key(), challengeRound) + if err != nil { + return nil, xerrors.Errorf("failed to get chain randomness for fpost (ts=%d; eps=%d): %w", ts.Height(), eps, err) + } + + ssi, err := s.sortedSectorInfo(ctx, ts) + if err != nil { + return nil, xerrors.Errorf("getting sorted sector info: %w", err) + } + + log.Infow("running fPoSt", "chain-random", rand, "eps", eps, "height", ts.Height()) + + tsStart := time.Now() + var faults []uint64 // TODO + + var seed [32]byte + copy(seed[:], rand) + + scandidates, proof, err := s.sb.GenerateFallbackPoSt(ssi, seed, faults) + if err != nil { + return nil, xerrors.Errorf("running post failed: %w", err) + } + + elapsed := time.Since(tsStart) + log.Infow("submitting PoSt", "pLen", len(proof), "elapsed", elapsed) + + candidates := make([]types.EPostTicket, len(scandidates)) + for i, sc := range scandidates { + candidates[i] = types.EPostTicket{ + Partial: sc.PartialTicket[:], + SectorID: sc.SectorID, + ChallengeIndex: sc.SectorChallengeIndex, + } + } + + return &actors.SubmitFallbackPoStParams{ + Proof: proof, + Candidates: candidates, + }, nil +} + +func (s *fpostScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet) (sectorbuilder.SortedPublicSectorInfo, error) { + sset, err := s.api.StateMinerProvingSet(ctx, s.actor, ts) + if err != nil { + return sectorbuilder.SortedPublicSectorInfo{}, xerrors.Errorf("failed to get proving set for miner (tsH: %d): %w", ts.Height(), err) + } + if len(sset) == 0 { + log.Warn("empty proving set! (ts.H: %d)", ts.Height()) + } + + sbsi := make([]ffi.PublicSectorInfo, len(sset)) + for k, sector := range sset { + var commR [sectorbuilder.CommLen]byte + copy(commR[:], sector.CommR) + + sbsi[k] = ffi.PublicSectorInfo{ + SectorID: sector.SectorID, + CommR: commR, + } + } + + return sectorbuilder.NewSortedPublicSectorInfo(sbsi), nil +} + +func (s *fpostScheduler) submitPost(ctx context.Context, proof *actors.SubmitFallbackPoStParams) error { + ctx, span := trace.StartSpan(ctx, "storage.commitPost") + defer span.End() + + enc, aerr := actors.SerializeParams(proof) + if aerr != nil { + return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) + } + + msg := &types.Message{ + To: s.actor, + From: s.worker, + Method: actors.MAMethods.SubmitFallbackPoSt, + Params: enc, + Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late + GasLimit: types.NewInt(10000000), // i dont know help + GasPrice: types.NewInt(1), + } + + // TODO: consider maybe caring about the output + sm, err := s.api.MpoolPushMessage(ctx, msg) + if err != nil { + return xerrors.Errorf("pushing message to mpool: %w", err) + } + + log.Infof("Submitted fallback post: %s", sm.Cid()) + + return nil +} diff --git a/storage/fpost_sched.go b/storage/fpost_sched.go new file mode 100644 index 000000000..565a3604f --- /dev/null +++ b/storage/fpost_sched.go @@ -0,0 +1,141 @@ +package storage + +import ( + "context" + + "go.opencensus.io/trace" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sectorbuilder" +) + +const Inactive = 0 + +const StartConfidence = 4 // TODO: config + +type fpostScheduler struct { + api storageMinerApi + sb *sectorbuilder.SectorBuilder + + actor address.Address + worker address.Address + + cur *types.TipSet + + // if a post is in progress, this indicates for which ElectionPeriodStart + activeEPS uint64 + abort context.CancelFunc +} + +func (s *fpostScheduler) run(ctx context.Context) { + notifs, err := s.api.ChainNotify(ctx) + if err != nil { + return + } + + current := <-notifs + if len(current) != 1 { + panic("expected first notif to have len = 1") + } + if current[0].Type == store.HCCurrent { + panic("expected first notif to tell current ts") + } + + if err := s.update(ctx, current[0].Val); err != nil { + panic(err) + } + + // not fine to panic after this point + for { + select { + case changes := <-notifs: + ctx, span := trace.StartSpan(ctx, "fpostScheduler.headChange") + + var lowest, highest *types.TipSet = s.cur, nil + + for _, change := range changes { + switch change.Type { + case store.HCRevert: + lowest = change.Val + case store.HCApply: + highest = change.Val + } + } + + if err := s.revert(ctx, lowest); err != nil { + log.Error("handling head reverts in fallbackPost sched: %+v", err) + } + if err := s.update(ctx, highest); err != nil { + log.Error("handling head updates in fallbackPost sched: %+v", err) + } + + span.End() + } + } +} + +func (s *fpostScheduler) revert(ctx context.Context, newLowest *types.TipSet) error { + if s.cur == newLowest { + return nil + } + s.cur = newLowest + + newEPS, _, err := s.shouldFallbackPost(ctx, newLowest) + if err != nil { + return err + } + + if newEPS != s.activeEPS { + s.abortActivePoSt() + } + + return nil +} + +func (s *fpostScheduler) update(ctx context.Context, new *types.TipSet) error { + newEPS, start, err := s.shouldFallbackPost(ctx, new) + if err != nil { + return err + } + + if newEPS != s.activeEPS { + s.abortActivePoSt() + } + + if newEPS != Inactive && start { + s.doPost(ctx, newEPS, new) + } + + return nil +} + +func (s *fpostScheduler) abortActivePoSt() { + if s.activeEPS == Inactive { + return // noop + } + + if s.abort != nil { + s.abort() + } + + log.Warnf("Aborting Fallback PoSt (EPS: %d)", s.activeEPS) + + s.activeEPS = 0 + s.abort = nil +} + +func (s *fpostScheduler) shouldFallbackPost(ctx context.Context, ts *types.TipSet) (uint64, bool, error) { + eps, err := s.api.StateMinerElectionPeriodStart(ctx, s.actor, ts) + if err != nil { + return 0, false, xerrors.Errorf("getting ElectionPeriodStart: %w", err) + } + + if ts.Height() >= eps+build.FallbackPoStDelay { + return eps, ts.Height() >= eps+build.FallbackPoStDelay+StartConfidence, nil + } + return 0, false, nil +} diff --git a/storage/miner.go b/storage/miner.go index 206bbbe4d..15f65e60c 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -53,7 +53,7 @@ type storageMinerApi interface { // Call a read only method on actors (no interaction with the chain required) StateCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) StateMinerWorker(context.Context, address.Address, *types.TipSet) (address.Address, error) - StateMinerProvingPeriodEnd(context.Context, address.Address, *types.TipSet) (uint64, error) + StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) StateMinerSectors(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerProvingSet(context.Context, address.Address, *types.TipSet) ([]*api.ChainSectorInfo, error) StateMinerSectorSize(context.Context, address.Address, *types.TipSet) (uint64, error) @@ -99,7 +99,14 @@ func (m *Miner) Run(ctx context.Context) error { m.events = events.NewEvents(ctx, m.api) - go m.beginPosting(ctx) + fps := &fpostScheduler{ + api: m.api, + sb: m.sb, + actor: m.maddr, + worker: m.worker, + } + + go fps.run(ctx) go m.sectorStateLoop(ctx) return nil } diff --git a/storage/post.go b/storage/post.go deleted file mode 100644 index 541d23b25..000000000 --- a/storage/post.go +++ /dev/null @@ -1,298 +0,0 @@ -package storage - -import ( - "context" - "time" - - ffi "github.com/filecoin-project/filecoin-ffi" - - "go.opencensus.io/trace" - "golang.org/x/xerrors" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/build" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/lib/sectorbuilder" -) - -const postMsgTimeout = 20 - -func (m *Miner) beginPosting(ctx context.Context) { - ts, err := m.api.ChainHead(context.TODO()) - if err != nil { - log.Error(err) - return - } - - sppe, err := m.api.StateMinerProvingPeriodEnd(ctx, m.maddr, ts) - if err != nil { - log.Errorf("failed to get proving period end for miner (ts h: %d): %s", ts.Height(), err) - return - } - - if sppe == 0 { - log.Warn("Not proving yet") - return - } - - m.postLk.Lock() - if m.schedPost > 0 { - log.Warnf("PoSts already running %d", m.schedPost) - m.postLk.Unlock() - return - } - - // height needs to be +1, because otherwise we'd be trying to schedule PoSt - // at current block height - ppe, _ := actors.ProvingPeriodEnd(sppe, ts.Height()+1) - m.schedPost = ppe - - m.postLk.Unlock() - - if build.PoStChallangeTime > ppe { - ppe = build.PoStChallangeTime - } - - log.Infof("Scheduling post at height %d (begin ts: %d, statePPE: %d)", ppe-build.PoStChallangeTime, ts.Height(), sppe) - err = m.events.ChainAt(m.computePost(m.schedPost), func(ctx context.Context, ts *types.TipSet) error { // Revert - // TODO: Cancel post - log.Errorf("TODO: Cancel PoSt, re-run") - return nil - }, PoStConfidence, ppe-build.PoStChallangeTime) - if err != nil { - // TODO: This is BAD, figure something out - log.Errorf("scheduling PoSt failed: %s", err) - return - } -} - -func (m *Miner) scheduleNextPost(ppe uint64) { - ts, err := m.api.ChainHead(context.TODO()) - if err != nil { - log.Error(err) - // TODO: retry - return - } - - headPPE, provingPeriod := actors.ProvingPeriodEnd(ppe, ts.Height()) - if headPPE > ppe { - log.Warnw("PoSt computation running behind chain", "headPPE", headPPE, "ppe", ppe) - ppe = headPPE - } - - m.postLk.Lock() - if m.schedPost >= ppe { - // this probably can't happen - log.Errorw("PoSt already scheduled", "schedPost", m.schedPost, "ppe", ppe) - m.postLk.Unlock() - return - } - - m.schedPost = ppe - m.postLk.Unlock() - - log.Infow("scheduling PoSt", "post-height", ppe-build.PoStChallangeTime, - "height", ts.Height(), "ppe", ppe, "proving-period", provingPeriod) - err = m.events.ChainAt(m.computePost(ppe), func(ctx context.Context, ts *types.TipSet) error { // Revert - // TODO: Cancel post - log.Errorf("TODO: Cancel PoSt, re-run") - return nil - }, PoStConfidence, ppe-build.PoStChallangeTime) - if err != nil { - // TODO: This is BAD, figure something out - log.Errorf("scheduling PoSt failed: %+v", err) - return - } -} - -type post struct { - m *Miner - - ppe uint64 - ts *types.TipSet - - // prep - sset []*api.ChainSectorInfo - r []byte - - // run - proof []byte - - // commit - smsg *types.SignedMessage -} - -func (p *post) doPost(ctx context.Context) error { - ctx, span := trace.StartSpan(ctx, "storage.computePost") - defer span.End() - - if err := p.preparePost(ctx); err != nil { - return xerrors.Errorf("prepare: %w", err) - } - - if err := p.runPost(ctx); err != nil { - return xerrors.Errorf("run: %w", err) - } - - if err := p.commitPost(ctx); err != nil { - return xerrors.Errorf("commit: %w", err) - } - - if err := p.waitCommit(ctx); err != nil { - return xerrors.Errorf("wait: %w", err) - } - - return nil -} - -func (p *post) preparePost(ctx context.Context) error { - ctx, span := trace.StartSpan(ctx, "storage.preparePost") - defer span.End() - log.Info("preparePost") - - sset, err := p.m.api.StateMinerProvingSet(ctx, p.m.maddr, p.ts) - if err != nil { - return xerrors.Errorf("failed to get proving set for miner (tsH: %d): %w", p.ts.Height(), err) - } - if len(sset) == 0 { - log.Warn("empty proving set! (ts.H: %d)", p.ts.Height()) - } - - p.sset = sset - - challengeRound := int64(p.ppe) - int64(build.PoStChallangeTime+build.PoStRandomnessLookback) - r, err := p.m.api.ChainGetRandomness(ctx, p.ts.Key(), challengeRound) - if err != nil { - return xerrors.Errorf("failed to get chain randomness for post (ts=%d; ppe=%d): %w", p.ts.Height(), p.ppe, err) - } - p.r = r - - return nil -} - -func (p *post) sortedSectorInfo() sectorbuilder.SortedPublicSectorInfo { - panic("NYI") - sbsi := make([]ffi.PublicSectorInfo, len(p.sset)) - for k, sector := range p.sset { - var commR [sectorbuilder.CommLen]byte - copy(commR[:], sector.CommR) - - sbsi[k] = ffi.PublicSectorInfo{ - SectorID: sector.SectorID, - CommR: commR, - } - } - - return sectorbuilder.NewSortedPublicSectorInfo(sbsi) -} - -func (p *post) runPost(ctx context.Context) error { - ctx, span := trace.StartSpan(ctx, "storage.runPost") - defer span.End() - - log.Infow("running PoSt", "delayed-by", - int64(p.ts.Height())-(int64(p.ppe)-int64(build.PoStChallangeTime)), - "chain-random", p.r, "ppe", p.ppe, "height", p.ts.Height(), "sectors", len(p.sset)) - - tsStart := time.Now() - var faults []uint64 // TODO - - var seed [32]byte - copy(seed[:], p.r) - - proof, err := p.m.sb.GenerateFallbackPoSt(p.sortedSectorInfo(), seed, faults) - if err != nil { - return xerrors.Errorf("running post failed: %w", err) - } - elapsed := time.Since(tsStart) - - p.proof = proof - log.Infow("submitting PoSt", "pLen", len(proof), "elapsed", elapsed) - - return nil -} - -func (p *post) commitPost(ctx context.Context) (err error) { - ctx, span := trace.StartSpan(ctx, "storage.commitPost") - defer span.End() - - params := &actors.SubmitPoStParams{ - Proof: p.proof, - } - - enc, aerr := actors.SerializeParams(params) - if aerr != nil { - return xerrors.Errorf("could not serialize submit post parameters: %w", aerr) - } - - msg := &types.Message{ - To: p.m.maddr, - From: p.m.worker, - Method: actors.MAMethods.SubmitPoSt, - Params: enc, - Value: types.NewInt(1000), // currently hard-coded late fee in actor, returned if not late - GasLimit: types.NewInt(1000000), // i dont know help - GasPrice: types.NewInt(1), - } - - log.Info("mpush") - - p.smsg, err = p.m.api.MpoolPushMessage(ctx, msg) - if err != nil { - return xerrors.Errorf("pushing message to mpool: %w", err) - } - - return nil -} - -func (p *post) waitCommit(ctx context.Context) error { - ctx, span := trace.StartSpan(ctx, "storage.waitPost") - defer span.End() - - log.Infof("Waiting for post %s to appear on chain", p.smsg.Cid()) - - err := p.m.events.CalledMsg(ctx, func(msg *types.Message, rec *types.MessageReceipt, ts *types.TipSet, curH uint64) (more bool, err error) { - if rec.ExitCode != 0 { - log.Warnf("SubmitPoSt EXIT: %d", rec.ExitCode) - } - - log.Infof("Post made it on chain! (height=%d)", ts.Height()) - - return false, nil - }, func(ctx context.Context, ts *types.TipSet) error { - log.Warn("post message reverted") - return nil - }, 3, postMsgTimeout, p.smsg) - if err != nil { - return xerrors.Errorf("waiting for post to appear on chain: %w", err) - } - - return nil -} - -func (m *Miner) computePost(ppe uint64) func(ctx context.Context, ts *types.TipSet, curH uint64) error { - called := 0 - return func(ctx context.Context, ts *types.TipSet, curH uint64) error { - called++ - if called > 1 { - log.Errorw("BUG: computePost callback called again", "ppe", ppe, - "height", ts.Height(), "curH", curH, "called", called-1) - return nil - } - - err := (&post{ - m: m, - ppe: ppe, - ts: ts, - }).doPost(ctx) - - m.scheduleNextPost(ppe + build.ProvingPeriodDuration) - - if err != nil { - return xerrors.Errorf("doPost: %w", err) - } - - return nil - } -} diff --git a/storage/sector_states.go b/storage/sector_states.go index ed5666285..455fa15b8 100644 --- a/storage/sector_states.go +++ b/storage/sector_states.go @@ -220,8 +220,6 @@ func (m *Miner) committing(ctx context.Context, sector SectorInfo) (func(*Sector return nil, xerrors.New("UNHANDLED: submitting sector proof failed") } - m.beginPosting(ctx) - return func(info *SectorInfo) { mcid := smsg.Cid() info.CommitMessage = &mcid From 367512d0670a3ff44bb9fa367f101986ac8426d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 19:08:10 +0100 Subject: [PATCH 38/93] Some fpost fixes --- api/struct.go | 46 +++++++++++++++++++++--------------------- chain/vm/invoker.go | 2 +- storage/fpost_run.go | 8 +++++--- storage/fpost_sched.go | 2 +- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/api/struct.go b/api/struct.go index e8f27680f..f47836f6a 100644 --- a/api/struct.go +++ b/api/struct.go @@ -84,28 +84,28 @@ type FullNodeStruct struct { ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"` ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"` - StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"` - StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"` - StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"` - StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"` - StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"` - StateMinerProvingPeriodEnd func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"` - StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"` - StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` - StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) `perm:"read"` - StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"` - StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"` - StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` - StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"` - StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` - StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` - StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"` - StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"` - StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"` - StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"` - StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (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.TipSet) (*types.MessageReceipt, error) `perm:"read"` + StateMinerSectors func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"` + StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*ChainSectorInfo, error) `perm:"read"` + StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"` + StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"` + StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"` + StateMinerElectionPeriodStart func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"` + StateMinerSectorSize func(context.Context, address.Address, *types.TipSet) (uint64, error) `perm:"read"` + StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` + StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, error) `perm:"read"` + StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"` + StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"` + StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"` + StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"` + StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` + StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"` + StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error) `perm:"read"` + StateMarketParticipants func(context.Context, *types.TipSet) (map[string]actors.StorageParticipantBalance, error) `perm:"read"` + StateMarketDeals func(context.Context, *types.TipSet) (map[string]actors.OnChainDeal, error) `perm:"read"` + StateMarketStorageDeal func(context.Context, uint64, *types.TipSet) (*actors.OnChainDeal, error) `perm:"read"` + StateLookupID func(ctx context.Context, addr address.Address, ts *types.TipSet) (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.TipSet) (*types.MessageReceipt, error) `perm:"read"` MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"` @@ -363,7 +363,7 @@ func (c *FullNodeStruct) StateMinerPeerID(ctx context.Context, m address.Address } func (c *FullNodeStruct) StateMinerElectionPeriodStart(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { - return c.Internal.StateMinerProvingPeriodEnd(ctx, actor, ts) + return c.Internal.StateMinerElectionPeriodStart(ctx, actor, ts) } func (c *FullNodeStruct) StateMinerSectorSize(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) { diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 3fa02d4c1..c53b75c24 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -159,7 +159,7 @@ func DumpActorState(code cid.Cid, b []byte) (interface{}, error) { typ, ok := i.builtInState[code] if !ok { - return nil, xerrors.New("state type for actor not found") + return nil, xerrors.Errorf("state type for actor %s not found", code) } rv := reflect.New(typ) diff --git a/storage/fpost_run.go b/storage/fpost_run.go index ba0990ef3..a2cf88810 100644 --- a/storage/fpost_run.go +++ b/storage/fpost_run.go @@ -2,14 +2,16 @@ package storage import ( "context" + "time" + ffi "github.com/filecoin-project/filecoin-ffi" + "go.opencensus.io/trace" + "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/lib/sectorbuilder" - "go.opencensus.io/trace" - "golang.org/x/xerrors" - "time" ) func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSet) { diff --git a/storage/fpost_sched.go b/storage/fpost_sched.go index 565a3604f..9480dc3c2 100644 --- a/storage/fpost_sched.go +++ b/storage/fpost_sched.go @@ -41,7 +41,7 @@ func (s *fpostScheduler) run(ctx context.Context) { if len(current) != 1 { panic("expected first notif to have len = 1") } - if current[0].Type == store.HCCurrent { + if current[0].Type != store.HCCurrent { panic("expected first notif to tell current ts") } From 466f1d8cb94257550dc50837432b5ad652148376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 19:52:28 +0100 Subject: [PATCH 39/93] Use ProvingSet for GetSectorsForElectionPost --- chain/stmgr/utils.go | 2 +- lib/sectorbuilder/sectorbuilder_test.go | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index a8c5378c1..0105ef0a5 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -180,7 +180,7 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, } func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedPublicSectorInfo, error) { - sectors, err := GetMinerSectorSet(ctx, sm, ts, maddr) + sectors, err := GetMinerProvingSet(ctx, sm, ts, maddr) if err != nil { return nil, xerrors.Errorf("failed to get sector set for miner: %w", err) } diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 17398d482..9ac332ae2 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -78,13 +78,18 @@ func (s *seal) commit(t *testing.T, sb *sectorbuilder.SectorBuilder, done func() done() } -func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) time.Time { +func post(t *testing.T, sb *sectorbuilder.SectorBuilder, seals ...seal) time.Time { cSeed := [32]byte{0, 9, 2, 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 7, 6, 45, 3, 2, 1, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 9} - ssi := sectorbuilder.NewSortedPublicSectorInfo([]ffi.PublicSectorInfo{{ - SectorID: s.sid, - CommR: s.pco.CommR, - }}) + ppi := make([]ffi.PublicSectorInfo, len(seals)) + for i, s := range seals { + ppi[i] = ffi.PublicSectorInfo{ + SectorID: s.sid, + CommR: s.pco.CommR, + } + } + + ssi := sectorbuilder.NewSortedPublicSectorInfo(ppi) candndates, err := sb.GenerateEPostCandidates(ssi, cSeed, []uint64{}) if err != nil { @@ -165,7 +170,7 @@ func TestSealAndVerify(t *testing.T) { commit := time.Now() - genCandidiates := s.post(t, sb) + genCandidiates := post(t, sb, s) epost := time.Now() @@ -175,7 +180,7 @@ func TestSealAndVerify(t *testing.T) { t.Fatalf("%+v", err) } - s.post(t, sb) + post(t, sb, s) fmt.Printf("PreCommit: %s\n", precommit.Sub(start).String()) fmt.Printf("Commit: %s\n", commit.Sub(precommit).String()) @@ -237,7 +242,7 @@ func TestSealPoStNoCommit(t *testing.T) { t.Fatalf("%+v", err) } - genCandidiates := s.post(t, sb) + genCandidiates := post(t, sb, s) epost := time.Now() @@ -302,6 +307,8 @@ func TestSealAndVerify2(t *testing.T) { go s1.commit(t, sb, wg.Done) go s2.commit(t, sb, wg.Done) wg.Wait() + + post(t, sb, s1, s2) } func TestAcquireID(t *testing.T) { From cb7d15e67e5cb231d178e3791bf0e8245ac9a6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 28 Nov 2019 23:50:58 +0100 Subject: [PATCH 40/93] genesis setup improvements --- chain/actors/actor_miner.go | 4 + chain/gen/gen.go | 9 +- chain/gen/utils.go | 144 +++++++++++++++++++------------- chain/wallet/wallet.go | 16 ++++ cmd/lotus-seed/seed/seed.go | 67 +++++++++++++-- genesis/types.go | 18 +++- node/modules/testing/genesis.go | 36 +++++--- 7 files changed, 210 insertions(+), 84 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 1de5ae2f1..1c574eb37 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -31,12 +31,16 @@ type StorageMinerActorState struct { PreCommittedSectors map[string]*PreCommittedSector // All sectors this miner has committed. + // + // AMT[sectorID]ffi.PublicSectorInfo Sectors cid.Cid // TODO: Spec says 'StagedCommittedSectors', which one is it? // Sectors this miner is currently mining. It is only updated // when a PoSt is submitted (not as each new sector commitment is added). + // + // AMT[sectorID]ffi.PublicSectorInfo ProvingSet cid.Cid // TODO: these: diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 9189f76c6..308439237 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -132,9 +132,8 @@ func NewGenerator() (*ChainGen, error) { } minercfg := &GenMinerCfg{ - Workers: []address.Address{worker1, worker2}, - Owners: []address.Address{worker1, worker2}, PeerIDs: []peer.ID{"peerID1", "peerID2"}, + // Call PreSeal(and give worker addrs to it somehow) } genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{ @@ -174,9 +173,9 @@ func NewGenerator() (*ChainGen, error) { genesis: genb.Genesis, w: w, - Miners: minercfg.MinerAddrs, - eppProvs: mgen, - mworkers: minercfg.Workers, + Miners: minercfg.MinerAddrs, + eppProvs: mgen, + //mworkers: minercfg.Workers, banker: banker, receivers: receievers, diff --git a/chain/gen/utils.go b/chain/gen/utils.go index aaf31c09a..82a9e907a 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -23,6 +23,14 @@ import ( "github.com/filecoin-project/lotus/genesis" ) +var validSsizes = map[uint64]struct{}{} + +func init() { + for _, size := range build.SectorSizes { + validSsizes[size] = struct{}{} + } +} + type GenesisBootstrap struct { Genesis *types.BlockHeader } @@ -99,15 +107,6 @@ func MakeInitialStateTree(bs bstore.Blockstore, actmap map[address.Address]types return nil, xerrors.Errorf("set storage market actor: %w", err) } - smact, err := SetupStorageMarketActor(bs) - if err != nil { - return nil, xerrors.Errorf("setup storage market actor: %w", err) - } - - if err := state.SetActor(actors.StorageMarketAddress, smact); err != nil { - return nil, xerrors.Errorf("set storage market actor: %w", err) - } - netAmt := types.FromFil(build.TotalFilecoin) for _, amt := range actmap { netAmt = types.BigSub(netAmt, amt) @@ -178,44 +177,60 @@ func SetupStoragePowerActor(bs bstore.Blockstore) (*types.Actor, error) { }, nil } -func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { +func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors.StorageDeal) (cid.Cid, error) { cst := hamt.CSTFromBstore(bs) nd := hamt.NewNode(cst) emptyHAMT, err := cst.Put(context.TODO(), nd) if err != nil { - return nil, err + return cid.Undef, err } blks := amt.WrapBlockstore(bs) - emptyAMT, err := amt.FromArray(blks, nil) + cdeals := make([]cbg.CBORMarshaler, len(deals)) + for i, deal := range deals { + cdeals[i] = &actors.OnChainDeal{ + Deal: deal, + ActivationEpoch: 1, + } + } + + dealAmt, err := amt.FromArray(blks, cdeals) if err != nil { - return nil, xerrors.Errorf("amt build failed: %w", err) + return cid.Undef, xerrors.Errorf("amt build failed: %w", err) } sms := &actors.StorageMarketState{ Balances: emptyHAMT, - Deals: emptyAMT, + Deals: dealAmt, NextDealID: 0, } stcid, err := cst.Put(context.TODO(), sms) if err != nil { - return nil, err + return cid.Undef, err } - return &types.Actor{ + act := &types.Actor{ Code: actors.StorageMarketCodeCid, Head: stcid, Nonce: 0, Balance: types.NewInt(0), - }, nil + } + + state, err := state.LoadStateTree(cst, sroot) + if err != nil { + return cid.Undef, xerrors.Errorf("making new state tree: %w", err) + } + + if err := state.SetActor(actors.StorageMarketAddress, act); err != nil { + return cid.Undef, xerrors.Errorf("set storage market actor: %w", err) + } + + return state.Flush() } type GenMinerCfg struct { - Owners []address.Address - Workers []address.Address - PreSeals map[string]genesis.GenesisMiner // The addresses of the created miner, this is set by the genesis setup @@ -232,94 +247,100 @@ func mustEnc(i cbg.CBORMarshaler) []byte { return enc } -func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) { +func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, []actors.StorageDeal, error) { vm, err := vm.NewVM(sroot, 0, nil, actors.NetworkAddress, cs.Blockstore()) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create NewVM: %w", err) + return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err) } - for i := 0; i < len(gmcfg.Workers); i++ { - owner := gmcfg.Owners[i] - worker := gmcfg.Workers[i] - pid := gmcfg.PeerIDs[i] + if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) { + return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals)) + } - params := mustEnc(&actors.CreateStorageMinerParams{ - Owner: owner, - Worker: worker, - SectorSize: build.SectorSizes[0], // TODO: needs to come from preseals info - PeerID: pid, - }) + var deals []actors.StorageDeal - // TODO: hardcoding 7000000 here is a little fragile, it changes any + for i, maddr := range gmcfg.MinerAddrs { + ps, psok := gmcfg.PreSeals[maddr.String()] + if !psok { + return cid.Undef, nil, xerrors.Errorf("no preseal for miner %s", maddr) + } + + minerParams := &actors.CreateStorageMinerParams{ + Owner: ps.Owner, + Worker: ps.Worker, + SectorSize: ps.SectorSize, + PeerID: gmcfg.PeerIDs[i], // TODO: grab from preseal too + } + + params := mustEnc(minerParams) + + // TODO: hardcoding 6500 here is a little fragile, it changes any // time anyone changes the initial account allocations - rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, owner, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params) + rval, err := doExecValue(ctx, vm, actors.StoragePowerAddress, ps.Worker, types.FromFil(6500), actors.SPAMethods.CreateStorageMiner, params) if err != nil { - return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) + return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err) } maddr, err := address.NewFromBytes(rval) if err != nil { - return cid.Undef, err + return cid.Undef, nil, err } gmcfg.MinerAddrs = append(gmcfg.MinerAddrs, maddr) - params = mustEnc(&actors.UpdateStorageParams{Delta: types.NewInt(5000)}) + power := types.BigMul(types.NewInt(minerParams.SectorSize), types.NewInt(uint64(len(ps.Sectors)))) + + params = mustEnc(&actors.UpdateStorageParams{Delta: power}) _, err = doExec(ctx, vm, actors.StoragePowerAddress, maddr, actors.SPAMethods.UpdateStorage, params) if err != nil { - return cid.Undef, xerrors.Errorf("failed to update total storage: %w", err) + return cid.Undef, nil, xerrors.Errorf("failed to update total storage: %w", err) } - // UGLY HACKY MODIFICATION OF MINER POWER - // we have to flush the vm here because it buffers stuff internally for perf reasons if _, err := vm.Flush(ctx); err != nil { - return cid.Undef, xerrors.Errorf("vm.Flush failed: %w", err) + return cid.Undef, nil, xerrors.Errorf("vm.Flush failed: %w", err) } st := vm.StateTree() mact, err := st.GetActor(maddr) if err != nil { - return cid.Undef, xerrors.Errorf("get miner actor failed: %w", err) + return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err) } cst := hamt.CSTFromBstore(cs.Blockstore()) var mstate actors.StorageMinerActorState if err := cst.Get(ctx, mact.Head, &mstate); err != nil { - return cid.Undef, xerrors.Errorf("getting miner actor state failed: %w", err) + return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err) } mstate.Power = types.NewInt(build.SectorSizes[0]) blks := amt.WrapBlockstore(cs.Blockstore()) - ps, ok := gmcfg.PreSeals[maddr.String()] - if ok { - for _, s := range ps.Sectors { - nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:]) - if err != nil { - return cid.Undef, xerrors.Errorf("failed to add fake sector to sector set: %w", err) - } - mstate.Sectors = nssroot - mstate.ProvingSet = nssroot + for _, s := range ps.Sectors { + nssroot, err := actors.AddToSectorSet(ctx, blks, mstate.Sectors, s.SectorID, s.CommR[:], s.CommD[:]) + if err != nil { + return cid.Undef, nil, xerrors.Errorf("failed to add fake sector to sector set: %w", err) } - } else { - log.Warning("No preseals for miner: ", maddr) + mstate.Sectors = nssroot + mstate.ProvingSet = nssroot + + deals = append(deals, s.Deal) } nstate, err := cst.Put(ctx, &mstate) if err != nil { - return cid.Undef, err + return cid.Undef, nil, err } mact.Head = nstate if err := st.SetActor(maddr, mact); err != nil { - return cid.Undef, err + return cid.Undef, nil, err } - // End of super haxx } - return vm.Flush(ctx) + c, err := vm.Flush(ctx) + return c, deals, err } func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) { @@ -368,11 +389,16 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B // temp chainstore cs := store.NewChainStore(bs, datastore.NewMapDatastore()) - stateroot, err = SetupStorageMiners(ctx, cs, stateroot, gmcfg) + stateroot, deals, err := SetupStorageMiners(ctx, cs, stateroot, gmcfg) if err != nil { return nil, xerrors.Errorf("setup storage miners failed: %w", err) } + stateroot, err = SetupStorageMarketActor(bs, stateroot, deals) + if err != nil { + return nil, xerrors.Errorf("setup storage market actor: %w", err) + } + blks := amt.WrapBlockstore(bs) emptyroot, err := amt.FromArray(blks, nil) diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 9dec1864e..9ca4d2e0a 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -41,6 +41,17 @@ func NewWallet(keystore types.KeyStore) (*Wallet, error) { return w, nil } +func KeyWallet(keys ...*Key) *Wallet { + m := make(map[address.Address]*Key) + for _, key := range keys { + m[key.Address] = key + } + + return &Wallet{ + keys: m, + } +} + func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*types.Signature, error) { ki, err := w.findKey(addr) if err != nil { @@ -85,6 +96,11 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) { if ok { return k, nil } + if w.keystore == nil { + log.Warn("findKey didn't find the key in in-memory wallet") + return nil, nil + } + ki, err := w.keystore.Get(KNamePrefix + addr.String()) if err != nil { if xerrors.Is(err, types.ErrKeyInfoNotFound) { diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 790897800..6e333371d 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -1,6 +1,7 @@ package seed import ( + "context" "crypto/sha256" "encoding/json" "fmt" @@ -12,8 +13,12 @@ import ( badger "github.com/ipfs/go-ds-badger" "golang.org/x/xerrors" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/lib/sectorbuilder" ) @@ -52,7 +57,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, r := rand.New(rand.NewSource(101)) size := sectorbuilder.UserBytesForSectorSize(ssize) - var sealedSectors []genesis.PreSeal + var sealedSectors []*genesis.PreSeal for i := uint64(1); i <= sectors; i++ { sid, err := sb.AcquireSectorId() if err != nil { @@ -76,17 +81,35 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, return xerrors.Errorf("commit: %w", err) } - sealedSectors = append(sealedSectors, genesis.PreSeal{ + sealedSectors = append(sealedSectors, &genesis.PreSeal{ CommR: pco.CommR, CommD: pco.CommD, SectorID: sid, }) } + minerAddr, err := wallet.GenerateKey(types.KTBLS) + if err != nil { + return err + } + + miner := &genesis.GenesisMiner{ + Owner: minerAddr.Address, + Worker: minerAddr.Address, + + SectorSize: ssize, + + Sectors: sealedSectors, + + Key: minerAddr.KeyInfo, + } + + if err := createDeals(miner, minerAddr, ssize); err != nil { + return xerrors.Errorf("creating deals: %w", err) + } + output := map[string]genesis.GenesisMiner{ - maddr.String(): genesis.GenesisMiner{ - Sectors: sealedSectors, - }, + maddr.String(): *miner, } out, err := json.MarshalIndent(output, "", " ") @@ -104,3 +127,37 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, return nil } + +func createDeals(m *genesis.GenesisMiner, k *wallet.Key, ssize uint64) error { + for _, sector := range m.Sectors { + proposal := &actors.StorageDealProposal{ + PieceRef: sector.CommD[:], // just one deal so this == CommP + PieceSize: ssize, + PieceSerialization: actors.SerializationUnixFSv0, + Client: k.Address, + Provider: k.Address, + ProposalExpiration: 9000, // TODO: allow setting + Duration: 9000, + StoragePricePerEpoch: types.NewInt(0), + StorageCollateral: types.NewInt(0), + ProposerSignature: nil, + } + + if err := api.SignWith(context.TODO(), wallet.KeyWallet(k).Sign, k.Address, proposal); err != nil { + return err + } + + deal := &actors.StorageDeal{ + Proposal: *proposal, + CounterSignature: nil, + } + + if err := api.SignWith(context.TODO(), wallet.KeyWallet(k).Sign, k.Address, deal); err != nil { + return err + } + + sector.Deal = *deal + } + + return nil +} diff --git a/genesis/types.go b/genesis/types.go index 36abd8f28..e8a208452 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -1,15 +1,25 @@ package genesis -import "github.com/filecoin-project/lotus/chain/address" +import ( + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/types" +) type PreSeal struct { CommR [32]byte CommD [32]byte SectorID uint64 + Deal actors.StorageDeal } type GenesisMiner struct { - Sectors []PreSeal - Owner address.Address - Worker address.Address + Owner address.Address + Worker address.Address + + SectorSize uint64 + + Sectors []*PreSeal + + Key types.KeyInfo // TODO: separate file } diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 5b6519e47..ee60af8b0 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "golang.org/x/xerrors" "io" "io/ioutil" "os" @@ -39,9 +40,8 @@ func MakeGenesisMem(out io.Writer, minerPid peer.ID) func(bs dtypes.ChainBlockst } gmc := &gen.GenMinerCfg{ - Owners: []address.Address{w}, - Workers: []address.Address{w}, PeerIDs: []peer.ID{minerPid}, + // TODO: Call seal.PreSeal } alloc := map[address.Address]types.BigInt{ w: types.FromFil(10000), @@ -78,20 +78,34 @@ func MakeGenesis(outFile, preseal string) func(bs dtypes.ChainBlockstore, w *wal return nil, err } - minerAddr, err := w.GenerateKey(types.KTBLS) - if err != nil { - return nil, err + minerAddresses := make([]address.Address, 0, len(preseal)) + for s := range preseal { + a, err := address.NewFromString(s) + if err != nil { + return nil, err + } + if a.Protocol() != address.ID { + return nil, xerrors.New("expected ID address") + } + minerAddresses = append(minerAddresses, a) } gmc := &gen.GenMinerCfg{ - Owners: []address.Address{minerAddr}, - Workers: []address.Address{minerAddr}, - PeerIDs: []peer.ID{"peer ID 1"}, - PreSeals: preseal, + PeerIDs: []peer.ID{"peer ID 1"}, + PreSeals: preseal, + MinerAddrs: minerAddresses, } - addrs := map[address.Address]types.BigInt{ - minerAddr: types.FromFil(100000), + addrs := map[address.Address]types.BigInt{} + + for _, miner := range preseal { + if _, err := w.Import(&miner.Key); err != nil { + return nil, xerrors.Errorf("importing miner key: %w", err) + } + + _ = w.SetDefault(miner.Worker) + + addrs[miner.Worker] = types.FromFil(100000) } b, err := gen.MakeGenesisBlock(bs, addrs, gmc, uint64(time.Now().Unix())) From ce89ddbd6aee1dedbd09d976d030595e90a479cd Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 28 Nov 2019 21:38:18 -0600 Subject: [PATCH 41/93] fixing some tests --- chain/actors/cbor_gen.go | 66 ++++++++++++++++++++++++++++++--- chain/address/address_test.go | 8 ++-- chain/gen/gen.go | 27 +++++++++++++- chain/types/blockheader_test.go | 6 ++- chain/validation/state.go | 13 +++++-- cmd/lotus-seed/main.go | 7 +++- cmd/lotus-seed/seed/seed.go | 34 +++++++++-------- lotuspond/spawn.go | 7 +++- 8 files changed, 135 insertions(+), 33 deletions(-) diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 1666adeb2..115f02744 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -818,11 +818,27 @@ func (t *SubmitFallbackPoStParams) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{129}); err != nil { + if _, err := w.Write([]byte{130}); err != nil { return err } - // t.t.Proof (types.EPostProof) (struct) + // t.t.Proof ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil { + return err + } + if _, err := w.Write(t.Proof); err != nil { + return err + } + + // t.t.Candidates ([]types.EPostTicket) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil { + return err + } + for _, v := range t.Candidates { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } return nil } @@ -837,15 +853,53 @@ func (t *SubmitFallbackPoStParams) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 1 { + if extra != 2 { return fmt.Errorf("cbor input had wrong number of fields") } - // t.t.Proof (types.EPostProof) (struct) - - { + // t.t.Proof ([]uint8) (slice) + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err } + if extra > 8192 { + return fmt.Errorf("t.Proof: array too large (%d)", extra) + } + + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Proof = make([]byte, extra) + if _, err := io.ReadFull(br, t.Proof); err != nil { + return err + } + // t.t.Candidates ([]types.EPostTicket) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.Candidates: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + if extra > 0 { + t.Candidates = make([]types.EPostTicket, extra) + } + for i := 0; i < int(extra); i++ { + + var v types.EPostTicket + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Candidates[i] = v + } + return nil } diff --git a/chain/address/address_test.go b/chain/address/address_test.go index 33e69312f..48e9fc76f 100644 --- a/chain/address/address_test.go +++ b/chain/address/address_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/filecoin-project/filecoin-ffi" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-leb128" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -285,7 +285,7 @@ func TestVectorActorAddress(t *testing.T) { func TestRandomBLSAddress(t *testing.T) { assert := assert.New(t) - pk := bls.PrivateKeyPublicKey(bls.PrivateKeyGenerate()) + pk := ffi.PrivateKeyPublicKey(ffi.PrivateKeyGenerate()) addr, err := NewBLSAddress(pk[:]) assert.NoError(err) @@ -410,8 +410,8 @@ func TestInvalidByteAddresses(t *testing.T) { {append([]byte{2}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload}, // BLS Protocol - {append([]byte{3}, make([]byte, bls.PublicKeyBytes-1)...), ErrInvalidPayload}, - {append([]byte{3}, make([]byte, bls.PrivateKeyBytes+1)...), ErrInvalidPayload}, + {append([]byte{3}, make([]byte, ffi.PublicKeyBytes-1)...), ErrInvalidPayload}, + {append([]byte{3}, make([]byte, ffi.PrivateKeyBytes+1)...), ErrInvalidPayload}, } for _, tc := range testCases { diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 308439237..6b8aefccc 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -6,9 +6,11 @@ import ( "crypto/sha256" "encoding/binary" "fmt" - ffi "github.com/filecoin-project/filecoin-ffi" + "io/ioutil" "sync/atomic" + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/ipfs/go-blockservice" "github.com/ipfs/go-car" offline "github.com/ipfs/go-ipfs-exchange-offline" @@ -24,6 +26,8 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" + "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/node/repo" @@ -131,9 +135,28 @@ func NewGenerator() (*ChainGen, error) { } } + // TODO: this is really weird, we have to guess the miner addresses that + // will be created in order to preseal data for them + maddr1, err := address.NewFromString("t0101") + if err != nil { + return nil, err + } + + m1temp, err := ioutil.TempDir("", "preseal") + if err != nil { + return nil, err + } + + genm1, err := seed.PreSeal(maddr1, 1024, 1, m1temp, []byte("some randomness")) + if err != nil { + return nil, err + } + minercfg := &GenMinerCfg{ PeerIDs: []peer.ID{"peerID1", "peerID2"}, - // Call PreSeal(and give worker addrs to it somehow) + PreSeals: map[string]genesis.GenesisMiner{ + maddr1.String(): *genm1, + }, } genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{ diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index 60f8b7770..54ec1da09 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "fmt" "reflect" "testing" @@ -25,7 +26,8 @@ func testBlockHeader(t testing.TB) *BlockHeader { return &BlockHeader{ Miner: addr, EPostProof: EPostProof{ - Proof: []byte("pruuf"), + Proof: []byte("pruuf"), + PostRand: []byte("random"), }, Ticket: &Ticket{ VRFProof: []byte("vrf proof0000000vrf proof0000000"), @@ -55,6 +57,8 @@ func TestBlockHeaderSerialization(t *testing.T) { } if !reflect.DeepEqual(&out, bh) { + fmt.Printf("%#v\n", &out) + fmt.Printf("%#v\n", bh) t.Fatal("not equal") } } diff --git a/chain/validation/state.go b/chain/validation/state.go index 8a51e442e..087c05b21 100644 --- a/chain/validation/state.go +++ b/chain/validation/state.go @@ -135,12 +135,19 @@ func (s *StateWrapper) SetSingletonActor(addr vstate.SingletonActorID, balance v return &actorWrapper{*initact}, s.storage, s.flush(tree) case actors.StorageMarketAddress: - smact, err := gen.SetupStorageMarketActor(s.bs) + nsroot, err := gen.SetupStorageMarketActor(s.bs, s.stateRoot, nil) if err != nil { return nil, nil, err } - if err := tree.SetActor(actors.StorageMarketAddress, smact); err != nil { - return nil, nil, xerrors.Errorf("set network storage market actor: %w", err) + s.stateRoot = nsroot + + tree, err = state.LoadStateTree(s.cst, s.stateRoot) + if err != nil { + return nil, nil, err + } + smact, err := tree.GetActor(actors.StorageMarketAddress) + if err != nil { + return nil, nil, err } return &actorWrapper{*smact}, s.storage, s.flush(tree) case actors.StoragePowerAddress: diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index 603a346b4..cebe71f32 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -79,6 +79,11 @@ var preSealCmd = &cli.Command{ return err } - return seed.PreSeal(maddr, c.Uint64("sector-size"), c.Uint64("num-sectors"), sbroot, []byte(c.String("ticket-preimage"))) + gm, err := seed.PreSeal(maddr, c.Uint64("sector-size"), c.Uint64("num-sectors"), sbroot, []byte(c.String("ticket-preimage"))) + if err != nil { + return err + } + + return seed.WriteGenesisMiner(maddr, sbroot, gm) }, } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 6e333371d..f1c2cbbc9 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -23,7 +23,7 @@ import ( "github.com/filecoin-project/lotus/lib/sectorbuilder" ) -func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, preimage []byte) error { +func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, preimage []byte) (*genesis.GenesisMiner, error) { cfg := §orbuilder.Config{ Miner: maddr, SectorSize: ssize, @@ -36,22 +36,22 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { if err := os.MkdirAll(d, 0775); err != nil { - return err + return nil, err } } mds, err := badger.NewDatastore(filepath.Join(sbroot, "badger"), nil) if err != nil { - return err + return nil, err } if err := build.GetParams(true, false); err != nil { - return xerrors.Errorf("getting params: %w", err) + return nil, xerrors.Errorf("getting params: %w", err) } sb, err := sectorbuilder.New(cfg, mds) if err != nil { - return err + return nil, err } r := rand.New(rand.NewSource(101)) @@ -61,12 +61,12 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, for i := uint64(1); i <= sectors; i++ { sid, err := sb.AcquireSectorId() if err != nil { - return err + return nil, err } pi, err := sb.AddPiece(size, sid, r, nil) if err != nil { - return err + return nil, err } trand := sha256.Sum256(preimage) @@ -78,7 +78,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, pco, err := sb.SealPreCommit(sid, ticket, []sectorbuilder.PublicPieceInfo{pi}) if err != nil { - return xerrors.Errorf("commit: %w", err) + return nil, xerrors.Errorf("commit: %w", err) } sealedSectors = append(sealedSectors, &genesis.PreSeal{ @@ -90,7 +90,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, minerAddr, err := wallet.GenerateKey(types.KTBLS) if err != nil { - return err + return nil, err } miner := &genesis.GenesisMiner{ @@ -105,11 +105,19 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, } if err := createDeals(miner, minerAddr, ssize); err != nil { - return xerrors.Errorf("creating deals: %w", err) + return nil, xerrors.Errorf("creating deals: %w", err) } + if err := mds.Close(); err != nil { + return nil, xerrors.Errorf("closing datastore: %w", err) + } + + return miner, nil +} + +func WriteGenesisMiner(maddr address.Address, sbroot string, gm *genesis.GenesisMiner) error { output := map[string]genesis.GenesisMiner{ - maddr.String(): *miner, + maddr.String(): *gm, } out, err := json.MarshalIndent(output, "", " ") @@ -121,10 +129,6 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, return err } - if err := mds.Close(); err != nil { - return xerrors.Errorf("closing datastore: %w", err) - } - return nil } diff --git a/lotuspond/spawn.go b/lotuspond/spawn.go index 5f0faa35c..5eb8ca52d 100644 --- a/lotuspond/spawn.go +++ b/lotuspond/spawn.go @@ -35,10 +35,15 @@ func (api *api) Spawn() (nodeInfo, error) { return nodeInfo{}, err } - err = seed.PreSeal(genMiner, build.SectorSizes[0], 1, filepath.Join(dir, "preseal"), []byte("8")) + sbroot := filepath.Join(dir, "preseal") + genm, err := seed.PreSeal(genMiner, build.SectorSizes[0], 1, sbroot, []byte("8")) if err != nil { return nodeInfo{}, xerrors.Errorf("preseal failed: %w", err) } + + if err := seed.WriteGenesisMiner(genMiner, sbroot, genm); err != nil { + return nodeInfo{}, xerrors.Errorf("failed to write genminer info: %w", err) + } params = append(params, "--genesis-presealed-sectors="+filepath.Join(dir, "preseal", "pre-seal-t0101.json")) // make genesis From 637c28ba5520debfd0662452e64ef51b8d2853d0 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 28 Nov 2019 22:04:46 -0600 Subject: [PATCH 42/93] generator sets up appropriate number of miners --- chain/gen/gen.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 6b8aefccc..9eb841e31 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -152,10 +152,26 @@ func NewGenerator() (*ChainGen, error) { return nil, err } + maddr2, err := address.NewFromString("t0102") + if err != nil { + return nil, err + } + + m2temp, err := ioutil.TempDir("", "preseal") + if err != nil { + return nil, err + } + + genm2, err := seed.PreSeal(maddr2, 1024, 1, m2temp, []byte("some randomness")) + if err != nil { + return nil, err + } + minercfg := &GenMinerCfg{ PeerIDs: []peer.ID{"peerID1", "peerID2"}, PreSeals: map[string]genesis.GenesisMiner{ maddr1.String(): *genm1, + maddr2.String(): *genm2, }, } From 3dddcb85e7c0d686548f209368e912a8c7912125 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 28 Nov 2019 20:41:37 -0800 Subject: [PATCH 43/93] tests properly create miners, they just can't mine yet --- chain/gen/gen.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 9eb841e31..e882dd424 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -112,16 +112,6 @@ func NewGenerator() (*ChainGen, error) { return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err) } - worker1, err := w.GenerateKey(types.KTBLS) - if err != nil { - return nil, xerrors.Errorf("failed to generate worker key: %w", err) - } - - worker2, err := w.GenerateKey(types.KTBLS) - if err != nil { - return nil, xerrors.Errorf("failed to generate worker key: %w", err) - } - banker, err := w.GenerateKey(types.KTSecp256k1) if err != nil { return nil, xerrors.Errorf("failed to generate banker key: %w", err) @@ -167,18 +157,28 @@ func NewGenerator() (*ChainGen, error) { return nil, err } + mk1, err := w.Import(&genm1.Key) + if err != nil { + return nil, err + } + mk2, err := w.Import(&genm2.Key) + if err != nil { + return nil, err + } + minercfg := &GenMinerCfg{ PeerIDs: []peer.ID{"peerID1", "peerID2"}, PreSeals: map[string]genesis.GenesisMiner{ maddr1.String(): *genm1, maddr2.String(): *genm2, }, + MinerAddrs: []address.Address{maddr1, maddr2}, } genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{ - worker1: types.FromFil(40000), - worker2: types.FromFil(40000), - banker: types.FromFil(50000), + mk1: types.FromFil(40000), + mk2: types.FromFil(40000), + banker: types.FromFil(50000), }, minercfg, 100000) if err != nil { return nil, xerrors.Errorf("make genesis block failed: %w", err) From 57f6d9e624c92f1b1aa88dbcf5dd17513c67211f Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 28 Nov 2019 20:45:30 -0800 Subject: [PATCH 44/93] correctly predict miner addresses for test --- chain/gen/gen.go | 4 ++-- chain/gen/utils.go | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index e882dd424..a7c0ff00f 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -127,7 +127,7 @@ func NewGenerator() (*ChainGen, error) { // TODO: this is really weird, we have to guess the miner addresses that // will be created in order to preseal data for them - maddr1, err := address.NewFromString("t0101") + maddr1, err := address.NewFromString("t0103") if err != nil { return nil, err } @@ -142,7 +142,7 @@ func NewGenerator() (*ChainGen, error) { return nil, err } - maddr2, err := address.NewFromString("t0102") + maddr2, err := address.NewFromString("t0104") if err != nil { return nil, err } diff --git a/chain/gen/utils.go b/chain/gen/utils.go index 82a9e907a..a33f3ed2e 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -286,8 +286,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, nil, err } - gmcfg.MinerAddrs = append(gmcfg.MinerAddrs, maddr) - power := types.BigMul(types.NewInt(minerParams.SectorSize), types.NewInt(uint64(len(ps.Sectors)))) params = mustEnc(&actors.UpdateStorageParams{Delta: power}) From 01e4958f73ecde75fc02b4cbd15f9b843138650c Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 28 Nov 2019 21:25:03 -0800 Subject: [PATCH 45/93] remove debug prints --- chain/actors/actor_miner.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 1c574eb37..3a75f261d 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -190,7 +190,6 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ SectorSize: params.SectorSize, } - fmt.Println("NEW STORAGE MINER WITH SECTOR SIZE: ", params.SectorSize) minfocid, err := vmctx.Storage().Put(minerInfo) if err != nil { return nil, err @@ -904,7 +903,6 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro prevSlashingDeadline = 0 } - fmt.Println("POWER UPDATE DELTA: ", delta) enc, err := SerializeParams(&UpdateStorageParams{ Delta: delta, NextProvingPeriodEnd: vmctx.BlockHeight() + build.SlashablePowerDelay, From 0ca92bdca0c8a7485845a10d97699729bd24211b Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 29 Nov 2019 10:48:07 -0800 Subject: [PATCH 46/93] track hot and cold times for epost --- cmd/lotus-bench/main.go | 58 ++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index cbdaa3048..be640ba70 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "context" "crypto/sha256" "fmt" @@ -30,8 +31,10 @@ type BenchResults struct { SealingResults []SealingResult PostGenerateCandidates time.Duration - PostEProof time.Duration - VerifyEPost time.Duration + PostEProofCold time.Duration + PostEProofHot time.Duration + VerifyEPostCold time.Duration + VerifyEPostHot time.Duration } type SealingResult struct { @@ -158,7 +161,13 @@ func main() { sealcommit := time.Now() commD := pi.CommP - sectorbuilder.VerifySeal(sectorSize, pco.CommR[:], commD[:], maddr, ticket.TicketBytes[:], seed.TicketBytes[:], i, proof) + ok, err := sectorbuilder.VerifySeal(sectorSize, pco.CommR[:], commD[:], maddr, ticket.TicketBytes[:], seed.TicketBytes[:], i, proof) + if err != nil { + return err + } + if !ok { + return xerrors.Errorf("porep proof for sector %d was invalid", i) + } verifySeal := time.Now() @@ -184,15 +193,27 @@ func main() { gencandidates := time.Now() - log.Info("computing election post snark") - proof, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1]) + log.Info("computing election post snark (cold)") + proof1, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1]) if err != nil { return err } - epost := time.Now() + epost1 := time.Now() - ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr) + log.Info("computing election post snark (hot)") + proof2, err := sb.ComputeElectionPoSt(sinfos, challenge[:], candidates[:1]) + if err != nil { + return err + } + + epost2 := time.Now() + + if !bytes.Equal(proof1, proof2) { + log.Warn("separate epost calls returned different proof values (this might be bad)") + } + + ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof1, candidates[:1], maddr) if err != nil { return err } @@ -200,15 +221,26 @@ func main() { log.Error("post verification failed") } - verifypost := time.Now() + verifypost1 := time.Now() + + ok, err = sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof2, candidates[:1], maddr) + if err != nil { + return err + } + if !ok { + log.Error("post verification failed") + } + verifypost2 := time.Now() benchout := BenchResults{ SectorSize: cfg.SectorSize, SealingResults: sealTimings, PostGenerateCandidates: gencandidates.Sub(beforePost), - PostEProof: epost.Sub(gencandidates), - VerifyEPost: verifypost.Sub(epost), + PostEProofCold: epost1.Sub(gencandidates), + PostEProofHot: epost2.Sub(epost1), + VerifyEPostCold: verifypost1.Sub(epost2), + VerifyEPostHot: verifypost2.Sub(verifypost1), } // TODO: optionally write this as json to a file fmt.Println("results") @@ -217,8 +249,10 @@ func main() { fmt.Printf("seal: Commit: %s\n", benchout.SealingResults[0].Commit) fmt.Printf("seal: Verify: %s\n", benchout.SealingResults[0].Verify) fmt.Printf("generate candidates: %s\n", benchout.PostGenerateCandidates) - fmt.Printf("compute epost proof: %s\n", benchout.PostEProof) - fmt.Printf("verify epost proof: %s\n", benchout.VerifyEPost) + fmt.Printf("compute epost proof (cold): %s\n", benchout.PostEProofCold) + fmt.Printf("compute epost proof (hot): %s\n", benchout.PostEProofHot) + fmt.Printf("verify epost proof (cold): %s\n", benchout.VerifyEPostCold) + fmt.Printf("verify epost proof (hot): %s\n", benchout.VerifyEPostHot) return nil }, } From ad978949db8b5e1f52a6af68049a16f808c2634a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 29 Nov 2019 20:11:01 +0100 Subject: [PATCH 47/93] import sector/deal into state machines on init --- build/params_debug.go | 2 +- chain/actors/actor_storagemarket.go | 12 ++- chain/deals/provider.go | 4 +- cmd/lotus-storage-miner/init.go | 145 +++++++++++++++++++++++++--- cmd/lotus-storage-miner/run.go | 1 + cmd/lotus/daemon.go | 2 +- storage/miner.go | 4 +- storage/sealing.go | 40 ++++++-- storage/sector_states.go | 2 +- 9 files changed, 186 insertions(+), 26 deletions(-) diff --git a/build/params_debug.go b/build/params_debug.go index 3337c827f..71c243113 100644 --- a/build/params_debug.go +++ b/build/params_debug.go @@ -5,7 +5,7 @@ package build import "os" // Seconds -const BlockDelay = 2 +const BlockDelay = 4 // Blocks const ProvingPeriodDuration uint64 = 40 diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 6fb07be3f..772911f1d 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -3,16 +3,17 @@ package actors import ( "bytes" "context" + "golang.org/x/xerrors" "github.com/filecoin-project/go-amt-ipld" "github.com/ipfs/go-cid" "github.com/ipfs/go-hamt-ipld" - "golang.org/x/xerrors" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/aerrors" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/cborutil" "github.com/filecoin-project/lotus/lib/sectorbuilder" ) @@ -110,6 +111,15 @@ func (sdp *StorageDealProposal) Sign(ctx context.Context, sign SignFunc) error { return nil } +func (sdp *StorageDealProposal) Cid() (cid.Cid, error) { + nd, err := cborutil.AsIpld(sdp) + if err != nil { + return cid.Undef, err + } + + return nd.Cid(), nil +} + func (sdp *StorageDealProposal) Verify() error { unsigned := *sdp unsigned.ProposerSignature = nil diff --git a/chain/deals/provider.go b/chain/deals/provider.go index fecaecea2..626fa7c0b 100644 --- a/chain/deals/provider.go +++ b/chain/deals/provider.go @@ -24,6 +24,8 @@ import ( "github.com/filecoin-project/lotus/storage/sectorblocks" ) +var ProviderDsPrefix = "/deals/provider" + type MinerDeal struct { Client peer.ID Proposal actors.StorageDealProposal @@ -110,7 +112,7 @@ func NewProvider(ds dtypes.MetadataDS, sminer *storage.Miner, secb *sectorblocks actor: minerAddress, - deals: statestore.New(namespace.Wrap(ds, datastore.NewKey("/deals/client"))), + deals: statestore.New(namespace.Wrap(ds, datastore.NewKey(ProviderDsPrefix))), ds: ds, } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 87d51769d..de1164cb5 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -3,8 +3,12 @@ package main import ( "context" "crypto/rand" + "encoding/json" + "fmt" + "io/ioutil" "os" "path/filepath" + "strconv" "github.com/ipfs/go-datastore" badger "github.com/ipfs/go-ds-badger" @@ -14,12 +18,15 @@ import ( "golang.org/x/xerrors" "gopkg.in/urfave/cli.v2" - "github.com/filecoin-project/lotus/api" + lapi "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/deals" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/genesis" + "github.com/filecoin-project/lotus/lib/cborutil" "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node/modules" @@ -199,7 +206,116 @@ func migratePreSealedSectors(presealsb string, repoPath string, mds dtypes.Metad return nil } -func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, r repo.Repo) error { +func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir string, maddr address.Address, mds dtypes.MetadataDS) error { + b, err := ioutil.ReadFile(filepath.Join(presealDir, "pre-seal-"+maddr.String()+".json")) + if err != nil { + return xerrors.Errorf("reading preseal metadata: %w", err) + } + + preseals := map[string]genesis.GenesisMiner{} + + if err := json.Unmarshal(b, &preseals); err != nil { + return xerrors.Errorf("unmarshaling preseal metadata: %w", err) + } + + meta, ok := preseals[maddr.String()] + if !ok { + return xerrors.New("got wrong preseal info") + } + + for _, sector := range meta.Sectors { + sectorKey := datastore.NewKey(storage.SectorStorePrefix).ChildString(fmt.Sprint(sector.SectorID)) + + dealID, err := findMarketDealID(ctx, api, sector.Deal) + if err != nil { + return xerrors.Errorf("finding storage deal for pre-sealed sector %d: %w", sector.SectorID, err) + } + + info := &storage.SectorInfo{ + State: lapi.Proving, + SectorID: sector.SectorID, + Pieces: []storage.Piece{ + { + DealID: dealID, + Ref: fmt.Sprintf("preseal-%d", sector.SectorID), + Size: meta.SectorSize, + CommP: sector.CommD[:], + }, + }, + CommC: nil, + CommD: sector.CommD[:], + CommR: sector.CommR[:], + CommRLast: nil, + Proof: nil, + Ticket: storage.SealTicket{}, + PreCommitMessage: nil, + Seed: storage.SealSeed{}, + CommitMessage: nil, + } + + b, err := cborutil.Dump(info) + if err != nil { + return err + } + + if err := mds.Put(sectorKey, b); err != nil { + return err + } + + proposalCid, err := sector.Deal.Proposal.Cid() + if err != nil { + return err + } + + dealKey := datastore.NewKey(deals.ProviderDsPrefix).ChildString(proposalCid.String()) + + deal := &deals.MinerDeal{ + Proposal: sector.Deal.Proposal, + ProposalCid: proposalCid, + State: lapi.DealComplete, + Ref: proposalCid, // TODO: This is super wrong, but there + // are no params for CommP CIDs, we can't recover unixfs cid easily, + // and this isn't even used after the deal enters Complete state + DealID: dealID, + SectorID: sector.SectorID, + } + + b, err = cborutil.Dump(deal) + if err != nil { + return err + } + + if err := mds.Put(dealKey, b); err != nil { + return err + } + } + + return nil +} + +func findMarketDealID(ctx context.Context, api lapi.FullNode, deal actors.StorageDeal) (uint64, error) { + // TODO: find a better way + // (this is only used by genesis miners) + + deals, err := api.StateMarketDeals(ctx, nil) + if err != nil { + return 0, xerrors.Errorf("getting market deals: %w", err) + } + + for k, v := range deals { + eq, err := cborutil.Equals(&v.Deal, &deal) + if err != nil { + return 0, err + } + if eq { + return strconv.ParseUint(k, 10, 64) + } + } + + return 0, xerrors.New("deal not found") +} + +func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, r repo.Repo) error { lr, err := r.Lock(repo.StorageMiner) if err != nil { return err @@ -218,6 +334,11 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, return xerrors.Errorf("peer ID from private key: %w", err) } + mds, err := lr.Datastore("/metadata") + if err != nil { + return err + } + var addr address.Address if act := cctx.String("actor"); act != "" { a, err := address.NewFromString(act) @@ -226,10 +347,6 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, } if cctx.Bool("genesis-miner") { - mds, err := lr.Datastore("/metadata") - if err != nil { - return err - } if err := mds.Put(datastore.NewKey("miner-address"), a.Bytes()); err != nil { return err } @@ -261,6 +378,14 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, } } + if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { + log.Infof("Importing pre-sealed sector metadata for %s", a) + + if err := migratePreSealMeta(ctx, api, cctx.String("pre-sealed-sectors"), a, mds); err != nil { + return xerrors.Errorf("migrating presealed sector metadata: %w", err) + } + } + return nil } else { if err := configureStorageMiner(ctx, api, a, peerid); err != nil { @@ -279,10 +404,6 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api api.FullNode, } log.Infof("Created new storage miner: %s", addr) - mds, err := lr.Datastore("/metadata") - if err != nil { - return err - } if err := mds.Put(datastore.NewKey("miner-address"), addr.Bytes()); err != nil { return err } @@ -316,7 +437,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) { return pk, nil } -func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.Address, peerid peer.ID) error { +func configureStorageMiner(ctx context.Context, api lapi.FullNode, addr address.Address, peerid peer.ID) error { // This really just needs to be an api call at this point... recp, err := api.StateCall(ctx, &types.Message{ To: addr, @@ -369,7 +490,7 @@ func configureStorageMiner(ctx context.Context, api api.FullNode, addr address.A return nil } -func createStorageMiner(ctx context.Context, api api.FullNode, peerid peer.ID, cctx *cli.Context) (addr address.Address, err error) { +func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, cctx *cli.Context) (addr address.Address, err error) { log.Info("Creating StorageMarket.CreateStorageMiner message") var owner address.Address diff --git a/cmd/lotus-storage-miner/run.go b/cmd/lotus-storage-miner/run.go index 735a0d21d..894303b92 100644 --- a/cmd/lotus-storage-miner/run.go +++ b/cmd/lotus-storage-miner/run.go @@ -33,6 +33,7 @@ var runCmd = &cli.Command{ &cli.BoolFlag{ Name: "enable-gpu-proving", Usage: "Enable use of GPU for mining operations", + Value: true, }, }, Action: func(cctx *cli.Context) error { diff --git a/cmd/lotus/daemon.go b/cmd/lotus/daemon.go index c20ec7e6e..bbf036275 100644 --- a/cmd/lotus/daemon.go +++ b/cmd/lotus/daemon.go @@ -40,7 +40,7 @@ var DaemonCmd = &cli.Command{ Hidden: true, }, &cli.StringFlag{ - Name: "genesis-presealed-sectors", + Name: preSealedSectorsFlag, Hidden: true, }, &cli.StringFlag{ diff --git a/storage/miner.go b/storage/miner.go index 15f65e60c..f295504d8 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -24,7 +24,7 @@ import ( var log = logging.Logger("storageminer") -const PoStConfidence = 3 +const SectorStorePrefix = "/sectors" type Miner struct { api storageMinerApi @@ -83,7 +83,7 @@ func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datasto sb: sb, tktFn: tktFn, - sectors: statestore.New(namespace.Wrap(ds, datastore.NewKey("/sectors"))), + sectors: statestore.New(namespace.Wrap(ds, datastore.NewKey(SectorStorePrefix))), sectorIncoming: make(chan *SectorInfo), sectorUpdated: make(chan sectorUpdate), diff --git a/storage/sealing.go b/storage/sealing.go index 3e3c576f5..7b3356fc7 100644 --- a/storage/sealing.go +++ b/storage/sealing.go @@ -125,13 +125,13 @@ func (t *SectorInfo) rspco() sectorbuilder.RawSealPreCommitOutput { } func (m *Miner) sectorStateLoop(ctx context.Context) error { - toRestart, err := m.ListSectors() + trackedSectors, err := m.ListSectors() if err != nil { return err } go func() { - for _, si := range toRestart { + for _, si := range trackedSectors { select { case m.sectorUpdated <- sectorUpdate{ newState: si.State, @@ -146,6 +146,32 @@ func (m *Miner) sectorStateLoop(ctx context.Context) error { } }() + { + // verify on-chain state + trackedByID := map[uint64]*SectorInfo{} + for _, si := range trackedSectors { + trackedByID[si.SectorID] = &si + } + + curTs, err := m.api.ChainHead(ctx) + if err != nil { + return xerrors.Errorf("getting chain head: %w", err) + } + + ps, err := m.api.StateMinerProvingSet(ctx, m.maddr, curTs) + if err != nil { + return err + } + for _, ocs := range ps { + if _, ok := trackedByID[ocs.SectorID]; ok { + continue // TODO: check state + } + + // TODO: attempt recovery + log.Warnf("untracked sector %d found on chain", ocs.SectorID) + } + } + go func() { defer log.Warn("quitting deal provider loop") defer close(m.stopped) @@ -217,15 +243,15 @@ func (m *Miner) onSectorUpdated(ctx context.Context, update sectorUpdate) { switch update.newState { case api.Packing: - m.handle(ctx, sector, m.finishPacking, api.Unsealed) + m.handleSectorUpdate(ctx, sector, m.finishPacking, api.Unsealed) case api.Unsealed: - m.handle(ctx, sector, m.sealPreCommit, api.PreCommitting) + m.handleSectorUpdate(ctx, sector, m.sealPreCommit, api.PreCommitting) case api.PreCommitting: - m.handle(ctx, sector, m.preCommit, api.PreCommitted) + m.handleSectorUpdate(ctx, sector, m.preCommit, api.PreCommitted) case api.PreCommitted: - m.handle(ctx, sector, m.preCommitted, api.SectorNoUpdate) + m.handleSectorUpdate(ctx, sector, m.preCommitted, api.SectorNoUpdate) case api.Committing: - m.handle(ctx, sector, m.committing, api.Proving) + m.handleSectorUpdate(ctx, sector, m.committing, api.Proving) case api.Proving: // TODO: track sector health / expiration log.Infof("Proving sector %d", update.id) diff --git a/storage/sector_states.go b/storage/sector_states.go index 455fa15b8..d57f6275d 100644 --- a/storage/sector_states.go +++ b/storage/sector_states.go @@ -14,7 +14,7 @@ import ( type providerHandlerFunc func(ctx context.Context, deal SectorInfo) (func(*SectorInfo), error) -func (m *Miner) handle(ctx context.Context, sector SectorInfo, cb providerHandlerFunc, next api.SectorState) { +func (m *Miner) handleSectorUpdate(ctx context.Context, sector SectorInfo, cb providerHandlerFunc, next api.SectorState) { go func() { mut, err := cb(ctx, sector) From adf71f502c84a8780d6892f2388f8f9aec6d8a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 29 Nov 2019 20:14:10 +0100 Subject: [PATCH 48/93] don't print scary errors when miner has no sectors --- chain/gen/gen.go | 4 +++- chain/stmgr/stmgr.go | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index a7c0ff00f..ccb48a1c9 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -492,7 +492,9 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add if err != nil { return false, nil, xerrors.Errorf("failed to load proving set for miner: %w", err) } - log.Warningf("Proving set for miner %s: %s", miner, pset) + if len(pset) == 0 { + return false, nil, nil + } var sinfos []ffi.PublicSectorInfo for _, s := range pset { diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index d2ef66327..3ead45bfa 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -136,7 +136,6 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl } // all block miners created a valid post, go update the actor state - fmt.Println("SUBMIT ELECTION POST TIME", netact.Nonce, b.Height) postSubmitMsg := &types.Message{ From: actors.NetworkAddress, Nonce: netact.Nonce, From 703bc7e774c55e72dae8b07ea175f23ac00cbfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 29 Nov 2019 21:18:34 +0100 Subject: [PATCH 49/93] Fix slashing / power recovery issues --- build/params_debug.go | 18 +++++++++++++++--- build/params_devnet.go | 16 ++++++++++++++-- build/params_shared.go | 20 -------------------- chain/actors/actor_miner.go | 4 ++++ chain/actors/actor_storagemarket.go | 4 +--- chain/actors/actor_storagepower.go | 6 +++--- lotuspond/front/src/State.js | 2 +- lotuspond/front/src/StorageNode.js | 2 +- miner/miner.go | 19 +++++++++++++++++++ 9 files changed, 58 insertions(+), 33 deletions(-) diff --git a/build/params_debug.go b/build/params_debug.go index 71c243113..7186ee478 100644 --- a/build/params_debug.go +++ b/build/params_debug.go @@ -5,10 +5,22 @@ package build import "os" // Seconds -const BlockDelay = 4 +const BlockDelay = 6 -// Blocks -const ProvingPeriodDuration uint64 = 40 +// FallbackPoStDelay is the number of epochs the miner needs to wait after +// ElectionPeriodStart before starting fallback post computation +// +// Epochs +const FallbackPoStDelay = 10 + +// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after +// which the miner is slashed +// +// Epochs +const SlashablePowerDelay = 20 + +// Epochs +const InteractivePoRepDelay = 2 func init() { os.Setenv("TRUST_PARAMS", "1") diff --git a/build/params_devnet.go b/build/params_devnet.go index 58aa48321..2a18b9372 100644 --- a/build/params_devnet.go +++ b/build/params_devnet.go @@ -5,5 +5,17 @@ package build // Seconds const BlockDelay = 12 -// Blocks -const ProvingPeriodDuration uint64 = 300 +// FallbackPoStDelay is the number of epochs the miner needs to wait after +// ElectionPeriodStart before starting fallback post computation +// +// Epochs +const FallbackPoStDelay = 1000 + +// SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after +// which the miner is slashed +// +// Epochs +const SlashablePowerDelay = 2000 + +// Epochs +const InteractivePoRepDelay = 10 diff --git a/build/params_shared.go b/build/params_shared.go index e482ca9eb..0134084bf 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -57,13 +57,6 @@ const WRatioDen = 2 // ///// // Proofs -// PoStRandomnessLookback is additional randomness lookback for PoSt computation -// To compute randomness epoch in a given proving period: -// RandH = PPE - PoStChallangeTime - PoStRandomnessLookback -// -// Epochs -const PoStRandomnessLookback = 1 - // Epochs const SealRandomnessLookback = Finality @@ -75,16 +68,6 @@ const SectorChallengeRatioDiv = 25 const MaxFallbackPostChallengeCount = 10 -// FallbackPoStDelay is the number of epochs the miner needs to wait after -// ElectionPeriodStart before starting fallback post computation -// -// Epochs -const FallbackPoStDelay = 1000 - -// SlashablePowerDelay is the number of epochs -// Epochs -const SlashablePowerDelay = 2000 - // ///// // Mining @@ -95,9 +78,6 @@ const PowerCollateralProportion = 5 const PerCapitaCollateralProportion = 1 const CollateralPrecision = 1000 -// Epochs -const InteractivePoRepDelay = 10 - // ///// // Devnet settings diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 3a75f261d..6d0d7eb49 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -854,6 +854,10 @@ func (sma StorageMinerActor) SubmitElectionPoSt(act *types.Actor, vmctx types.VM return nil, aerr } + if self.SlashedAt != 0 { + return nil, aerrors.New(1, "slashed miners can't perform election PoSt") + } + if err := onSuccessfulPoSt(self, vmctx); err != nil { return nil, err } diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 772911f1d..9cd8a265a 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -548,9 +548,7 @@ func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx return nil, nil } - // todo: check math (written on a plane, also tired) - // TODO: division is hard, this more than likely has some off-by-one issue - toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.ProvingPeriodDuration)) + toPay := types.BigMul(dealInfo.Deal.Proposal.StoragePricePerEpoch, types.NewInt(build.SlashablePowerDelay)) b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Deal.Proposal.Client, providerWorker) if aerr != nil { diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index e76cdd054..85fb2890e 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -289,8 +289,8 @@ func (spa StoragePowerActor) UpdateStorage(act *types.Actor, vmctx types.VMConte self.TotalStorage = types.BigAdd(self.TotalStorage, params.Delta) - previousBucket := params.PreviousProvingPeriodEnd % build.ProvingPeriodDuration - nextBucket := params.NextProvingPeriodEnd % build.ProvingPeriodDuration + previousBucket := params.PreviousProvingPeriodEnd % build.SlashablePowerDelay + nextBucket := params.NextProvingPeriodEnd % build.SlashablePowerDelay if previousBucket == nextBucket && params.PreviousProvingPeriodEnd != 0 { nroot, err := vmctx.Storage().Put(&self) @@ -601,7 +601,7 @@ func (spa StoragePowerActor) CheckProofSubmissions(act *types.Actor, vmctx types } func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, height uint64) aerrors.ActorError { - bucketID := height % build.ProvingPeriodDuration + bucketID := height % build.SlashablePowerDelay buckets, eerr := amt.LoadAMT(types.WrapStorage(vmctx.Storage()), self.ProvingBuckets) if eerr != nil { diff --git a/lotuspond/front/src/State.js b/lotuspond/front/src/State.js index 0af240c2e..9932ceb5e 100644 --- a/lotuspond/front/src/State.js +++ b/lotuspond/front/src/State.js @@ -181,7 +181,7 @@ class MinerState extends React.Component {
Worker:
Sector Size: {this.state.sectorSize/1024} KiB
Power: {state.Power} ({state.Power/this.state.networkPower*100}%)
-
Proving Period End: {state.ProvingPeriodEnd}
+
Election Period Start: {state.ElectionPeriodStart}
Slashed: {state.SlashedAt === 0 ? "NO" : state.SlashedAt}
----
diff --git a/lotuspond/front/src/StorageNode.js b/lotuspond/front/src/StorageNode.js index c07abc590..903729d9f 100644 --- a/lotuspond/front/src/StorageNode.js +++ b/lotuspond/front/src/StorageNode.js @@ -120,7 +120,7 @@ class StorageNode extends React.Component {
-  PPE: {this.state.actorState.State.ProvingPeriodEnd} +  EPS: {this.state.actorState.State.ElectionPeriodStart}
{this.state.statusCounts.map((c, i) => {sealCodes[i]}: {c} | )}
diff --git a/miner/miner.go b/miner/miner.go index f8004240a..2b2b464e6 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -237,10 +237,29 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) }, nil } +func (m *Miner) isSlashed(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) { + power, err := m.api.StateMinerPower(ctx, addr, ts) + if err != nil { + return false, err + } + + return power.MinerPower.Equals(types.NewInt(0)), nil +} + func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningBase) (*types.BlockMsg, error) { log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids())) start := time.Now() + slashed, err := m.isSlashed(ctx, addr, base.ts) + if err != nil { + return nil, xerrors.Errorf("checking if miner is slashed: %w", err) + } + if slashed { + log.Warnf("Slashed at epoch %d, not attempting to mine a block", base.ts.Height()+base.nullRounds) + base.nullRounds++ + return nil, nil + } + ticket, err := m.computeTicket(ctx, addr, base) if err != nil { return nil, xerrors.Errorf("scratching ticket failed: %w", err) From 3b533ed76c587be7cd06533cba52a9498c03b6f0 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 29 Nov 2019 22:31:16 -0600 Subject: [PATCH 50/93] Genesis miner config actually sets the created miner address now --- api/test/deals.go | 2 +- build/paramfetch.go | 3 + chain/actors/actor_init.go | 1 - chain/address/address.go | 8 ++ chain/gen/gen.go | 7 +- chain/gen/utils.go | 197 +++++++++++++++++++++++++++++++- chain/stmgr/utils.go | 11 +- chain/sync.go | 3 +- chain/sync_test.go | 2 +- chain/vm/invoker.go | 6 +- cmd/lotus-chainwatch/storage.go | 2 +- miner/miner.go | 2 +- node/modules/testing/genesis.go | 22 ++-- node/node_test.go | 40 ++++++- 14 files changed, 278 insertions(+), 28 deletions(-) diff --git a/api/test/deals.go b/api/test/deals.go index cb3002459..8dbde5a78 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -42,7 +42,7 @@ func TestDealFlow(t *testing.T, b APIBuilder) { t.Fatal(err) } - maddr, err := address.NewFromString("t0101") + maddr, err := address.NewFromString("t0102") if err != nil { t.Fatal(err) } diff --git a/build/paramfetch.go b/build/paramfetch.go index b167f1ca5..f6f07cf06 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -54,6 +54,9 @@ func GetParams(storage bool, tests bool) error { ft := &fetch{} for name, info := range params { + if info.SectorSize != 1024 { + continue + } if !(SupportedSectorSize(info.SectorSize) || (tests && info.SectorSize == 1<<10)) { continue } diff --git a/chain/actors/actor_init.go b/chain/actors/actor_init.go index 66d9d98fa..ffcd5fd94 100644 --- a/chain/actors/actor_init.go +++ b/chain/actors/actor_init.go @@ -40,7 +40,6 @@ func init() { type InitActor struct{} type InitActorState struct { - // TODO: this needs to be a HAMT, its a dumb map for now AddressMap cid.Cid NextID uint64 diff --git a/chain/address/address.go b/chain/address/address.go index 801da6147..3912b8bf6 100644 --- a/chain/address/address.go +++ b/chain/address/address.go @@ -389,3 +389,11 @@ func (a *Address) UnmarshalCBOR(br io.Reader) error { return nil } + +func IDFromAddress(addr Address) (uint64, error) { + if addr.Protocol() != ID { + return 0, xerrors.Errorf("cannot get id from non id address") + } + + return leb128.ToUInt64(addr.Payload()), nil +} diff --git a/chain/gen/gen.go b/chain/gen/gen.go index ccb48a1c9..35891f000 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -127,7 +127,7 @@ func NewGenerator() (*ChainGen, error) { // TODO: this is really weird, we have to guess the miner addresses that // will be created in order to preseal data for them - maddr1, err := address.NewFromString("t0103") + maddr1, err := address.NewFromString("t0300") if err != nil { return nil, err } @@ -142,7 +142,7 @@ func NewGenerator() (*ChainGen, error) { return nil, err } - maddr2, err := address.NewFromString("t0104") + maddr2, err := address.NewFromString("t0301") if err != nil { return nil, err } @@ -256,6 +256,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add return nil, nil, xerrors.Errorf("get miner worker: %w", err) } + log.Warnf("compute VRF ROUND: %d %s %s", round, m, worker) vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof) if err != nil { return nil, nil, xerrors.Errorf("compute VRF: %w", err) @@ -307,6 +308,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad } if proof != nil { + log.Warn("making block, ticket: ", t.VRFProof) fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs) if err != nil { return nil, xerrors.Errorf("making a block for next tipset failed: %w", err) @@ -612,6 +614,7 @@ func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Addres if err != nil { return nil, err } + log.Warnf("making ticket: %x %s %s %x %x", sig.Data, worker, miner, input, sigInput) if sig.Type != types.KTBLS { return nil, fmt.Errorf("miner worker address was not a BLS key") diff --git a/chain/gen/utils.go b/chain/gen/utils.go index a33f3ed2e..e16a78813 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -1,6 +1,7 @@ package gen import ( + "bytes" "context" "fmt" @@ -8,6 +9,7 @@ import ( "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" hamt "github.com/ipfs/go-hamt-ipld" + blockstore "github.com/ipfs/go-ipfs-blockstore" bstore "github.com/ipfs/go-ipfs-blockstore" peer "github.com/libp2p/go-libp2p-peer" cbg "github.com/whyrusleeping/cbor-gen" @@ -281,11 +283,21 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, nil, xerrors.Errorf("failed to create genesis miner: %w", err) } - maddr, err := address.NewFromBytes(rval) + maddrret, err := address.NewFromBytes(rval) if err != nil { return cid.Undef, nil, err } + _, err = vm.Flush(ctx) + if err != nil { + return cid.Undef, nil, err + } + + cst := hamt.CSTFromBstore(cs.Blockstore()) + if err := reassignMinerActorAddress(vm, cst, maddrret, maddr); err != nil { + return cid.Undef, nil, err + } + power := types.BigMul(types.NewInt(minerParams.SectorSize), types.NewInt(uint64(len(ps.Sectors)))) params = mustEnc(&actors.UpdateStorageParams{Delta: power}) @@ -306,7 +318,6 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, nil, xerrors.Errorf("get miner actor failed: %w", err) } - cst := hamt.CSTFromBstore(cs.Blockstore()) var mstate actors.StorageMinerActorState if err := cst.Get(ctx, mact.Head, &mstate); err != nil { return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err) @@ -341,6 +352,149 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return c, deals, err } +func reassignMinerActorAddress(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error { + if from == to { + return nil + } + act, err := vm.StateTree().GetActor(from) + if err != nil { + return xerrors.Errorf("reassign: failed to get 'from' actor: %w", err) + } + + _, err = vm.StateTree().GetActor(to) + if err == nil { + return xerrors.Errorf("cannot reassign actor, target address taken") + } + if err := vm.StateTree().SetActor(to, act); err != nil { + return xerrors.Errorf("failed to reassign actor: %w", err) + } + + if err := adjustStorageMarketTracking(vm, cst, from, to); err != nil { + return xerrors.Errorf("adjusting storage market tracking: %w", err) + } + + // Now, adjust the tracking in the init actor + return initActorReassign(vm, cst, from, to) +} + +func adjustStorageMarketTracking(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error { + ctx := context.TODO() + act, err := vm.StateTree().GetActor(actors.StoragePowerAddress) + if err != nil { + return xerrors.Errorf("loading storage power actor: %w", err) + } + + var spst actors.StoragePowerState + if err := cst.Get(ctx, act.Head, &spst); err != nil { + return xerrors.Errorf("loading storage power actor state: %w", err) + } + + miners, err := hamt.LoadNode(ctx, cst, spst.Miners) + if err != nil { + return xerrors.Errorf("loading miner set: %w", err) + } + + if err := miners.Delete(ctx, string(from.Bytes())); err != nil { + return xerrors.Errorf("deleting from spa set: %w", err) + } + + if err := miners.Set(ctx, string(to.Bytes()), uint64(1)); err != nil { + return xerrors.Errorf("failed setting miner: %w", err) + } + + if err := miners.Flush(ctx); err != nil { + return err + } + + nminerscid, err := cst.Put(ctx, miners) + if err != nil { + return err + } + spst.Miners = nminerscid + + nhead, err := cst.Put(ctx, &spst) + if err != nil { + return err + } + + act.Head = nhead + + return nil +} + +func initActorReassign(vm *vm.VM, cst *hamt.CborIpldStore, from, to address.Address) error { + ctx := context.TODO() + initact, err := vm.StateTree().GetActor(actors.InitAddress) + if err != nil { + return xerrors.Errorf("couldnt get init actor: %w", err) + } + + var st actors.InitActorState + if err := cst.Get(ctx, initact.Head, &st); err != nil { + return xerrors.Errorf("reassign loading init actor state: %w", err) + } + + amap, err := hamt.LoadNode(ctx, cst, st.AddressMap) + if err != nil { + return xerrors.Errorf("failed to load init actor map: %w", err) + } + + target, err := address.IDFromAddress(from) + if err != nil { + return xerrors.Errorf("failed to extract ID: %w", err) + } + + var out string + halt := xerrors.Errorf("halt") + err = amap.ForEach(ctx, func(k string, v interface{}) error { + _, val, err := cbg.CborReadHeader(bytes.NewReader(v.(*cbg.Deferred).Raw)) + if err != nil { + return xerrors.Errorf("parsing int in map failed: %w", err) + } + + if val == target { + out = k + return halt + } + return nil + }) + + if err == nil { + return xerrors.Errorf("could not find from address in init ID map") + } + if !xerrors.Is(err, halt) { + return xerrors.Errorf("finding address in ID map failed: %w", err) + } + + if err := amap.Delete(ctx, out); err != nil { + return xerrors.Errorf("deleting 'from' entry in amap: %w", err) + } + + if err := amap.Set(ctx, out, target); err != nil { + return xerrors.Errorf("setting 'to' entry in amap: %w", err) + } + + if err := amap.Flush(ctx); err != nil { + return xerrors.Errorf("failed to flush amap: %w", err) + } + + ncid, err := cst.Put(ctx, amap) + if err != nil { + return err + } + + st.AddressMap = ncid + + nacthead, err := cst.Put(ctx, &st) + if err != nil { + return err + } + + initact.Head = nacthead + + return nil +} + func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) { return doExecValue(ctx, vm, to, from, types.NewInt(0), method, params) } @@ -397,6 +551,11 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B return nil, xerrors.Errorf("setup storage market actor: %w", err) } + stateroot, err = AdjustInitActorStartID(ctx, bs, stateroot, 1000) + if err != nil { + return nil, xerrors.Errorf("failed to adjust init actor start ID: %w", err) + } + blks := amt.WrapBlockstore(bs) emptyroot, err := amt.FromArray(blks, nil) @@ -453,3 +612,37 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B Genesis: b, }, nil } + +func AdjustInitActorStartID(ctx context.Context, bs blockstore.Blockstore, stateroot cid.Cid, val uint64) (cid.Cid, error) { + cst := hamt.CSTFromBstore(bs) + + tree, err := state.LoadStateTree(cst, stateroot) + if err != nil { + return cid.Undef, err + } + + act, err := tree.GetActor(actors.InitAddress) + if err != nil { + return cid.Undef, err + } + + var st actors.InitActorState + if err := cst.Get(ctx, act.Head, &st); err != nil { + return cid.Undef, err + } + + st.NextID = val + + nstate, err := cst.Put(ctx, &st) + if err != nil { + return cid.Undef, err + } + + act.Head = nstate + + if err := tree.SetActor(actors.InitAddress, act); err != nil { + return cid.Undef, err + } + + return tree.Flush() +} diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 0105ef0a5..86f66821b 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -2,6 +2,7 @@ package stmgr import ( "context" + ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/lotus/api" @@ -153,7 +154,7 @@ func GetMinerElectionPeriodStart(ctx context.Context, sm *StateManager, ts *type var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { - return 0, xerrors.Errorf("failed to load miner actor state: %w", err) + return 0, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err) } return mas.ElectionPeriodStart, nil @@ -163,7 +164,7 @@ func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { - return nil, xerrors.Errorf("failed to load miner actor state: %w", err) + return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err) } return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.ProvingSet) @@ -173,7 +174,7 @@ func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { - return nil, xerrors.Errorf("failed to load miner actor state: %w", err) + return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) } return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors) @@ -203,7 +204,7 @@ func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { - return 0, xerrors.Errorf("failed to load miner actor state: %w", err) + return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err) } cst := hamt.CSTFromBstore(sm.cs.Blockstore()) @@ -219,7 +220,7 @@ func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, ma var mas actors.StorageMinerActorState _, err := sm.LoadActorState(ctx, maddr, &mas, ts) if err != nil { - return 0, xerrors.Errorf("failed to load miner actor state: %w", err) + return 0, xerrors.Errorf("(get mslash) failed to load miner actor state: %w", err) } return mas.SlashedAt, nil diff --git a/chain/sync.go b/chain/sync.go index abedd2ff0..2519ab71c 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -615,11 +615,12 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err }) tktsCheck := async.Err(func() error { - vrfBase := gen.TicketHash(baseTs.MinTicket(), h.Miner) + vrfBase := baseTs.MinTicket().VRFProof err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof) if err != nil { + log.Warnf("BAD TICKET: %d %x %x %s %s %x", h.Height, h.Ticket.VRFProof, vrfBase, waddr, h.Miner, baseTs.MinTicket().VRFProof) return xerrors.Errorf("validating block tickets failed: %w", err) } return nil diff --git a/chain/sync_test.go b/chain/sync_test.go index 49e26774a..f161316b9 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -346,7 +346,7 @@ func (tu *syncTestUtil) waitUntilSyncTarget(to int, target *types.TipSet) { } func TestSyncSimple(t *testing.T) { - H := 50 + H := 2 tu := prepSyncTest(t, H) client := tu.addClientNode() diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index c53b75c24..7dca9f96c 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -42,9 +42,13 @@ func newInvoker() *invoker { func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint64, params []byte) ([]byte, aerrors.ActorError) { + if act.Code == actors.AccountCodeCid { + return nil, aerrors.Newf(254, "cannot invoke methods on account actors") + } + code, ok := inv.builtInCode[act.Code] if !ok { - log.Errorf("no code for actor %s", act.Code) + log.Errorf("no code for actor %s (Addr: %s)", act.Code, vmctx.Message().To) return nil, aerrors.Newf(255, "no code for actor %s(%d)(%s)", act.Code, method, hex.EncodeToString(params)) } if method >= uint64(len(code)) || code[method] == nil { diff --git a/cmd/lotus-chainwatch/storage.go b/cmd/lotus-chainwatch/storage.go index 26f88640b..35135313f 100644 --- a/cmd/lotus-chainwatch/storage.go +++ b/cmd/lotus-chainwatch/storage.go @@ -252,7 +252,7 @@ func (st *storage) storeMiners(miners map[minerKey]*minerInfo) error { i.info.SectorSize, i.state.Power.String(), i.state.Active, - i.state.ProvingPeriodEnd, + i.state.ElectionPeriodStart, i.state.SlashedAt, ); err != nil { return err diff --git a/miner/miner.go b/miner/miner.go index 2b2b464e6..232910aed 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -320,7 +320,7 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty func (m *Miner) computeTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) { - vrfBase := gen.TicketHash(base.ts.MinTicket(), addr) + vrfBase := base.ts.MinTicket().VRFProof vrfOut, err := m.computeVRF(ctx, addr, vrfBase) if err != nil { diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index ee60af8b0..6fbc0ccfc 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -4,12 +4,13 @@ import ( "context" "encoding/json" "fmt" - "golang.org/x/xerrors" "io" "io/ioutil" "os" "time" + "golang.org/x/xerrors" + "github.com/ipfs/go-blockservice" "github.com/ipfs/go-car" "github.com/ipfs/go-cid" @@ -29,22 +30,25 @@ import ( var glog = logging.Logger("genesis") -func MakeGenesisMem(out io.Writer, minerPid peer.ID) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { +func MakeGenesisMem(out io.Writer, gmc *gen.GenMinerCfg) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func() (*types.BlockHeader, error) { glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") - // TODO: make an address allocation - w, err := w.GenerateKey(types.KTBLS) + defk, err := w.GenerateKey(types.KTBLS) if err != nil { return nil, err } - gmc := &gen.GenMinerCfg{ - PeerIDs: []peer.ID{minerPid}, - // TODO: Call seal.PreSeal - } alloc := map[address.Address]types.BigInt{ - w: types.FromFil(10000), + defk: types.FromFil(1000), + } + + for _, genm := range gmc.PreSeals { + waddr, err := w.Import(&genm.Key) + if err != nil { + return nil, err + } + alloc[waddr] = types.FromFil(10000) } b, err := gen.MakeGenesisBlock(bs, alloc, gmc, 100000) diff --git a/node/node_test.go b/node/node_test.go index a1ee38c75..552a7bf00 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/rand" + "io/ioutil" "net/http/httptest" "testing" @@ -19,7 +20,10 @@ import ( "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" + "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/lib/jsonrpc" "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node" @@ -87,7 +91,9 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a node.Override(new(api.FullNode), tnd), ) - require.NoError(t, err) + if err != nil { + t.Fatalf("failed to construct node: %v", err) + } /*// Bootstrap with full node remoteAddrs, err := tnd.NetAddrsListen(ctx) @@ -114,10 +120,38 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te var genbuf bytes.Buffer + if len(storage) != 1 { + panic("need more peer IDs") + } + // PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE + // TODO: would be great if there was a better way to fake the preseals + gmc := &gen.GenMinerCfg{ + PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs + PreSeals: map[string]genesis.GenesisMiner{}, + } + for i := 0; i < len(storage); i++ { + maddr, err := address.NewIDAddress(300 + uint64(i)) + if err != nil { + t.Fatal(err) + } + tdir, err := ioutil.TempDir("", "preseal-memgen") + if err != nil { + t.Fatal(err) + } + genm, err := seed.PreSeal(maddr, 1024, 1, tdir, []byte("make genesis mem random")) + if err != nil { + t.Fatal(err) + } + gmc.MinerAddrs = append(gmc.MinerAddrs, maddr) + gmc.PreSeals[maddr.String()] = *genm + } + + // END PRESEAL SECTION + for i := 0; i < nFull; i++ { var genesis node.Option if i == 0 { - genesis = node.Override(new(modules.Genesis), modtest.MakeGenesisMem(&genbuf, minerPid)) + genesis = node.Override(new(modules.Genesis), modtest.MakeGenesisMem(&genbuf, gmc)) } else { genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genbuf.Bytes())) } @@ -165,7 +199,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te wa, err := f.WalletDefaultAddress(ctx) require.NoError(t, err) - genMiner, err := address.NewFromString("t0101") + genMiner, err := address.NewFromString("t0102") require.NoError(t, err) storers[i] = testStorageNode(ctx, t, wa, genMiner, pk, f, mn) From 81038b6a19aad6198e4dc564fbb59fcb709a33da Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 29 Nov 2019 22:43:53 -0600 Subject: [PATCH 51/93] fix the peer ID count check --- build/paramfetch.go | 3 --- node/node_test.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build/paramfetch.go b/build/paramfetch.go index f6f07cf06..b167f1ca5 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -54,9 +54,6 @@ func GetParams(storage bool, tests bool) error { ft := &fetch{} for name, info := range params { - if info.SectorSize != 1024 { - continue - } if !(SupportedSectorSize(info.SectorSize) || (tests && info.SectorSize == 1<<10)) { continue } diff --git a/node/node_test.go b/node/node_test.go index 552a7bf00..7c9de9365 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -120,7 +120,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te var genbuf bytes.Buffer - if len(storage) != 1 { + if len(storage) > 1 { panic("need more peer IDs") } // PRESEAL SECTION, TRY TO REPLACE WITH BETTER IN THE FUTURE From 2cbe14b234d365b7c8d30f109d0acd1a4f065dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 30 Nov 2019 09:21:01 +0100 Subject: [PATCH 52/93] make: build-all target --- .circleci/config.yml | 10 ++++++++++ .gitignore | 3 +++ Makefile | 43 ++++++++++++++++++++++++++++++------------- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 10f5cd782..827c9f77b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,6 +46,15 @@ jobs: - go/mod-download - go/mod-tidy-check + build-all: + executor: golang + steps: + - install-deps + - prepare + - go/mod-download + - run: + command: make buildall + test: description: | Run tests with gotestsum. @@ -166,3 +175,4 @@ workflows: - test: codecov-upload: true - mod-tidy-check + - build-all \ No newline at end of file diff --git a/.gitignore b/.gitignore index c54df6a7a..6ecfc0076 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ /pond /townhall /fountain +/stats +/bench +/bench.json /lotuspond/front/node_modules /lotuspond/front/build /cmd/lotus-townhall/townhall/node_modules diff --git a/Makefile b/Makefile index 7f1630fef..fadb68129 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ build/.update-modules: # end git modules -## PROOFS +## MAIN BINARIES CLEAN+=build/.update-modules @@ -53,7 +53,7 @@ lotus: $(BUILD_DEPS) go run github.com/GeertJohan/go.rice/rice append --exec lotus -i ./build .PHONY: lotus -CLEAN+=lotus +BINS+=lotus lotus-storage-miner: $(BUILD_DEPS) rm -f lotus-storage-miner @@ -61,6 +61,16 @@ lotus-storage-miner: $(BUILD_DEPS) go run github.com/GeertJohan/go.rice/rice append --exec lotus-storage-miner -i ./build .PHONY: lotus-storage-miner +BINS+=lotus-storage-miner + +build: lotus lotus-storage-miner +.PHONY: build + +install: + install -C ./lotus /usr/local/bin/lotus + install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner + +# TOOLS lotus-seed: $(BUILD_DEPS) rm -f lotus-seed @@ -68,16 +78,7 @@ lotus-seed: $(BUILD_DEPS) go run github.com/GeertJohan/go.rice/rice append --exec lotus-seed -i ./build .PHONY: lotus-seed - -CLEAN+=lotus-storage-miner - -build: lotus lotus-storage-miner - -.PHONY: build - -install: - install -C ./lotus /usr/local/bin/lotus - install -C ./lotus-storage-miner /usr/local/bin/lotus-storage-miner +BINS+=lotus-seed benchmarks: go run github.com/whyrusleeping/bencher ./... > bench.json @@ -89,6 +90,7 @@ pond: build go build -o pond ./lotuspond (cd lotuspond/front && npm i && npm run build) .PHONY: pond +BINS+=pond townhall: rm -f townhall @@ -96,26 +98,41 @@ townhall: (cd ./cmd/lotus-townhall/townhall && npm i && npm run build) go run github.com/GeertJohan/go.rice/rice append --exec townhall -i ./cmd/lotus-townhall -i ./build .PHONY: townhall +BINS+=townhall fountain: rm -f fountain go build -o fountain ./cmd/lotus-fountain go run github.com/GeertJohan/go.rice/rice append --exec fountain -i ./cmd/lotus-fountain .PHONY: fountain +BINS+=fountain chainwatch: rm -f chainwatch go build -o chainwatch ./cmd/lotus-chainwatch go run github.com/GeertJohan/go.rice/rice append --exec chainwatch -i ./cmd/lotus-chainwatch .PHONY: chainwatch +BINS+=chainwatch + +bench: + rm -f bench + go build -o bench ./cmd/lotus-bench + go run github.com/GeertJohan/go.rice/rice append --exec bench -i ./build +.PHONY: bench +BINS+=bench stats: rm -f stats go build -o stats ./tools/stats .PHONY: stats +BINS+=stats + +# MISC + +buildall: $(BINS) clean: - rm -rf $(CLEAN) + rm -rf $(CLEAN) $(BINS) -$(MAKE) -C $(FFI_PATH) clean .PHONY: clean From 82c7818b843d4a70f3981484292c4d04caa0f6af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 30 Nov 2019 09:22:57 +0100 Subject: [PATCH 53/93] mod tidy --- go.sum | 7 ------- 1 file changed, 7 deletions(-) diff --git a/go.sum b/go.sum index c376e7bba..446993d13 100644 --- a/go.sum +++ b/go.sum @@ -82,7 +82,6 @@ github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7 h1:lK github.com/filecoin-project/go-amt-ipld v0.0.0-20191122035745-59b9dfc0efc7/go.mod h1:lKjJYPg2kwbav5f78i5YA8kGccnZn18IySbpneXvaQs= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug= github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8= -github.com/filecoin-project/go-sectorbuilder v0.0.0-20191125152826-0aeff9f9485d/go.mod h1:NulUuak/mLUOIX+p5p6E9fCaR9VekiU1wpTgUB+DPgw= 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= @@ -438,8 +437,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -668,8 +665,6 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -701,8 +696,6 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= From 6b4fcc0090720e1d9dcc2b3666d183e93d9dbdb8 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sat, 30 Nov 2019 11:02:25 -0600 Subject: [PATCH 54/93] progressively getting closer to fixing tests --- chain/store/weight.go | 1 - node/node_test.go | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/chain/store/weight.go b/chain/store/weight.go index 72811ebec..901356728 100644 --- a/chain/store/weight.go +++ b/chain/store/weight.go @@ -40,7 +40,6 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn log2P = int64(tpow.BitLen() - 1) } else { // Not really expect to be here ... - panic("where are we") return types.EmptyInt, xerrors.Errorf("All power in the net is gone. You network might be disconnected, or the net is dead!") } diff --git a/node/node_test.go b/node/node_test.go index 7c9de9365..b78d1e79c 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -199,8 +199,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te wa, err := f.WalletDefaultAddress(ctx) require.NoError(t, err) - genMiner, err := address.NewFromString("t0102") - require.NoError(t, err) + genMiner := gmc.MinerAddrs[i] storers[i] = testStorageNode(ctx, t, wa, genMiner, pk, f, mn) } From d5f78d66590662d0090d7d7c53690b8f7532b2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 30 Nov 2019 23:22:26 +0100 Subject: [PATCH 55/93] more verbose logging in node tests --- chain/gen/utils.go | 4 ++++ node/node_test.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index e16a78813..b43815783 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -255,6 +255,10 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid return cid.Undef, nil, xerrors.Errorf("failed to create NewVM: %w", err) } + if len(gmcfg.MinerAddrs) == 0 { + return cid.Undef, nil, xerrors.New("no genesis miners") + } + if len(gmcfg.MinerAddrs) != len(gmcfg.PreSeals) { return cid.Undef, nil, xerrors.Errorf("miner address list, and preseal count doesn't match (%d != %d)", len(gmcfg.MinerAddrs), len(gmcfg.PreSeals)) } diff --git a/node/node_test.go b/node/node_test.go index b78d1e79c..399eff559 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -11,6 +11,7 @@ import ( "github.com/libp2p/go-libp2p-core/crypto" "github.com/ipfs/go-datastore" + logging "github.com/ipfs/go-log" "github.com/libp2p/go-libp2p-core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" "github.com/stretchr/testify/require" @@ -32,6 +33,10 @@ import ( "github.com/filecoin-project/lotus/node/repo" ) +func init() { + logging.SetLogLevel("*", "INFO") +} + func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, pk crypto.PrivKey, tnd test.TestNode, mn mocknet.Mocknet) test.TestStorageNode { r := repo.NewMemory(nil) From 59d9c681add118f28e4e9003287df73dc8c205ed Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sat, 30 Nov 2019 17:17:50 -0600 Subject: [PATCH 56/93] Rework miner test setups to fix tests --- api/test/deals.go | 12 ++++-- api/test/mining.go | 4 +- api/test/test.go | 10 ++--- build/paramfetch.go | 3 ++ chain/gen/gen.go | 1 - cmd/lotus-seed/main.go | 4 +- cmd/lotus-seed/seed/seed.go | 8 +++- cmd/lotus-storage-miner/init.go | 68 ++++++++++-------------------- lib/sectorbuilder/sectorbuilder.go | 51 ++++++++++++++++++++++ miner/miner.go | 1 + miner/testminer.go | 14 ++++-- node/node_test.go | 64 ++++++++++++++++++++-------- node/repo/interface.go | 2 +- storage/miner.go | 5 +++ 14 files changed, 164 insertions(+), 83 deletions(-) diff --git a/api/test/deals.go b/api/test/deals.go index 8dbde5a78..62830c382 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -12,15 +12,19 @@ import ( logging "github.com/ipfs/go-log" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/impl" ) +func init() { + logging.SetAllLoggers(logging.LevelInfo) + build.InsecurePoStValidation = true +} + func TestDealFlow(t *testing.T, b APIBuilder) { os.Setenv("BELLMAN_NO_GPU", "1") - logging.SetAllLoggers(logging.LevelInfo) ctx := context.Background() n, sn := b(t, 1, []int{0}) client := n[0].FullNode.(*impl.FullNodeAPI) @@ -42,7 +46,7 @@ func TestDealFlow(t *testing.T, b APIBuilder) { t.Fatal(err) } - maddr, err := address.NewFromString("t0102") + maddr, err := miner.ActorAddress(ctx) if err != nil { t.Fatal(err) } @@ -57,7 +61,7 @@ func TestDealFlow(t *testing.T, b APIBuilder) { for mine { time.Sleep(time.Second) fmt.Println("mining a block now") - if err := n[0].MineOne(ctx); err != nil { + if err := sn[0].MineOne(ctx); err != nil { t.Fatal(err) } } diff --git a/api/test/mining.go b/api/test/mining.go index 7e7f639c1..77f4ec6c3 100644 --- a/api/test/mining.go +++ b/api/test/mining.go @@ -9,7 +9,7 @@ import ( func (ts *testSuite) testMining(t *testing.T) { ctx := context.Background() - apis, _ := ts.makeNodes(t, 1, []int{0}) + apis, sn := ts.makeNodes(t, 1, []int{0}) api := apis[0] h1, err := api.ChainHead(ctx) @@ -20,7 +20,7 @@ func (ts *testSuite) testMining(t *testing.T) { require.NoError(t, err) <-newHeads - err = api.MineOne(ctx) + err = sn[0].MineOne(ctx) require.NoError(t, err) <-newHeads diff --git a/api/test/test.go b/api/test/test.go index 1e369fa8c..8ade6d981 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -11,12 +11,12 @@ import ( type TestNode struct { api.FullNode - - MineOne func(context.Context) error } type TestStorageNode struct { api.StorageMiner + + MineOne func(context.Context) error } // APIBuilder is a function which is invoked in test suite to provide @@ -43,7 +43,7 @@ func TestApis(t *testing.T, b APIBuilder) { func (ts *testSuite) testVersion(t *testing.T) { ctx := context.Background() - apis, _ := ts.makeNodes(t, 1, []int{}) + apis, _ := ts.makeNodes(t, 1, []int{0}) api := apis[0] v, err := api.Version(ctx) @@ -57,7 +57,7 @@ func (ts *testSuite) testVersion(t *testing.T) { func (ts *testSuite) testID(t *testing.T) { ctx := context.Background() - apis, _ := ts.makeNodes(t, 1, []int{}) + apis, _ := ts.makeNodes(t, 1, []int{0}) api := apis[0] id, err := api.ID(ctx) @@ -69,7 +69,7 @@ func (ts *testSuite) testID(t *testing.T) { func (ts *testSuite) testConnectTwo(t *testing.T) { ctx := context.Background() - apis, _ := ts.makeNodes(t, 2, []int{}) + apis, _ := ts.makeNodes(t, 2, []int{0}) p, err := apis[0].NetPeers(ctx) if err != nil { diff --git a/build/paramfetch.go b/build/paramfetch.go index b167f1ca5..f6f07cf06 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -54,6 +54,9 @@ func GetParams(storage bool, tests bool) error { ft := &fetch{} for name, info := range params { + if info.SectorSize != 1024 { + continue + } if !(SupportedSectorSize(info.SectorSize) || (tests && info.SectorSize == 1<<10)) { continue } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 35891f000..ca201bf9e 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -614,7 +614,6 @@ func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Addres if err != nil { return nil, err } - log.Warnf("making ticket: %x %s %s %x %x", sig.Data, worker, miner, input, sigInput) if sig.Type != types.KTBLS { return nil, fmt.Errorf("miner worker address was not a BLS key") diff --git a/cmd/lotus-seed/main.go b/cmd/lotus-seed/main.go index cebe71f32..d3e9eb4e5 100644 --- a/cmd/lotus-seed/main.go +++ b/cmd/lotus-seed/main.go @@ -61,7 +61,7 @@ var preSealCmd = &cli.Command{ Value: "lotus is fire", Usage: "set the ticket preimage for sealing randomness", }, - &cli.Uint64Flag{ + &cli.IntFlag{ Name: "num-sectors", Value: 1, Usage: "select number of sectors to pre-seal", @@ -79,7 +79,7 @@ var preSealCmd = &cli.Command{ return err } - gm, err := seed.PreSeal(maddr, c.Uint64("sector-size"), c.Uint64("num-sectors"), sbroot, []byte(c.String("ticket-preimage"))) + gm, err := seed.PreSeal(maddr, c.Uint64("sector-size"), c.Int("num-sectors"), sbroot, []byte(c.String("ticket-preimage"))) if err != nil { return err } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index f1c2cbbc9..670c55056 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -11,6 +11,7 @@ import ( "path/filepath" badger "github.com/ipfs/go-ds-badger" + logging "github.com/ipfs/go-log" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" @@ -23,7 +24,9 @@ import ( "github.com/filecoin-project/lotus/lib/sectorbuilder" ) -func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, preimage []byte) (*genesis.GenesisMiner, error) { +var log = logging.Logger("preseal") + +func PreSeal(maddr address.Address, ssize uint64, sectors int, sbroot string, preimage []byte) (*genesis.GenesisMiner, error) { cfg := §orbuilder.Config{ Miner: maddr, SectorSize: ssize, @@ -58,7 +61,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, size := sectorbuilder.UserBytesForSectorSize(ssize) var sealedSectors []*genesis.PreSeal - for i := uint64(1); i <= sectors; i++ { + for i := 0; i < sectors; i++ { sid, err := sb.AcquireSectorId() if err != nil { return nil, err @@ -81,6 +84,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors uint64, sbroot string, return nil, xerrors.Errorf("commit: %w", err) } + log.Warn("PreCommitOutput: ", sid, pco) sealedSectors = append(sealedSectors, &genesis.PreSeal{ CommR: pco.CommR, CommD: pco.CommD, diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index de1164cb5..17089983f 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -133,7 +133,28 @@ var initCmd = &cli.Command{ return err } - if err := migratePreSealedSectors(pssb, repoPath, mds); err != nil { + oldmds, err := badger.NewDatastore(filepath.Join(pssb, "badger"), nil) + if err != nil { + return err + } + + oldsb, err := sectorbuilder.New(§orbuilder.Config{ + SectorSize: 1024, + SealedDir: filepath.Join(pssb, "sealed"), + CacheDir: filepath.Join(pssb, "cache"), + StagedDir: filepath.Join(pssb, "staging"), + MetadataDir: filepath.Join(pssb, "meta"), + }, oldmds) + + nsb, err := sectorbuilder.New(§orbuilder.Config{ + SectorSize: 1024, + SealedDir: filepath.Join(lr.Path(), "sealed"), + CacheDir: filepath.Join(lr.Path(), "cache"), + StagedDir: filepath.Join(lr.Path(), "staging"), + MetadataDir: filepath.Join(lr.Path(), "meta"), + }, mds) + + if err := nsb.ImportFrom(oldsb); err != nil { return err } if err := lr.Close(); err != nil { @@ -161,51 +182,6 @@ var initCmd = &cli.Command{ }, } -// TODO: this method should be a lot more robust for mainnet. For testnet, its -// fine if we mess things up a few times -// Also probably makes sense for this method to be in the sectorbuilder package -func migratePreSealedSectors(presealsb string, repoPath string, mds dtypes.MetadataDS) error { - pspath, err := homedir.Expand(presealsb) - if err != nil { - return err - } - - srcds, err := badger.NewDatastore(filepath.Join(pspath, "badger"), nil) - if err != nil { - return xerrors.Errorf("openning presealed sectors datastore: %w", err) - } - - expRepo, err := homedir.Expand(repoPath) - if err != nil { - return err - } - - if stat, err := os.Stat(pspath); err != nil { - return xerrors.Errorf("failed to stat presealed sectors directory: %w", err) - } else if !stat.IsDir() { - return xerrors.Errorf("given presealed sectors path was not a directory: %w", err) - } - - for _, dir := range []string{"meta", "sealed", "staging", "cache"} { - from := filepath.Join(pspath, dir) - to := filepath.Join(expRepo, dir) - if err := os.Rename(from, to); err != nil { - return err - } - } - - val, err := srcds.Get(sectorbuilder.LastSectorIdKey) - if err != nil { - return xerrors.Errorf("getting source last sector ID: %w", err) - } - - if err := mds.Put(sectorbuilder.LastSectorIdKey, val); err != nil { - return xerrors.Errorf("failed to write last sector ID key to target datastore: %w", err) - } - - return nil -} - func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir string, maddr address.Address, mds dtypes.MetadataDS) error { b, err := ioutil.ReadFile(filepath.Join(presealDir, "pre-seal-"+maddr.String()+".json")) if err != nil { diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index f953dea14..150d4f504 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strconv" "sync" @@ -100,6 +101,7 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { default: return nil, err } + log.Warn("STARTING UP SECTOR BULIDER, LAST ID: ", lastUsedID) sb := &SectorBuilder{ ds: ds, @@ -290,6 +292,9 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, } proverID := addressToProverID(sb.Miner) + log.Info("GENERATING ELECTION POST") + defer log.Info("DONE GENERATING ELECTION POST") + return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) } @@ -422,3 +427,49 @@ func fallbackPostChallengeCount(sectors uint64) uint64 { } return challengeCount } + +func (sb *SectorBuilder) ImportFrom(osb *SectorBuilder) error { + if err := moveAllFiles(osb.cacheDir, sb.cacheDir); err != nil { + return err + } + + if err := moveAllFiles(osb.sealedDir, sb.sealedDir); err != nil { + return err + } + + if err := moveAllFiles(osb.stagedDir, sb.stagedDir); err != nil { + return err + } + + val, err := osb.ds.Get(LastSectorIdKey) + if err != nil { + return err + } + + if err := sb.ds.Put(LastSectorIdKey, val); err != nil { + return err + } + + sb.lastID = osb.lastID + + return nil +} + +func moveAllFiles(from, to string) error { + dir, err := os.Open(from) + if err != nil { + return err + } + + names, err := dir.Readdirnames(0) + if err != nil { + return xerrors.Errorf("failed to list items in dir: %w", err) + } + for _, n := range names { + if err := os.Rename(filepath.Join(from, n), filepath.Join(to, n)); err != nil { + return xerrors.Errorf("moving file failed: %w", err) + } + } + + return nil +} diff --git a/miner/miner.go b/miner/miner.go index 232910aed..306a38ab8 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -119,6 +119,7 @@ func (m *Miner) Unregister(ctx context.Context, addr address.Address) error { } func (m *Miner) mine(ctx context.Context) { + log.Warn("Starting mining!!") ctx, span := trace.StartSpan(ctx, "/mine") defer span.End() diff --git a/miner/testminer.go b/miner/testminer.go index 48fbd92a6..594f2175e 100644 --- a/miner/testminer.go +++ b/miner/testminer.go @@ -4,14 +4,22 @@ import ( "context" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/gen" ) -func NewTestMiner(nextCh <-chan struct{}) func(api api.FullNode) *Miner { - return func(api api.FullNode) *Miner { - return &Miner{ +func NewTestMiner(nextCh <-chan struct{}, addr address.Address) func(api.FullNode, gen.ElectionPoStProver) *Miner { + return func(api api.FullNode, epp gen.ElectionPoStProver) *Miner { + m := &Miner{ api: api, waitFunc: chanWaiter(nextCh), + epp: epp, } + + if err := m.Register(addr); err != nil { + panic(err) + } + return m } } diff --git a/node/node_test.go b/node/node_test.go index 399eff559..f5760230b 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -6,11 +6,13 @@ import ( "crypto/rand" "io/ioutil" "net/http/httptest" + "path/filepath" "testing" "github.com/libp2p/go-libp2p-core/crypto" "github.com/ipfs/go-datastore" + badger "github.com/ipfs/go-ds-badger" logging "github.com/ipfs/go-log" "github.com/libp2p/go-libp2p-core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" @@ -26,8 +28,10 @@ import ( "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/lib/jsonrpc" + "github.com/filecoin-project/lotus/lib/sectorbuilder" "github.com/filecoin-project/lotus/miner" "github.com/filecoin-project/lotus/node" + "github.com/filecoin-project/lotus/node/impl" "github.com/filecoin-project/lotus/node/modules" modtest "github.com/filecoin-project/lotus/node/modules/testing" "github.com/filecoin-project/lotus/node/repo" @@ -85,6 +89,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a // start node var minerapi api.StorageMiner + mineBlock := make(chan struct{}) // TODO: use stop _, err = node.New(ctx, node.StorageMiner(&minerapi), @@ -95,6 +100,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a node.MockHost(mn), node.Override(new(api.FullNode), tnd), + node.Override(new(*miner.Miner), miner.NewTestMiner(mineBlock, act)), ) if err != nil { t.Fatalf("failed to construct node: %v", err) @@ -106,8 +112,16 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a err = minerapi.NetConnect(ctx, remoteAddrs) require.NoError(t, err)*/ + mineOne := func(ctx context.Context) error { + select { + case mineBlock <- struct{}{}: + return nil + case <-ctx.Done(): + return ctx.Err() + } + } - return test.TestStorageNode{minerapi} + return test.TestStorageNode{minerapi, mineOne} } func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.TestStorageNode) { @@ -134,6 +148,8 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te PeerIDs: []peer.ID{minerPid}, // TODO: if we have more miners, need more peer IDs PreSeals: map[string]genesis.GenesisMiner{}, } + + var presealDirs []string for i := 0; i < len(storage); i++ { maddr, err := address.NewIDAddress(300 + uint64(i)) if err != nil { @@ -147,6 +163,8 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te if err != nil { t.Fatal(err) } + + presealDirs = append(presealDirs, tdir) gmc.MinerAddrs = append(gmc.MinerAddrs, maddr) gmc.PreSeals[maddr.String()] = *genm } @@ -161,8 +179,6 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genbuf.Bytes())) } - mineBlock := make(chan struct{}) - var err error // TODO: Don't ignore stop _, err = node.New(ctx, @@ -172,22 +188,12 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te node.MockHost(mn), node.Test(), - node.Override(new(*miner.Miner), miner.NewTestMiner(mineBlock)), - genesis, ) if err != nil { t.Fatal(err) } - fulls[i].MineOne = func(ctx context.Context) error { - select { - case mineBlock <- struct{}{}: - return nil - case <-ctx.Done(): - return ctx.Err() - } - } } for i, full := range storage { @@ -201,12 +207,36 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te f := fulls[full] - wa, err := f.WalletDefaultAddress(ctx) - require.NoError(t, err) - genMiner := gmc.MinerAddrs[i] + wa := gmc.PreSeals[genMiner.String()].Worker storers[i] = testStorageNode(ctx, t, wa, genMiner, pk, f, mn) + + sma := storers[i].StorageMiner.(*impl.StorageMinerAPI) + + psd := presealDirs[i] + mds, err := badger.NewDatastore(filepath.Join(psd, "badger"), nil) + if err != nil { + t.Fatal(err) + } + + osb, err := sectorbuilder.New(§orbuilder.Config{ + SectorSize: 1024, + WorkerThreads: 2, + Miner: genMiner, + CacheDir: filepath.Join(psd, "cache"), + StagedDir: filepath.Join(psd, "staging"), + SealedDir: filepath.Join(psd, "sealed"), + MetadataDir: filepath.Join(psd, "meta"), + }, mds) + if err != nil { + t.Fatal(err) + } + + if err := sma.SectorBuilder.ImportFrom(osb); err != nil { + t.Fatal(err) + } + } if err := mn.LinkAll(); err != nil { @@ -235,7 +265,6 @@ func rpcBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test if err != nil { t.Fatal(err) } - fulls[i].MineOne = a.MineOne } for i, a := range storaApis { @@ -248,6 +277,7 @@ func rpcBuilder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test if err != nil { t.Fatal(err) } + storers[i].MineOne = a.MineOne } return fulls, storers diff --git a/node/repo/interface.go b/node/repo/interface.go index 9a7a3e3eb..b4c2b0950 100644 --- a/node/repo/interface.go +++ b/node/repo/interface.go @@ -47,6 +47,6 @@ type LockedRepo interface { // KeyStore returns store of private keys for Filecoin transactions KeyStore() (types.KeyStore, error) - // Path returns absolute path of the repo (or empty string if in-memory) + // Path returns absolute path of the repo Path() string } diff --git a/storage/miner.go b/storage/miner.go index f295504d8..3972e4e11 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -13,6 +13,7 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/gen" @@ -161,5 +162,9 @@ func (epp *sectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorb } func (epp *sectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { + if build.InsecurePoStValidation { + log.Warn("Generating fake EPost proof! You should only see this while running tests!") + return []byte("valid proof"), nil + } return epp.sb.ComputeElectionPoSt(ssi, rand, winners) } From 422e25c8e6c7375eee89a48b552270f0c2d63286 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sat, 30 Nov 2019 22:02:52 -0600 Subject: [PATCH 57/93] self review: some cleanup --- build/paramfetch.go | 3 --- chain/gen/gen.go | 11 ++--------- chain/sync.go | 1 - lib/sectorbuilder/sectorbuilder.go | 21 +++++---------------- miner/miner.go | 1 - 5 files changed, 7 insertions(+), 30 deletions(-) diff --git a/build/paramfetch.go b/build/paramfetch.go index f6f07cf06..b167f1ca5 100644 --- a/build/paramfetch.go +++ b/build/paramfetch.go @@ -54,9 +54,6 @@ func GetParams(storage bool, tests bool) error { ft := &fetch{} for name, info := range params { - if info.SectorSize != 1024 { - continue - } if !(SupportedSectorSize(info.SectorSize) || (tests && info.SectorSize == 1<<10)) { continue } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index ca201bf9e..a96b167e0 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -61,7 +61,6 @@ type ChainGen struct { eppProvs map[address.Address]ElectionPoStProver Miners []address.Address - mworkers []address.Address receivers []address.Address banker address.Address bankerNonce uint64 @@ -125,8 +124,6 @@ func NewGenerator() (*ChainGen, error) { } } - // TODO: this is really weird, we have to guess the miner addresses that - // will be created in order to preseal data for them maddr1, err := address.NewFromString("t0300") if err != nil { return nil, err @@ -212,9 +209,8 @@ func NewGenerator() (*ChainGen, error) { genesis: genb.Genesis, w: w, - Miners: minercfg.MinerAddrs, - eppProvs: mgen, - //mworkers: minercfg.Workers, + Miners: minercfg.MinerAddrs, + eppProvs: mgen, banker: banker, receivers: receievers, @@ -256,7 +252,6 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add return nil, nil, xerrors.Errorf("get miner worker: %w", err) } - log.Warnf("compute VRF ROUND: %d %s %s", round, m, worker) vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, m, DSepTicket, lastTicket.VRFProof) if err != nil { return nil, nil, xerrors.Errorf("compute VRF: %w", err) @@ -308,7 +303,6 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad } if proof != nil { - log.Warn("making block, ticket: ", t.VRFProof) fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs) if err != nil { return nil, xerrors.Errorf("making a block for next tipset failed: %w", err) @@ -510,7 +504,6 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add sectors := sectorbuilder.NewSortedPublicSectorInfo(sinfos) hvrf := sha256.Sum256(vrfout) - log.Info("Replicas: ", sectors) candidates, err := epp.GenerateCandidates(ctx, sectors, hvrf[:]) if err != nil { return false, nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) diff --git a/chain/sync.go b/chain/sync.go index 2519ab71c..c6e8f17a5 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -620,7 +620,6 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err err := gen.VerifyVRF(ctx, waddr, h.Miner, gen.DSepTicket, vrfBase, h.Ticket.VRFProof) if err != nil { - log.Warnf("BAD TICKET: %d %x %x %s %s %x", h.Height, h.Ticket.VRFProof, vrfBase, waddr, h.Miner, baseTs.MinTicket().VRFProof) return xerrors.Errorf("validating block tickets failed: %w", err) } return nil diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 150d4f504..509b28f32 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -23,7 +23,7 @@ import ( const PoStReservedWorkers = 1 const PoRepProofPartitions = 2 -var LastSectorIdKey = datastore.NewKey("/sectorbuilder/last") +var lastSectorIdKey = datastore.NewKey("/sectorbuilder/last") var log = logging.Logger("sectorbuilder") @@ -89,7 +89,7 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { } var lastUsedID uint64 - b, err := ds.Get(LastSectorIdKey) + b, err := ds.Get(lastSectorIdKey) switch err { case nil: i, err := strconv.ParseInt(string(b), 10, 64) @@ -101,7 +101,6 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { default: return nil, err } - log.Warn("STARTING UP SECTOR BULIDER, LAST ID: ", lastUsedID) sb := &SectorBuilder{ ds: ds, @@ -148,7 +147,7 @@ func (sb *SectorBuilder) AcquireSectorId() (uint64, error) { sb.lastID++ id := sb.lastID - err := sb.ds.Put(LastSectorIdKey, []byte(fmt.Sprint(id))) + err := sb.ds.Put(lastSectorIdKey, []byte(fmt.Sprint(id))) if err != nil { return 0, err } @@ -267,14 +266,6 @@ func (sb *SectorBuilder) SealCommit(sectorID uint64, ticket SealTicket, seed Sea return proof, nil } -/* -func (sb *SectorBuilder) GeneratePoSt(sectorInfo SortedSectorInfo, challengeSeed [CommLen]byte, faults []uint64) ([]byte, error) { - // Wait, this is a blocking method with no way of interrupting it? - // does it checkpoint itself? - return sectorbuilder.GeneratePoSt(sb.handle, sectorInfo, challengeSeed, faults) -} -*/ - func (sb *SectorBuilder) SectorSize() uint64 { return sb.ssize } @@ -292,8 +283,6 @@ func (sb *SectorBuilder) ComputeElectionPoSt(sectorInfo SortedPublicSectorInfo, } proverID := addressToProverID(sb.Miner) - log.Info("GENERATING ELECTION POST") - defer log.Info("DONE GENERATING ELECTION POST") return sectorbuilder.GeneratePoSt(sb.ssize, proverID, privsects, cseed, winners) } @@ -441,12 +430,12 @@ func (sb *SectorBuilder) ImportFrom(osb *SectorBuilder) error { return err } - val, err := osb.ds.Get(LastSectorIdKey) + val, err := osb.ds.Get(lastSectorIdKey) if err != nil { return err } - if err := sb.ds.Put(LastSectorIdKey, val); err != nil { + if err := sb.ds.Put(lastSectorIdKey, val); err != nil { return err } diff --git a/miner/miner.go b/miner/miner.go index 306a38ab8..232910aed 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -119,7 +119,6 @@ func (m *Miner) Unregister(ctx context.Context, addr address.Address) error { } func (m *Miner) mine(ctx context.Context) { - log.Warn("Starting mining!!") ctx, span := trace.StartSpan(ctx, "/mine") defer span.End() From c92b9d5a0d0f44276053142bf7ab01d87fb264bb Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sat, 30 Nov 2019 23:55:20 -0600 Subject: [PATCH 58/93] fix storage miner sectorbuilder construction --- cmd/lotus-storage-miner/init.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 17089983f..b3b65ce5f 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -139,20 +139,28 @@ var initCmd = &cli.Command{ } oldsb, err := sectorbuilder.New(§orbuilder.Config{ - SectorSize: 1024, - SealedDir: filepath.Join(pssb, "sealed"), - CacheDir: filepath.Join(pssb, "cache"), - StagedDir: filepath.Join(pssb, "staging"), - MetadataDir: filepath.Join(pssb, "meta"), + SectorSize: 1024, + WorkerThreads: 2, + SealedDir: filepath.Join(pssb, "sealed"), + CacheDir: filepath.Join(pssb, "cache"), + StagedDir: filepath.Join(pssb, "staging"), + MetadataDir: filepath.Join(pssb, "meta"), }, oldmds) + if err != nil { + return xerrors.Errorf("failed to open up preseal sectorbuilder: %w", err) + } nsb, err := sectorbuilder.New(§orbuilder.Config{ - SectorSize: 1024, - SealedDir: filepath.Join(lr.Path(), "sealed"), - CacheDir: filepath.Join(lr.Path(), "cache"), - StagedDir: filepath.Join(lr.Path(), "staging"), - MetadataDir: filepath.Join(lr.Path(), "meta"), + SectorSize: 1024, + WorkerThreads: 2, + SealedDir: filepath.Join(lr.Path(), "sealed"), + CacheDir: filepath.Join(lr.Path(), "cache"), + StagedDir: filepath.Join(lr.Path(), "staging"), + MetadataDir: filepath.Join(lr.Path(), "meta"), }, mds) + if err != nil { + return xerrors.Errorf("failed to open up sectorbuilder: %w", err) + } if err := nsb.ImportFrom(oldsb); err != nil { return err From a59d0f0f8c73bff06196058f8509626b232a43fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 18:58:31 +0100 Subject: [PATCH 59/93] Fix unsealing, sector based data refs --- api/api_storage.go | 6 +- api/cbor_gen.go | 23 +++---- chain/blocksync/cbor_gen.go | 2 +- chain/deals/provider_states.go | 2 +- chain/types/cbor_gen.go | 2 +- cmd/lotus-seed/seed/seed.go | 4 +- cmd/lotus-storage-miner/init.go | 5 +- cmd/lotus-storage-miner/sectors.go | 2 +- lib/sectorbuilder/files.go | 4 ++ lib/sectorbuilder/mock.go | 4 +- lib/sectorbuilder/sectorbuilder.go | 82 ++++++++++++++++++++++--- node/modules/storageminer.go | 4 +- storage/cbor_gen.go | 22 +------ storage/garbage.go | 5 +- storage/sealing.go | 40 ++++++------ storage/sectorblocks/blocks.go | 48 +++++++-------- storage/sectorblocks/blockstore.go | 25 +++++++- storage/sectorblocks/unsealed.go | 99 ------------------------------ 18 files changed, 171 insertions(+), 208 deletions(-) delete mode 100644 storage/sectorblocks/unsealed.go diff --git a/api/api_storage.go b/api/api_storage.go index 299449662..880259dd6 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -86,9 +86,9 @@ type SectorInfo struct { } type SealedRef struct { - Piece string - Offset uint64 - Size uint64 + SectorID uint64 + Offset uint64 + Size uint64 } type SealedRefs struct { diff --git a/api/cbor_gen.go b/api/cbor_gen.go index 0f968865b..0cd224876 100644 --- a/api/cbor_gen.go +++ b/api/cbor_gen.go @@ -137,11 +137,8 @@ func (t *SealedRef) MarshalCBOR(w io.Writer) error { return err } - // t.t.Piece (string) (string) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Piece)))); err != nil { - return err - } - if _, err := w.Write([]byte(t.Piece)); err != nil { + // t.t.SectorID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil { return err } @@ -172,16 +169,16 @@ func (t *SealedRef) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.t.Piece (string) (string) + // t.t.SectorID (uint64) (uint64) - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - t.Piece = string(sval) + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.SectorID = uint64(extra) // t.t.Offset (uint64) (uint64) maj, extra, err = cbg.CborReadHeader(br) diff --git a/chain/blocksync/cbor_gen.go b/chain/blocksync/cbor_gen.go index 4af61a490..579b3f857 100644 --- a/chain/blocksync/cbor_gen.go +++ b/chain/blocksync/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "github.com/filecoin-project/lotus/chain/types" - "github.com/ipfs/go-cid" + cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/chain/deals/provider_states.go b/chain/deals/provider_states.go index 0cfe86e00..ca66cdedb 100644 --- a/chain/deals/provider_states.go +++ b/chain/deals/provider_states.go @@ -204,7 +204,7 @@ func (p *Provider) staged(ctx context.Context, deal MinerDeal) (func(*MinerDeal) return nil, xerrors.Errorf("deal.Proposal.PieceSize didn't match padded unixfs file size") } - sectorID, err := p.secb.AddUnixfsPiece(ctx, deal.Ref, uf, deal.DealID) + sectorID, err := p.secb.AddUnixfsPiece(ctx, uf, deal.DealID) if err != nil { return nil, xerrors.Errorf("AddPiece failed: %s", err) } diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index d2b60f268..fc7a7888c 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "math" - "github.com/ipfs/go-cid" + cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 670c55056..c3c92c07c 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -33,11 +33,11 @@ func PreSeal(maddr address.Address, ssize uint64, sectors int, sbroot string, pr CacheDir: filepath.Join(sbroot, "cache"), SealedDir: filepath.Join(sbroot, "sealed"), StagedDir: filepath.Join(sbroot, "staging"), - MetadataDir: filepath.Join(sbroot, "meta"), + UnsealedDir: filepath.Join(sbroot, "unsealed"), WorkerThreads: 2, } - for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { + for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.UnsealedDir} { if err := os.MkdirAll(d, 0775); err != nil { return nil, err } diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index b3b65ce5f..4ee3ae7f2 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -144,7 +144,7 @@ var initCmd = &cli.Command{ SealedDir: filepath.Join(pssb, "sealed"), CacheDir: filepath.Join(pssb, "cache"), StagedDir: filepath.Join(pssb, "staging"), - MetadataDir: filepath.Join(pssb, "meta"), + UnsealedDir: filepath.Join(pssb, "unsealed"), }, oldmds) if err != nil { return xerrors.Errorf("failed to open up preseal sectorbuilder: %w", err) @@ -156,7 +156,7 @@ var initCmd = &cli.Command{ SealedDir: filepath.Join(lr.Path(), "sealed"), CacheDir: filepath.Join(lr.Path(), "cache"), StagedDir: filepath.Join(lr.Path(), "staging"), - MetadataDir: filepath.Join(lr.Path(), "meta"), + UnsealedDir: filepath.Join(lr.Path(), "unsealed"), }, mds) if err != nil { return xerrors.Errorf("failed to open up sectorbuilder: %w", err) @@ -221,7 +221,6 @@ func migratePreSealMeta(ctx context.Context, api lapi.FullNode, presealDir strin Pieces: []storage.Piece{ { DealID: dealID, - Ref: fmt.Sprintf("preseal-%d", sector.SectorID), Size: meta.SectorSize, CommP: sector.CommD[:], }, diff --git a/cmd/lotus-storage-miner/sectors.go b/cmd/lotus-storage-miner/sectors.go index b1794f393..d5ee85d00 100644 --- a/cmd/lotus-storage-miner/sectors.go +++ b/cmd/lotus-storage-miner/sectors.go @@ -163,7 +163,7 @@ var sectorsRefsCmd = &cli.Command{ for name, refs := range refs { fmt.Printf("Block %s:\n", name) for _, ref := range refs { - fmt.Printf("\t%s+%d %d bytes\n", ref.Piece, ref.Offset, ref.Size) + fmt.Printf("\t%d+%d %d bytes\n", ref.SectorID, ref.Offset, ref.Size) } } return nil diff --git a/lib/sectorbuilder/files.go b/lib/sectorbuilder/files.go index 51b748f50..b23f2a5c8 100644 --- a/lib/sectorbuilder/files.go +++ b/lib/sectorbuilder/files.go @@ -18,6 +18,10 @@ func (sb *SectorBuilder) stagedSectorPath(sectorID uint64) string { return filepath.Join(sb.stagedDir, sb.sectorName(sectorID)) } +func (sb *SectorBuilder) unsealedSectorPath(sectorID uint64) string { + return filepath.Join(sb.unsealedDir, sb.sectorName(sectorID)) +} + func (sb *SectorBuilder) stagedSectorFile(sectorID uint64) (*os.File, error) { return os.OpenFile(sb.stagedSectorPath(sectorID), os.O_RDWR|os.O_CREATE, 0644) } diff --git a/lib/sectorbuilder/mock.go b/lib/sectorbuilder/mock.go index de2009b46..ee38f4265 100644 --- a/lib/sectorbuilder/mock.go +++ b/lib/sectorbuilder/mock.go @@ -29,7 +29,7 @@ func TempSectorbuilderDir(dir string, sectorSize uint64, ds dtypes.MetadataDS) ( return nil, err } - metadata := filepath.Join(dir, "meta") + unsealed := filepath.Join(dir, "unsealed") sealed := filepath.Join(dir, "sealed") staging := filepath.Join(dir, "staging") cache := filepath.Join(dir, "cache") @@ -39,7 +39,7 @@ func TempSectorbuilderDir(dir string, sectorSize uint64, ds dtypes.MetadataDS) ( SealedDir: sealed, StagedDir: staging, - MetadataDir: metadata, + UnsealedDir: unsealed, CacheDir: cache, WorkerThreads: 2, diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 509b28f32..5a3312f5e 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -55,9 +55,12 @@ type SectorBuilder struct { Miner address.Address - stagedDir string - sealedDir string - cacheDir string + stagedDir string + sealedDir string + cacheDir string + unsealedDir string + + unsealLk sync.Mutex rateLimit chan struct{} } @@ -71,7 +74,7 @@ type Config struct { CacheDir string SealedDir string StagedDir string - MetadataDir string + UnsealedDir string } func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { @@ -79,7 +82,7 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { return nil, xerrors.Errorf("minimum worker threads is %d, specified %d", PoStReservedWorkers+1, cfg.WorkerThreads) } - for _, dir := range []string{cfg.StagedDir, cfg.SealedDir, cfg.CacheDir, cfg.MetadataDir} { + for _, dir := range []string{cfg.StagedDir, cfg.SealedDir, cfg.CacheDir, cfg.UnsealedDir} { if err := os.Mkdir(dir, 0755); err != nil { if os.IsExist(err) { continue @@ -187,13 +190,72 @@ func (sb *SectorBuilder) AddPiece(pieceSize uint64, sectorId uint64, file io.Rea }, werr() } -// TODO: should *really really* return an io.ReadCloser -func (sb *SectorBuilder) ReadPieceFromSealedSector(pieceKey string) ([]byte, error) { - ret := sb.RateLimit() +func (sb *SectorBuilder) ReadPieceFromSealedSector(sectorID uint64, offset uint64, size uint64, ticket []byte, commD []byte) (io.ReadCloser, error) { + ret := sb.RateLimit() // TODO: check perf, consider remote unseal worker defer ret() - panic("fixme") - //return sectorbuilder.Unseal(sb.handle, pieceKey) + sb.unsealLk.Lock() // TODO: allow unsealing unrelated sectors in parallel + defer sb.unsealLk.Lock() + + cacheDir, err := sb.sectorCacheDir(sectorID) + if err != nil { + return nil, err + } + + sealedPath, err := sb.sealedSectorPath(sectorID) + if err != nil { + return nil, err + } + + unsealedPath := sb.unsealedSectorPath(sectorID) + + // TODO: GC for those + // (Probably configurable count of sectors to be kept unsealed, and just + // remove last used one (or use whatever other cache policy makes sense)) + f, err := os.OpenFile(unsealedPath, os.O_RDONLY, 0644) + if err != nil { + if !os.IsNotExist(err) { + return nil, err + } + + var commd [CommLen]byte + copy(commd[:], commD) + + var tkt [CommLen]byte + copy(tkt[:], ticket) + + err = sectorbuilder.Unseal(sb.ssize, + PoRepProofPartitions, + cacheDir, + sealedPath, + unsealedPath, + sectorID, + addressToProverID(sb.Miner), + tkt, + commd) + if err != nil { + return nil, xerrors.Errorf("unseal failed: %w", err) + } + + f, err = os.OpenFile(unsealedPath, os.O_RDONLY, 0644) + if err != nil { + return nil, err + } + } + + if _, err := f.Seek(int64(offset), io.SeekStart); err != nil { + return nil, xerrors.Errorf("seek: %w", err) + } + + lr := io.LimitReader(f, int64(size)) + + return &struct { + io.Reader + io.Closer + }{ + Reader: lr, + Closer: f, + }, nil } func (sb *SectorBuilder) SealPreCommit(sectorID uint64, ticket SealTicket, pieces []PublicPieceInfo) (RawSealPreCommitOutput, error) { diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 5be351323..eaa2a837a 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -66,7 +66,7 @@ func SectorBuilderConfig(storagePath string, threads uint) func(dtypes.MetadataD } cache := filepath.Join(sp, "cache") - metadata := filepath.Join(sp, "meta") + unsealed := filepath.Join(sp, "unsealed") sealed := filepath.Join(sp, "sealed") staging := filepath.Join(sp, "staging") @@ -76,7 +76,7 @@ func SectorBuilderConfig(storagePath string, threads uint) func(dtypes.MetadataD WorkerThreads: uint8(threads), CacheDir: cache, - MetadataDir: metadata, + UnsealedDir: unsealed, SealedDir: sealed, StagedDir: staging, } diff --git a/storage/cbor_gen.go b/storage/cbor_gen.go index 623cd31a9..1bc604e4a 100644 --- a/storage/cbor_gen.go +++ b/storage/cbor_gen.go @@ -155,7 +155,7 @@ func (t *Piece) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{132}); err != nil { + if _, err := w.Write([]byte{131}); err != nil { return err } @@ -164,14 +164,6 @@ func (t *Piece) MarshalCBOR(w io.Writer) error { return err } - // t.t.Ref (string) (string) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Ref)))); err != nil { - return err - } - if _, err := w.Write([]byte(t.Ref)); err != nil { - return err - } - // t.t.Size (uint64) (uint64) if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Size))); err != nil { return err @@ -198,7 +190,7 @@ func (t *Piece) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 4 { + if extra != 3 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -212,16 +204,6 @@ func (t *Piece) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("wrong type for uint64 field") } t.DealID = uint64(extra) - // t.t.Ref (string) (string) - - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - t.Ref = string(sval) - } // t.t.Size (uint64) (uint64) maj, extra, err = cbg.CborReadHeader(br) diff --git a/storage/garbage.go b/storage/garbage.go index ab41d6ff0..8b60392cf 100644 --- a/storage/garbage.go +++ b/storage/garbage.go @@ -3,7 +3,6 @@ package storage import ( "bytes" "context" - "fmt" "io" "math" "math/rand" @@ -95,7 +94,6 @@ func (m *Miner) storeGarbage(ctx context.Context, sectorID uint64, existingPiece out := make([]Piece, len(sizes)) for i, size := range sizes { - name := fmt.Sprintf("fake-file-%d", rand.Intn(100000000)) ppi, err := m.sb.AddPiece(size, sectorID, io.LimitReader(rand.New(rand.NewSource(42)), int64(size)), existingPieceSizes) if err != nil { return nil, err @@ -105,7 +103,6 @@ func (m *Miner) storeGarbage(ctx context.Context, sectorID uint64, existingPiece out[i] = Piece{ DealID: resp.DealIDs[i], - Ref: name, Size: ppi.Size, CommP: ppi.CommP[:], } @@ -134,7 +131,7 @@ func (m *Miner) StoreGarbageData() error { return } - if err := m.newSector(context.TODO(), sid, pieces[0].DealID, pieces[0].Ref, pieces[0].ppi()); err != nil { + if err := m.newSector(context.TODO(), sid, pieces[0].DealID, pieces[0].ppi()); err != nil { log.Errorf("%+v", err) return } diff --git a/storage/sealing.go b/storage/sealing.go index 7b3356fc7..6db2a70af 100644 --- a/storage/sealing.go +++ b/storage/sealing.go @@ -2,6 +2,7 @@ package storage import ( "context" + "github.com/filecoin-project/lotus/lib/padreader" "io" cid "github.com/ipfs/go-cid" @@ -37,7 +38,6 @@ func (t *SealSeed) SB() sectorbuilder.SealSeed { type Piece struct { DealID uint64 - Ref string Size uint64 CommP []byte @@ -97,14 +97,6 @@ func (t *SectorInfo) deals() []uint64 { return out } -func (t *SectorInfo) refs() []string { - out := make([]string, len(t.Pieces)) - for i, piece := range t.Pieces { - out[i] = piece.Ref - } - return out -} - func (t *SectorInfo) existingPieces() []uint64 { out := make([]uint64, len(t.Pieces)) for i, piece := range t.Pieces { @@ -265,30 +257,38 @@ func (m *Miner) failSector(id uint64, err error) { log.Errorf("sector %d error: %+v", id, err) } -func (m *Miner) SealPiece(ctx context.Context, ref string, size uint64, r io.Reader, dealID uint64) (uint64, error) { - log.Infof("Seal piece for deal %d", dealID) +func (m *Miner) AllocatePiece(size uint64) (sectorID uint64, offset uint64, err error) { + if padreader.PaddedSize(size) != size { + return 0, 0, xerrors.Errorf("cannot allocate unpadded piece") + } sid, err := m.sb.AcquireSectorId() // TODO: Put more than one thing in a sector if err != nil { - return 0, xerrors.Errorf("acquiring sector ID: %w", err) + return 0, 0, xerrors.Errorf("acquiring sector ID: %w", err) } - ppi, err := m.sb.AddPiece(size, sid, r, []uint64{}) - if err != nil { - return 0, xerrors.Errorf("adding piece to sector: %w", err) - } - - return sid, m.newSector(ctx, sid, dealID, ref, ppi) + // offset hard-coded to 0 since we only put one thing in a sector for now + return sid, 0, nil } -func (m *Miner) newSector(ctx context.Context, sid uint64, dealID uint64, ref string, ppi sectorbuilder.PublicPieceInfo) error { +func (m *Miner) SealPiece(ctx context.Context, size uint64, r io.Reader, sectorID uint64, dealID uint64) error { + log.Infof("Seal piece for deal %d", dealID) + + ppi, err := m.sb.AddPiece(size, sectorID, r, []uint64{}) + if err != nil { + return xerrors.Errorf("adding piece to sector: %w", err) + } + + return m.newSector(ctx, sectorID, dealID, ppi) +} + +func (m *Miner) newSector(ctx context.Context, sid uint64, dealID uint64, ppi sectorbuilder.PublicPieceInfo) error { si := &SectorInfo{ SectorID: sid, Pieces: []Piece{ { DealID: dealID, - Ref: ref, Size: ppi.Size, CommP: ppi.CommP[:], diff --git a/storage/sectorblocks/blocks.go b/storage/sectorblocks/blocks.go index e1f64ae3e..efdbe6ae5 100644 --- a/storage/sectorblocks/blocks.go +++ b/storage/sectorblocks/blocks.go @@ -39,31 +39,24 @@ var ErrNotFound = errors.New("not found") type SectorBlocks struct { *storage.Miner + sb *sectorbuilder.SectorBuilder intermediate blockstore.Blockstore // holds intermediate nodes TODO: consider combining with the staging blockstore - unsealed *unsealedBlocks - keys datastore.Batching - keyLk sync.Mutex + keys datastore.Batching + keyLk sync.Mutex } func NewSectorBlocks(miner *storage.Miner, ds dtypes.MetadataDS, sb *sectorbuilder.SectorBuilder) *SectorBlocks { sbc := &SectorBlocks{ Miner: miner, + sb: sb, intermediate: blockstore.NewBlockstore(namespace.Wrap(ds, imBlocksPrefix)), keys: namespace.Wrap(ds, dsPrefix), } - unsealed := &unsealedBlocks{ // TODO: untangle this - sb: sb, - - unsealed: map[string][]byte{}, - unsealing: map[string]chan struct{}{}, - } - - sbc.unsealed = unsealed return sbc } @@ -77,14 +70,13 @@ type UnixfsReader interface { type refStorer struct { blockReader UnixfsReader - writeRef func(cid cid.Cid, pieceRef string, offset uint64, size uint64) error + writeRef func(cid cid.Cid, offset uint64, size uint64) error intermediate blockstore.Blockstore - pieceRef string remaining []byte } -func (st *SectorBlocks) writeRef(cid cid.Cid, pieceRef string, offset uint64, size uint64) error { +func (st *SectorBlocks) writeRef(cid cid.Cid, sectorID uint64, offset uint64, size uint64) error { st.keyLk.Lock() // TODO: make this multithreaded defer st.keyLk.Unlock() @@ -104,9 +96,9 @@ func (st *SectorBlocks) writeRef(cid cid.Cid, pieceRef string, offset uint64, si } refs.Refs = append(refs.Refs, api.SealedRef{ - Piece: pieceRef, - Offset: offset, - Size: size, + SectorID: sectorID, + Offset: offset, + Size: size, }) newRef, err := cborutil.Dump(&refs) @@ -147,7 +139,7 @@ func (r *refStorer) Read(p []byte) (n int, err error) { continue } - if err := r.writeRef(nd.Cid(), r.pieceRef, offset, uint64(len(data))); err != nil { + if err := r.writeRef(nd.Cid(), offset, uint64(len(data))); err != nil { return 0, xerrors.Errorf("writing ref: %w", err) } @@ -160,22 +152,30 @@ func (r *refStorer) Read(p []byte) (n int, err error) { } } -func (st *SectorBlocks) AddUnixfsPiece(ctx context.Context, ref cid.Cid, r UnixfsReader, dealID uint64) (sectorID uint64, err error) { +func (st *SectorBlocks) AddUnixfsPiece(ctx context.Context, r UnixfsReader, dealID uint64) (sectorID uint64, err error) { size, err := r.Size() if err != nil { return 0, err } + sectorID, pieceOffset, err := st.Miner.AllocatePiece(padreader.PaddedSize(uint64(size))) + if err != nil { + return 0, err + } + refst := &refStorer{ - blockReader: r, - pieceRef: string(SerializationUnixfs0) + ref.String(), - writeRef: st.writeRef, + blockReader: r, + writeRef: func(cid cid.Cid, offset uint64, size uint64) error { + offset += pieceOffset + + return st.writeRef(cid, sectorID, offset, size) + }, intermediate: st.intermediate, } - pr, psize := padreader.New(r, uint64(size)) + pr, psize := padreader.New(refst, uint64(size)) - return st.Miner.SealPiece(ctx, refst.pieceRef, psize, pr, dealID) + return sectorID, st.Miner.SealPiece(ctx, psize, pr, sectorID, dealID) } func (st *SectorBlocks) List() (map[cid.Cid][]api.SealedRef, error) { diff --git a/storage/sectorblocks/blockstore.go b/storage/sectorblocks/blockstore.go index afa0fcbdf..2c5144854 100644 --- a/storage/sectorblocks/blockstore.go +++ b/storage/sectorblocks/blockstore.go @@ -2,6 +2,8 @@ package sectorblocks import ( "context" + "golang.org/x/xerrors" + "io/ioutil" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" @@ -67,9 +69,28 @@ func (s *SectorBlockStore) Get(c cid.Cid) (blocks.Block, error) { return nil, blockstore.ErrNotFound } - data, err := s.sectorBlocks.unsealed.getRef(context.TODO(), refs, s.approveUnseal) + best := refs[0] // TODO: better strategy (e.g. look for already unsealed) + + si, err := s.sectorBlocks.Miner.GetSectorInfo(best.SectorID) if err != nil { - return nil, err + return nil, xerrors.Errorf("getting sector info: %w", err) + } + + r, err := s.sectorBlocks.sb.ReadPieceFromSealedSector( + best.SectorID, + best.Offset, + best.Size, + si.Ticket.TicketBytes, + si.CommD, + ) + if err != nil { + return nil, xerrors.Errorf("unsealing block: %w", err) + } + defer r.Close() + + data, err := ioutil.ReadAll(r) + if err != nil { + return nil, xerrors.Errorf("reading block data: %w", err) } return blocks.NewBlockWithCid(data, c) diff --git a/storage/sectorblocks/unsealed.go b/storage/sectorblocks/unsealed.go deleted file mode 100644 index d01363a9a..000000000 --- a/storage/sectorblocks/unsealed.go +++ /dev/null @@ -1,99 +0,0 @@ -package sectorblocks - -import ( - "context" - "sync" - - logging "github.com/ipfs/go-log" - - "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/lib/sectorbuilder" -) - -var log = logging.Logger("sectorblocks") - -type unsealedBlocks struct { - lk sync.Mutex - sb *sectorbuilder.SectorBuilder - - // TODO: Treat this as some sort of cache, one with rather aggressive GC - // TODO: This REALLY, REALLY needs to be on-disk - unsealed map[string][]byte - - unsealing map[string]chan struct{} -} - -func (ub *unsealedBlocks) getRef(ctx context.Context, refs []api.SealedRef, approveUnseal func() error) ([]byte, error) { - var best api.SealedRef - - ub.lk.Lock() - for _, ref := range refs { - b, ok := ub.unsealed[ref.Piece] - if ok { - ub.lk.Unlock() - return b[ref.Offset : ref.Offset+uint64(ref.Size)], nil - } - // TODO: pick unsealing based on how long it's running (or just select all relevant, usually it'll be just one) - _, ok = ub.unsealing[ref.Piece] - if ok { - best = ref - break - } - best = ref - } - ub.lk.Unlock() - - b, err := ub.maybeUnseal(ctx, best.Piece, approveUnseal) - if err != nil { - return nil, err - } - - return b[best.Offset : best.Offset+uint64(best.Size)], nil -} - -func (ub *unsealedBlocks) maybeUnseal(ctx context.Context, pieceKey string, approveUnseal func() error) ([]byte, error) { - ub.lk.Lock() - defer ub.lk.Unlock() - - out, ok := ub.unsealed[pieceKey] - if ok { - return out, nil - } - - wait, ok := ub.unsealing[pieceKey] - if ok { - ub.lk.Unlock() - select { - case <-wait: - ub.lk.Lock() - // TODO: make sure this is not racy with gc when it's implemented - return ub.unsealed[pieceKey], nil - case <-ctx.Done(): - ub.lk.Lock() - return nil, ctx.Err() - } - } - - // TODO: doing this under a lock is suboptimal.. but simpler - err := approveUnseal() - if err != nil { - return nil, err - } - - ub.unsealing[pieceKey] = make(chan struct{}) - ub.lk.Unlock() - - log.Infof("Unsealing piece '%s'", pieceKey) - data, err := ub.sb.ReadPieceFromSealedSector(pieceKey) - ub.lk.Lock() - - if err != nil { - // TODO: tell subs - log.Error(err) - return nil, err - } - - ub.unsealed[pieceKey] = data - close(ub.unsealing[pieceKey]) - return data, nil -} From 660ba3f4f6ae15a7db5b70d2d7dfb08943977892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 19:37:23 +0100 Subject: [PATCH 60/93] genesis: set correct NextDealID in SMA --- chain/gen/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index b43815783..e5c61386d 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -205,7 +205,7 @@ func SetupStorageMarketActor(bs bstore.Blockstore, sroot cid.Cid, deals []actors sms := &actors.StorageMarketState{ Balances: emptyHAMT, Deals: dealAmt, - NextDealID: 0, + NextDealID: uint64(len(deals)), } stcid, err := cst.Put(context.TODO(), sms) From fd8f65248bbca5195742d44923272cfd7d6aa6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 21:07:42 +0100 Subject: [PATCH 61/93] deals: Correctly set deal ID in provider states --- chain/actors/actor_miner.go | 2 +- chain/actors/actor_storagemarket.go | 10 +++++++--- chain/deals/cbor_gen.go | 18 ++++++++++++++++-- chain/deals/provider.go | 7 +++++-- chain/deals/provider_states.go | 12 +++++------- chain/deals/types.go | 1 + cmd/lotus-seed/seed/seed.go | 8 ++++---- lib/sectorbuilder/sectorbuilder.go | 2 +- lotuspond/front/src/State.js | 5 +++-- storage/sectorblocks/blockstore.go | 7 ++++++- 10 files changed, 49 insertions(+), 23 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 6d0d7eb49..6494f3220 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -335,7 +335,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC commD, err := vmctx.Send(StorageMarketAddress, SMAMethods.ComputeDataCommitment, types.NewInt(0), enc) if err != nil { - return nil, aerrors.Wrap(err, "failed to compute data commitment") + return nil, aerrors.Wrapf(err, "failed to compute data commitment (sector %d, deals: %v)", params.SectorID, params.DealIDs) } if ok, err := ValidatePoRep(ctx, maddr, mi.SectorSize, commD, us.Info.CommR, ticket, params.Proof, seed, params.SectorID); err != nil { diff --git a/chain/actors/actor_storagemarket.go b/chain/actors/actor_storagemarket.go index 9cd8a265a..651fd8f71 100644 --- a/chain/actors/actor_storagemarket.go +++ b/chain/actors/actor_storagemarket.go @@ -611,18 +611,22 @@ func (sma StorageMarketActor) ComputeDataCommitment(act *types.Actor, vmctx type return nil, aerrors.HandleExternalError(err, "loading deals amt") } + if len(params.DealIDs) == 0 { + return nil, aerrors.New(3, "no deal IDs") + } + var pieces []sectorbuilder.PublicPieceInfo for _, deal := range params.DealIDs { var dealInfo OnChainDeal if err := deals.Get(deal, &dealInfo); err != nil { if _, is := err.(*amt.ErrNotFound); is { - return nil, aerrors.New(3, "deal not found") + return nil, aerrors.New(4, "deal not found") } return nil, aerrors.HandleExternalError(err, "getting deal info failed") } if dealInfo.Deal.Proposal.Provider != vmctx.Message().From { - return nil, aerrors.New(4, "referenced deal was not from caller") + return nil, aerrors.New(5, "referenced deal was not from caller") } var commP [32]byte @@ -636,7 +640,7 @@ func (sma StorageMarketActor) ComputeDataCommitment(act *types.Actor, vmctx type commd, err := sectorbuilder.GenerateDataCommitment(params.SectorSize, pieces) if err != nil { - return nil, aerrors.Absorb(err, 5, "failed to generate data commitment from pieces") + return nil, aerrors.Absorb(err, 6, "failed to generate data commitment from pieces") } return commd[:], nil diff --git a/chain/deals/cbor_gen.go b/chain/deals/cbor_gen.go index 1b10f1772..a5e20bb54 100644 --- a/chain/deals/cbor_gen.go +++ b/chain/deals/cbor_gen.go @@ -857,7 +857,7 @@ func (t *StorageDataTransferVoucher) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{129}); err != nil { + if _, err := w.Write([]byte{130}); err != nil { return err } @@ -867,6 +867,10 @@ func (t *StorageDataTransferVoucher) MarshalCBOR(w io.Writer) error { return xerrors.Errorf("failed to write cid field t.Proposal: %w", err) } + // t.t.DealID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.DealID))); err != nil { + return err + } return nil } @@ -881,7 +885,7 @@ func (t *StorageDataTransferVoucher) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 1 { + if extra != 2 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -897,5 +901,15 @@ func (t *StorageDataTransferVoucher) UnmarshalCBOR(r io.Reader) error { t.Proposal = c } + // t.t.DealID (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.DealID = uint64(extra) return nil } diff --git a/chain/deals/provider.go b/chain/deals/provider.go index 626fa7c0b..ec9a08d60 100644 --- a/chain/deals/provider.go +++ b/chain/deals/provider.go @@ -224,10 +224,13 @@ func (p *Provider) onDataTransferEvent(event datatransfer.Event, channelState da // data transfer events for opening and progress do not affect deal state var next api.DealState var err error + var mut func(*MinerDeal) switch event { case datatransfer.Complete: next = api.DealStaged - err = nil + mut = func(deal *MinerDeal) { + deal.DealID = voucher.DealID + } case datatransfer.Error: next = api.DealFailed err = ErrDataTransferFailed @@ -241,7 +244,7 @@ func (p *Provider) onDataTransferEvent(event datatransfer.Event, channelState da newState: next, id: voucher.Proposal, err: err, - mut: nil, + mut: mut, }: case <-p.stop: } diff --git a/chain/deals/provider_states.go b/chain/deals/provider_states.go index ca66cdedb..2ac1c9f6a 100644 --- a/chain/deals/provider_states.go +++ b/chain/deals/provider_states.go @@ -132,10 +132,10 @@ func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal) return nil, err } if len(resp.DealIDs) != 1 { - return nil, xerrors.Errorf("got unexpected number of DealIDs from") + return nil, xerrors.Errorf("got unexpected number of DealIDs from SMA") } - log.Info("fetching data for a deal") + log.Infof("fetching data for a deal %d", resp.DealIDs[0]) mcid := smsg.Cid() err = p.sendSignedResponse(&Response{ State: api.DealAccepted, @@ -164,14 +164,12 @@ func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal) // (see onDataTransferEvent) _, err = p.dataTransfer.OpenPullDataChannel(ctx, deal.Client, - &StorageDataTransferVoucher{Proposal: deal.ProposalCid}, + &StorageDataTransferVoucher{Proposal: deal.ProposalCid, DealID: resp.DealIDs[0]}, deal.Ref, allSelector, ) - return func(deal *MinerDeal) { - deal.DealID = resp.DealIDs[0] - }, nil + return nil, nil } // STAGED @@ -208,7 +206,7 @@ func (p *Provider) staged(ctx context.Context, deal MinerDeal) (func(*MinerDeal) if err != nil { return nil, xerrors.Errorf("AddPiece failed: %s", err) } - log.Warnf("New Sector: %d", sectorID) + log.Warnf("New Sector: %d (deal %d)", sectorID, deal.DealID) return func(deal *MinerDeal) { deal.SectorID = sectorID diff --git a/chain/deals/types.go b/chain/deals/types.go index 907bd8db4..3ea80ebe7 100644 --- a/chain/deals/types.go +++ b/chain/deals/types.go @@ -90,6 +90,7 @@ type AskResponse struct { // used by the storage market type StorageDataTransferVoucher struct { Proposal cid.Cid + DealID uint64 } // ToBytes converts the StorageDataTransferVoucher to raw bytes diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index c3c92c07c..d52c1b32c 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -108,7 +108,7 @@ func PreSeal(maddr address.Address, ssize uint64, sectors int, sbroot string, pr Key: minerAddr.KeyInfo, } - if err := createDeals(miner, minerAddr, ssize); err != nil { + if err := createDeals(miner, minerAddr, maddr, ssize); err != nil { return nil, xerrors.Errorf("creating deals: %w", err) } @@ -136,14 +136,14 @@ func WriteGenesisMiner(maddr address.Address, sbroot string, gm *genesis.Genesis return nil } -func createDeals(m *genesis.GenesisMiner, k *wallet.Key, ssize uint64) error { +func createDeals(m *genesis.GenesisMiner, k *wallet.Key, maddr address.Address, ssize uint64) error { for _, sector := range m.Sectors { proposal := &actors.StorageDealProposal{ PieceRef: sector.CommD[:], // just one deal so this == CommP - PieceSize: ssize, + PieceSize: sectorbuilder.UserBytesForSectorSize(ssize), PieceSerialization: actors.SerializationUnixFSv0, Client: k.Address, - Provider: k.Address, + Provider: maddr, ProposalExpiration: 9000, // TODO: allow setting Duration: 9000, StoragePricePerEpoch: types.NewInt(0), diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 5a3312f5e..7895c7be3 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -195,7 +195,7 @@ func (sb *SectorBuilder) ReadPieceFromSealedSector(sectorID uint64, offset uint6 defer ret() sb.unsealLk.Lock() // TODO: allow unsealing unrelated sectors in parallel - defer sb.unsealLk.Lock() + defer sb.unsealLk.Unlock() cacheDir, err := sb.sectorCacheDir(sectorID) if err != nil { diff --git a/lotuspond/front/src/State.js b/lotuspond/front/src/State.js index 9932ceb5e..d5b81ff83 100644 --- a/lotuspond/front/src/State.js +++ b/lotuspond/front/src/State.js @@ -107,7 +107,8 @@ class MarketState extends React.Component { const tipset = await this.props.client.call("Filecoin.ChainHead", []) // TODO: from props const participants = await this.props.client.call("Filecoin.StateMarketParticipants", [tipset]) const deals = await this.props.client.call("Filecoin.StateMarketDeals", [tipset]) - this.setState({participants, deals}) + const state = await this.props.client.call('Filecoin.StateReadState', [this.props.actor, tipset]) + this.setState({participants, deals, nextDeal: state.State.NextDealID}) } render() { @@ -125,7 +126,7 @@ class MarketState extends React.Component {
---
-
Deals:
+
Deals ({this.state.nextDeal} Total):
{Object.keys(this.state.deals).map(d => diff --git a/storage/sectorblocks/blockstore.go b/storage/sectorblocks/blockstore.go index 2c5144854..b1cc02b79 100644 --- a/storage/sectorblocks/blockstore.go +++ b/storage/sectorblocks/blockstore.go @@ -2,14 +2,17 @@ package sectorblocks import ( "context" - "golang.org/x/xerrors" "io/ioutil" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" blockstore "github.com/ipfs/go-ipfs-blockstore" + logging "github.com/ipfs/go-log" + "golang.org/x/xerrors" ) +var log = logging.Logger("sectorblocks") + type SectorBlockStore struct { intermediate blockstore.Blockstore sectorBlocks *SectorBlocks @@ -76,6 +79,8 @@ func (s *SectorBlockStore) Get(c cid.Cid) (blocks.Block, error) { return nil, xerrors.Errorf("getting sector info: %w", err) } + log.Infof("reading block %s from sector %d(+%d;%d)", c, best.SectorID, best.Offset, best.Size) + r, err := s.sectorBlocks.sb.ReadPieceFromSealedSector( best.SectorID, best.Offset, From c7cf20843ed1710bcc17a485f4fe6af6dd180d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 22:22:03 +0100 Subject: [PATCH 62/93] actually set unsealed path in sectorbuilder --- lib/sectorbuilder/sectorbuilder.go | 7 ++++--- retrieval/miner.go | 2 +- storage/sectorblocks/blockstore.go | 10 +++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 7895c7be3..8cb228f74 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -111,9 +111,10 @@ func New(cfg *Config, ds dtypes.MetadataDS) (*SectorBuilder, error) { ssize: cfg.SectorSize, lastID: lastUsedID, - stagedDir: cfg.StagedDir, - sealedDir: cfg.SealedDir, - cacheDir: cfg.CacheDir, + stagedDir: cfg.StagedDir, + sealedDir: cfg.SealedDir, + cacheDir: cfg.CacheDir, + unsealedDir: cfg.UnsealedDir, Miner: cfg.Miner, rateLimit: make(chan struct{}, cfg.WorkerThreads-PoStReservedWorkers), diff --git a/retrieval/miner.go b/retrieval/miner.go index 1792880de..361054037 100644 --- a/retrieval/miner.go +++ b/retrieval/miner.go @@ -41,7 +41,7 @@ func NewMiner(sblks *sectorblocks.SectorBlocks, full api.FullNode) *Miner { } func writeErr(stream network.Stream, err error) { - log.Errorf("Retrieval deal error: %s", err) + log.Errorf("Retrieval deal error: %+v", err) _ = cborutil.WriteCborRPC(stream, &DealResponse{ Status: Error, Message: err.Error(), diff --git a/storage/sectorblocks/blockstore.go b/storage/sectorblocks/blockstore.go index b1cc02b79..de6039ff5 100644 --- a/storage/sectorblocks/blockstore.go +++ b/storage/sectorblocks/blockstore.go @@ -97,8 +97,16 @@ func (s *SectorBlockStore) Get(c cid.Cid) (blocks.Block, error) { if err != nil { return nil, xerrors.Errorf("reading block data: %w", err) } + if uint64(len(data)) != best.Size { + return nil, xerrors.Errorf("got wrong amount of data: %d != !d", len(data), best.Size) + } - return blocks.NewBlockWithCid(data, c) + b, err := blocks.NewBlockWithCid(data, c) + if err != nil { + return nil, xerrors.Errorf("sbs get (%d[%d:%d]): %w", best.SectorID, best.Offset, best.Offset+best.Size, err) + } + + return b, nil } var _ blockstore.Blockstore = &SectorBlockStore{} From 68d1fd595868fc65c73bb5db5e9b7b4ad48ab3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 22:52:24 +0100 Subject: [PATCH 63/93] Test Retrieval --- api/api_full.go | 4 +++- api/test/deals.go | 42 +++++++++++++++++++++++++++++++++++++++++- cli/client.go | 4 +--- node/node_test.go | 2 +- paych/simple.go | 11 ++++++----- 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 2e0b81d1a..2d5ed580c 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -226,12 +226,14 @@ type QueryOffer struct { MinerPeerID peer.ID } -func (o *QueryOffer) Order() RetrievalOrder { +func (o *QueryOffer) Order(client address.Address) RetrievalOrder { return RetrievalOrder{ Root: o.Root, Size: o.Size, Total: o.MinPrice, + Client: client, + Miner: o.Miner, MinerPeerID: o.MinerPeerID, } diff --git a/api/test/deals.go b/api/test/deals.go index 62830c382..f4a815594 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -1,11 +1,14 @@ package test import ( + "bytes" "context" "fmt" "io" + "io/ioutil" "math/rand" "os" + "path/filepath" "testing" "time" @@ -40,7 +43,8 @@ func TestDealFlow(t *testing.T, b APIBuilder) { } time.Sleep(time.Second) - r := io.LimitReader(rand.New(rand.NewSource(17)), 1000) + data, _ := ioutil.ReadAll(io.LimitReader(rand.New(rand.NewSource(5)), 1000)) + r := bytes.NewReader(data) fcid, err := client.ClientImportLocal(ctx, r) if err != nil { t.Fatal(err) @@ -94,6 +98,42 @@ loop: time.Sleep(time.Second / 2) } + // Retrieval + + offers, err := client.ClientFindData(ctx, fcid) + if err != nil { + t.Fatal(err) + } + + if len(offers) < 1 { + t.Fatal("no offers") + } + + rpath, err := ioutil.TempDir("", "lotus-retrieve-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(rpath) + + caddr, err := client.WalletDefaultAddress(ctx) + if err != nil { + t.Fatal(err) + } + + err = client.ClientRetrieve(ctx, offers[0].Order(caddr), filepath.Join(rpath, "ret")) + if err != nil { + t.Fatalf("%+v", err) + } + + rdata, err := ioutil.ReadFile(filepath.Join(rpath, "ret")) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(rdata, data) { + t.Fatal("wrong data retrieved") + } + mine = false fmt.Println("shutting down mining") <-done diff --git a/cli/client.go b/cli/client.go index ff82455ba..0f1fdc991 100644 --- a/cli/client.go +++ b/cli/client.go @@ -234,10 +234,8 @@ var clientRetrieveCmd = &cli.Command{ fmt.Println("Failed to find file") return nil } - order := offers[0].Order() - order.Client = payer - if err := api.ClientRetrieve(ctx, order, cctx.Args().Get(1)); err != nil { + if err := api.ClientRetrieve(ctx, offers[0].Order(payer), cctx.Args().Get(1)); err != nil { return err } diff --git a/node/node_test.go b/node/node_test.go index f5760230b..c97eae27c 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -227,7 +227,7 @@ func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.Te CacheDir: filepath.Join(psd, "cache"), StagedDir: filepath.Join(psd, "staging"), SealedDir: filepath.Join(psd, "sealed"), - MetadataDir: filepath.Join(psd, "meta"), + UnsealedDir: filepath.Join(psd, "unsealed"), }, mds) if err != nil { t.Fatal(err) diff --git a/paych/simple.go b/paych/simple.go index 99c578d05..81ba51830 100644 --- a/paych/simple.go +++ b/paych/simple.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/ipfs/go-cid" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/address" @@ -37,7 +38,7 @@ 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, err + return address.Undef, cid.Undef, xerrors.Errorf("initializing paych actor: %w", err) } mcid := smsg.Cid() @@ -46,7 +47,7 @@ func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, am // (tricky because we need to setup channel tracking before we know it's address) mwait, err := pm.state.StateWaitMsg(ctx, mcid) if err != nil { - return address.Undef, cid.Undef, err + return address.Undef, cid.Undef, xerrors.Errorf("wait msg: %w", err) } if mwait.Receipt.ExitCode != 0 { @@ -60,11 +61,11 @@ func (pm *Manager) createPaych(ctx context.Context, from, to address.Address, am ci, err := pm.loadOutboundChannelInfo(ctx, paychaddr) if err != nil { - return address.Undef, cid.Undef, err + return address.Undef, cid.Undef, xerrors.Errorf("loading channel info: %w", err) } if err := pm.store.trackChannel(ci); err != nil { - return address.Undef, cid.Undef, err + return address.Undef, cid.Undef, xerrors.Errorf("tracking channel: %w", err) } return paychaddr, mcid, nil @@ -108,7 +109,7 @@ func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, ensur return ci.Control == from && ci.Target == to }) if err != nil { - return address.Undef, cid.Undef, err + return address.Undef, cid.Undef, xerrors.Errorf("findChan: %w", err) } if ch != address.Undef { // TODO: Track available funds From d9840c05dbf6b68d011d5f74e760808eb616a5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 1 Dec 2019 23:37:53 +0100 Subject: [PATCH 64/93] bench: Measure unseal time --- cmd/lotus-bench/main.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index be640ba70..23ed366ab 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -42,6 +42,7 @@ type SealingResult struct { PreCommit time.Duration Commit time.Duration Verify time.Duration + Unseal time.Duration } func main() { @@ -97,9 +98,9 @@ func main() { CacheDir: filepath.Join(tsdir, "cache"), SealedDir: filepath.Join(tsdir, "sealed"), StagedDir: filepath.Join(tsdir, "staged"), - MetadataDir: filepath.Join(tsdir, "meta"), + UnsealedDir: filepath.Join(tsdir, "unsealed"), } - for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.MetadataDir} { + for _, d := range []string{cfg.CacheDir, cfg.SealedDir, cfg.StagedDir, cfg.UnsealedDir} { if err := os.MkdirAll(d, 0775); err != nil { return err } @@ -113,8 +114,7 @@ func main() { return err } - r := rand.New(rand.NewSource(101)) - size := sectorbuilder.UserBytesForSectorSize(sectorSize) + dataSize := sectorbuilder.UserBytesForSectorSize(sectorSize) var sealTimings []SealingResult var sealedSectors []ffi.PublicSectorInfo @@ -122,7 +122,10 @@ func main() { for i := uint64(1); i <= numSectors; i++ { start := time.Now() log.Info("Writing piece into sector...") - pi, err := sb.AddPiece(size, i, r, nil) + + r := rand.New(rand.NewSource(100 + int64(i))) + + pi, err := sb.AddPiece(dataSize, i, r, nil) if err != nil { return err } @@ -171,11 +174,24 @@ func main() { verifySeal := time.Now() + log.Info("Unsealing sector") + rc, err := sb.ReadPieceFromSealedSector(1, 0, dataSize, ticket.TicketBytes[:], commD[:]) + if err != nil { + return err + } + + unseal := time.Now() + + if err := rc.Close(); err != nil { + return err + } + sealTimings = append(sealTimings, SealingResult{ AddPiece: addpiece.Sub(start), PreCommit: precommit.Sub(addpiece), Commit: sealcommit.Sub(precommit), Verify: verifySeal.Sub(sealcommit), + Unseal: unseal.Sub(verifySeal), }) } @@ -248,6 +264,7 @@ func main() { fmt.Printf("seal: preCommit: %s\n", benchout.SealingResults[0].PreCommit) fmt.Printf("seal: Commit: %s\n", benchout.SealingResults[0].Commit) fmt.Printf("seal: Verify: %s\n", benchout.SealingResults[0].Verify) + fmt.Printf("unseal: %s\n", benchout.SealingResults[0].Unseal) fmt.Printf("generate candidates: %s\n", benchout.PostGenerateCandidates) fmt.Printf("compute epost proof (cold): %s\n", benchout.PostEProofCold) fmt.Printf("compute epost proof (hot): %s\n", benchout.PostEProofHot) From e239fe41d4b43a4b863a62fb6e50464c063635d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 12:34:01 +0100 Subject: [PATCH 65/93] Fix Failing tests --- chain/address/address_test.go | 1 - chain/deals/request_validation_test.go | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/chain/address/address_test.go b/chain/address/address_test.go index ad2bd164d..bf77b974a 100644 --- a/chain/address/address_test.go +++ b/chain/address/address_test.go @@ -11,7 +11,6 @@ import ( "time" ffi "github.com/filecoin-project/filecoin-ffi" - "github.com/filecoin-project/go-bls-sigs" "github.com/multiformats/go-varint" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/chain/deals/request_validation_test.go b/chain/deals/request_validation_test.go index 01005d10d..87f41c8f5 100644 --- a/chain/deals/request_validation_test.go +++ b/chain/deals/request_validation_test.go @@ -127,7 +127,7 @@ func TestClientRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{proposalNd.Cid()}, pieceRef, nil), deals.ErrNoDeal) { + if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{proposalNd.Cid(), 1}, pieceRef, nil), deals.ErrNoDeal) { t.Fatal("Pull should fail if there is no deal stored") } }) @@ -144,7 +144,7 @@ func TestClientRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid}, pieceRef, nil), deals.ErrWrongPeer) { + if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, pieceRef, nil), deals.ErrWrongPeer) { t.Fatal("Pull should fail if miner address is incorrect") } }) @@ -156,7 +156,7 @@ func TestClientRequestValidation(t *testing.T) { if err := state.Begin(clientDeal.ProposalCid, &clientDeal); err != nil { t.Fatal("deal tracking failed") } - if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) { + if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) { t.Fatal("Pull should fail if piece ref is incorrect") } }) @@ -172,7 +172,7 @@ func TestClientRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid}, pieceRef, nil), deals.ErrInacceptableDealState) { + if !xerrors.Is(crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, pieceRef, nil), deals.ErrInacceptableDealState) { t.Fatal("Pull should fail if deal is in a state that cannot be data transferred") } }) @@ -188,7 +188,7 @@ func TestClientRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid}, pieceRef, nil) != nil { + if crv.ValidatePull(minerID, &deals.StorageDataTransferVoucher{clientDeal.ProposalCid, 1}, pieceRef, nil) != nil { t.Fatal("Pull should should succeed when all parameters are correct") } }) @@ -220,7 +220,7 @@ func TestProviderRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{proposalNd.Cid()}, pieceRef, nil), deals.ErrNoDeal) { + if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{proposalNd.Cid(), 1}, pieceRef, nil), deals.ErrNoDeal) { t.Fatal("Push should fail if there is no deal stored") } }) @@ -237,7 +237,7 @@ func TestProviderRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid}, pieceRef, nil), deals.ErrWrongPeer) { + if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, pieceRef, nil), deals.ErrWrongPeer) { t.Fatal("Push should fail if miner address is incorrect") } }) @@ -249,7 +249,7 @@ func TestProviderRequestValidation(t *testing.T) { if err := state.Begin(minerDeal.ProposalCid, &minerDeal); err != nil { t.Fatal("deal tracking failed") } - if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) { + if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, blockGenerator.Next().Cid(), nil), deals.ErrWrongPiece) { t.Fatal("Push should fail if piece ref is incorrect") } }) @@ -265,7 +265,7 @@ func TestProviderRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid}, pieceRef, nil), deals.ErrInacceptableDealState) { + if !xerrors.Is(mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, pieceRef, nil), deals.ErrInacceptableDealState) { t.Fatal("Push should fail if deal is in a state that cannot be data transferred") } }) @@ -281,7 +281,7 @@ func TestProviderRequestValidation(t *testing.T) { if err != nil { t.Fatal("unable to construct piece cid") } - if mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid}, pieceRef, nil) != nil { + if mrv.ValidatePush(clientID, &deals.StorageDataTransferVoucher{minerDeal.ProposalCid, 1}, pieceRef, nil) != nil { t.Fatal("Push should should succeed when all parameters are correct") } }) From d5b94884c83802a65e2cef5ca09ddb6f5013ab49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 13:51:16 +0100 Subject: [PATCH 66/93] Buch of lint fixes --- chain/events/events_test.go | 6 +++--- chain/gen/gen.go | 8 +++----- chain/store/store.go | 2 +- cmd/lotus-storage-miner/init.go | 8 ++++---- lib/sectorbuilder/sectorbuilder_test.go | 9 +++------ node/modules/testing/genesis.go | 5 ++--- node/node_test.go | 4 ++-- storage/miner.go | 12 ++++++------ storage/sealing.go | 5 +++-- 9 files changed, 27 insertions(+), 32 deletions(-) diff --git a/chain/events/events_test.go b/chain/events/events_test.go index 927653357..034f0ce5f 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -55,12 +55,12 @@ func (fcs *fakeCS) ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { a, _ := address.NewFromString("t00") b, _ := address.NewFromString("t02") - ts, err := types.NewTipSet([]*types.BlockHeader{ + var ts, err = types.NewTipSet([]*types.BlockHeader{ { Height: h, Miner: a, - Ticket: &types.Ticket{[]byte{byte(h % 2)}}, + Ticket: &types.Ticket{VRFProof: []byte{byte(h % 2)}}, ParentStateRoot: dummyCid, Messages: msgcid, @@ -73,7 +73,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet { Height: h, Miner: b, - Ticket: &types.Ticket{[]byte{byte((h + 1) % 2)}}, + Ticket: &types.Ticket{VRFProof: []byte{byte((h + 1) % 2)}}, ParentStateRoot: dummyCid, Messages: msgcid, diff --git a/chain/gen/gen.go b/chain/gen/gen.go index a96b167e0..7ce3576c6 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -448,13 +448,11 @@ type ElectionPoStProver interface { ComputeProof(context.Context, sectorbuilder.SortedPublicSectorInfo, []byte, []sectorbuilder.EPostCandidate) ([]byte, error) } -type eppProvider struct { - sectors []ffi.PublicSectorInfo -} +type eppProvider struct{} func (epp *eppProvider) GenerateCandidates(ctx context.Context, _ sectorbuilder.SortedPublicSectorInfo, eprand []byte) ([]sectorbuilder.EPostCandidate, error) { return []sectorbuilder.EPostCandidate{ - sectorbuilder.EPostCandidate{ + { SectorID: 1, PartialTicket: [32]byte{}, Ticket: [32]byte{}, @@ -577,7 +575,7 @@ func hashVRFBase(personalization uint64, miner address.Address, input []byte) ([ } func VerifyVRF(ctx context.Context, worker, miner address.Address, p uint64, input, vrfproof []byte) error { - ctx, span := trace.StartSpan(ctx, "VerifyVRF") + _, span := trace.StartSpan(ctx, "VerifyVRF") defer span.End() vrfBase, err := hashVRFBase(p, miner, input) diff --git a/chain/store/store.go b/chain/store/store.go index 44bdefacf..879f16c32 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -800,7 +800,7 @@ func drawRandomness(t *types.Ticket, round int64) []byte { } func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) { - ctx, span := trace.StartSpan(ctx, "store.GetRandomness") + _, span := trace.StartSpan(ctx, "store.GetRandomness") defer span.End() span.AddAttributes(trace.Int64Attribute("round", round)) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 4ee3ae7f2..c54794913 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -370,10 +370,10 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, } return nil - } else { - if err := configureStorageMiner(ctx, api, a, peerid); err != nil { - return xerrors.Errorf("failed to configure storage miner: %w", err) - } + } + + if err := configureStorageMiner(ctx, api, a, peerid); err != nil { + return xerrors.Errorf("failed to configure storage miner: %w", err) } addr = a diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index 9ac332ae2..6f97f0a34 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -122,8 +122,7 @@ func TestSealAndVerify(t *testing.T) { if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware t.Skip("this is slow") } - os.Setenv("BELLMAN_NO_GPU", "1") - os.Setenv("RUST_LOG", "info") + _ = os.Setenv("RUST_LOG", "info") build.SectorSizes = []uint64{sectorSize} @@ -192,8 +191,7 @@ func TestSealPoStNoCommit(t *testing.T) { if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware t.Skip("this is slow") } - os.Setenv("BELLMAN_NO_GPU", "1") - os.Setenv("RUST_LOG", "info") + _ = os.Setenv("RUST_LOG", "info") build.SectorSizes = []uint64{sectorSize} @@ -255,8 +253,7 @@ func TestSealAndVerify2(t *testing.T) { if runtime.NumCPU() < 10 && os.Getenv("CI") == "" { // don't bother on slow hardware t.Skip("this is slow") } - os.Setenv("BELLMAN_NO_GPU", "1") - os.Setenv("RUST_LOG", "info") + _ = os.Setenv("RUST_LOG", "info") build.SectorSizes = []uint64{sectorSize} diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 6fbc0ccfc..4f6081c04 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -9,15 +9,14 @@ import ( "os" "time" - "golang.org/x/xerrors" - "github.com/ipfs/go-blockservice" "github.com/ipfs/go-car" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" logging "github.com/ipfs/go-log" "github.com/ipfs/go-merkledag" - peer "github.com/libp2p/go-libp2p-peer" + "github.com/libp2p/go-libp2p-core/peer" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/gen" diff --git a/node/node_test.go b/node/node_test.go index c97eae27c..190440416 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -38,7 +38,7 @@ import ( ) func init() { - logging.SetLogLevel("*", "INFO") + _ = logging.SetLogLevel("*", "INFO") } func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, pk crypto.PrivKey, tnd test.TestNode, mn mocknet.Mocknet) test.TestStorageNode { @@ -121,7 +121,7 @@ func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, a } } - return test.TestStorageNode{minerapi, mineOne} + return test.TestStorageNode{StorageMiner: minerapi, MineOne: mineOne} } func builder(t *testing.T, nFull int, storage []int) ([]test.TestNode, []test.TestStorageNode) { diff --git a/storage/miner.go b/storage/miner.go index 3972e4e11..3f78e7ca7 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -143,17 +143,17 @@ func (m *Miner) runPreflightChecks(ctx context.Context) error { return nil } -type sectorBuilderEpp struct { +type SectorBuilderEpp struct { sb *sectorbuilder.SectorBuilder } -func NewElectionPoStProver(sb *sectorbuilder.SectorBuilder) *sectorBuilderEpp { - return §orBuilderEpp{sb} +func NewElectionPoStProver(sb *sectorbuilder.SectorBuilder) *SectorBuilderEpp { + return &SectorBuilderEpp{sb} } -var _ gen.ElectionPoStProver = (*sectorBuilderEpp)(nil) +var _ gen.ElectionPoStProver = (*SectorBuilderEpp)(nil) -func (epp *sectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) { +func (epp *SectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) { var faults []uint64 // TODO var randbuf [32]byte @@ -161,7 +161,7 @@ func (epp *sectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorb return epp.sb.GenerateEPostCandidates(ssi, randbuf, faults) } -func (epp *sectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { +func (epp *SectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { if build.InsecurePoStValidation { log.Warn("Generating fake EPost proof! You should only see this while running tests!") return []byte("valid proof"), nil diff --git a/storage/sealing.go b/storage/sealing.go index 6db2a70af..7628fabd8 100644 --- a/storage/sealing.go +++ b/storage/sealing.go @@ -2,13 +2,13 @@ package storage import ( "context" - "github.com/filecoin-project/lotus/lib/padreader" "io" cid "github.com/ipfs/go-cid" xerrors "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/lib/padreader" "github.com/filecoin-project/lotus/lib/sectorbuilder" ) @@ -142,7 +142,8 @@ func (m *Miner) sectorStateLoop(ctx context.Context) error { // verify on-chain state trackedByID := map[uint64]*SectorInfo{} for _, si := range trackedSectors { - trackedByID[si.SectorID] = &si + i := si + trackedByID[si.SectorID] = &i } curTs, err := m.api.ChainHead(ctx) From 1cdf6a6f8d11b6535bdfdc6ab0f1edbdcdc0ebe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 15:24:27 +0100 Subject: [PATCH 67/93] use challangeCount as sampleRate in IsTicketWinner --- chain/gen/gen.go | 5 ++++- chain/sync.go | 7 +++++-- lib/sectorbuilder/sectorbuilder.go | 8 ++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 7ce3576c6..35bf58a38 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -519,7 +519,10 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add var winners []sectorbuilder.EPostCandidate for _, c := range candidates { - if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, 1) { + sectors := types.BigDiv(pow.MinerPower, types.NewInt(ssize)) + challangeCount := sectorbuilder.ElectionPostChallengeCount(sectors.Uint64()) + + if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, int64(challangeCount)) { winners = append(winners, c) } } diff --git a/chain/sync.go b/chain/sync.go index c6e8f17a5..dbf974cfa 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -545,7 +545,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } winnerCheck := async.Err(func() error { - _, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) + mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) if err != nil { return xerrors.Errorf("failed getting power: %w", err) } @@ -556,7 +556,10 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } for _, t := range h.EPostProof.Candidates { - if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) { + sectors := types.BigDiv(mpow, types.NewInt(ssize)) + challangeCount := sectorbuilder.ElectionPostChallengeCount(sectors.Uint64()) + + if !types.IsTicketWinner(t.Partial, ssize, tpow, int64(challangeCount)) { return xerrors.Errorf("miner created a block but was not a winner") } } diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 8cb228f74..c8f0a1e1c 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -356,7 +356,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn return nil, err } - challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values()))) + challengeCount := ElectionPostChallengeCount(uint64(len(sectorInfo.Values()))) proverID := addressToProverID(sb.Miner) return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors) @@ -425,7 +425,7 @@ func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedP } func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) { - challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values()))) + challengeCount := ElectionPostChallengeCount(uint64(len(sectorInfo.Values()))) return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID) } @@ -467,13 +467,13 @@ func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]by return sectorbuilder.GenerateDataCommitment(ssize, pieces) } -func electionPostChallengeCount(sectors uint64) uint64 { +func ElectionPostChallengeCount(sectors uint64) uint64 { // ceil(sectors / build.SectorChallengeRatioDiv) return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv } func fallbackPostChallengeCount(sectors uint64) uint64 { - challengeCount := electionPostChallengeCount(sectors) + challengeCount := ElectionPostChallengeCount(sectors) if challengeCount > build.MaxFallbackPostChallengeCount { return build.MaxFallbackPostChallengeCount } From 6f578d4006f0c31c9dc24be7fb1b279b534d3c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 15:26:39 +0100 Subject: [PATCH 68/93] Address review nits --- Makefile | 1 + api/test/deals.go | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fadb68129..d492060e5 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ endif MODULES:= CLEAN:= +BINS:= ## FFI diff --git a/api/test/deals.go b/api/test/deals.go index f4a815594..735c6063b 100644 --- a/api/test/deals.go +++ b/api/test/deals.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "io" "io/ioutil" "math/rand" "os" @@ -43,7 +42,9 @@ func TestDealFlow(t *testing.T, b APIBuilder) { } time.Sleep(time.Second) - data, _ := ioutil.ReadAll(io.LimitReader(rand.New(rand.NewSource(5)), 1000)) + data := make([]byte, 1000) + rand.New(rand.NewSource(5)).Read(data) + r := bytes.NewReader(data) fcid, err := client.ClientImportLocal(ctx, r) if err != nil { From 66a0aaf2534e61e4426a56155ac737c3cb3253c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 15:29:21 +0100 Subject: [PATCH 69/93] Update filecoin-ffi --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 0e71b164c..c5f3530f7 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 0e71b164cf4b2e1c0f53ca25145e3ea57cc53e90 +Subproject commit c5f3530f78b8152de92fcb3b4506ed00722c5076 From 24be85e8ec1509752e6124e903428296d7facfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 17:47:09 +0100 Subject: [PATCH 70/93] Fix storage miner info for ePoSt --- cmd/lotus-storage-miner/info.go | 17 ++++++++++++----- lotuspond/main.go | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index 900a7c611..27c6271ef 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -60,18 +60,25 @@ var infoCmd = &cli.Command{ } fmt.Printf("Worker use: %d / %d (+%d)\n", wstat.Total-wstat.Reserved-wstat.Free, wstat.Total, wstat.Reserved) - ppe, err := api.StateMinerElectionPeriodStart(ctx, maddr, nil) + eps, err := api.StateMinerElectionPeriodStart(ctx, maddr, nil) if err != nil { return err } - if ppe != 0 { + if eps != 0 { head, err := api.ChainHead(ctx) if err != nil { return err } - pdiff := int64(ppe - head.Height()) - pdifft := pdiff * build.BlockDelay - fmt.Printf("Proving Period: %d, in %d Blocks (~%dm %ds)\n", ppe, pdiff, pdifft/60, pdifft%60) + lastEps := int64(head.Height() - eps) + lastEpsS := lastEps * build.BlockDelay + + next := lastEps + build.SlashablePowerDelay + nextS := next * build.BlockDelay + + fmt.Printf("PoSt Submissions:\n") + fmt.Printf("\tPrevious: Epoch %d (%d block(s), ~%dm %ds ago)\n", eps, lastEps, lastEpsS/60, lastEpsS%60) + fmt.Printf("\tDeadline: Epoch %d (in %d blocks, ~%dm %ds)\n", eps+build.SlashablePowerDelay, next, nextS/60, nextS%60) + } else { fmt.Printf("Proving Period: Not Proving\n") } diff --git a/lotuspond/main.go b/lotuspond/main.go index d3238dad7..17ad7c970 100644 --- a/lotuspond/main.go +++ b/lotuspond/main.go @@ -88,6 +88,8 @@ var shCmd = &cli.Command{ } } + shcmd.Env = append(os.Environ(), shcmd.Env...) + shcmd.Stdin = os.Stdin shcmd.Stdout = os.Stdout shcmd.Stderr = os.Stderr From 5beb7f4a48ff8bda8113df9d08652624bbbdcc4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 19:56:27 +0100 Subject: [PATCH 71/93] More review fixes --- chain/gen/utils.go | 10 +--------- chain/sync_test.go | 4 +++- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index e5c61386d..817ab4f32 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -25,14 +25,6 @@ import ( "github.com/filecoin-project/lotus/genesis" ) -var validSsizes = map[uint64]struct{}{} - -func init() { - for _, size := range build.SectorSizes { - validSsizes[size] = struct{}{} - } -} - type GenesisBootstrap struct { Genesis *types.BlockHeader } @@ -326,7 +318,7 @@ func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid if err := cst.Get(ctx, mact.Head, &mstate); err != nil { return cid.Undef, nil, xerrors.Errorf("getting miner actor state failed: %w", err) } - mstate.Power = types.NewInt(build.SectorSizes[0]) + mstate.Power = types.BigMul(types.NewInt(build.SectorSizes[0]), types.NewInt(uint64(len(ps.Sectors)))) blks := amt.WrapBlockstore(cs.Blockstore()) diff --git a/chain/sync_test.go b/chain/sync_test.go index f161316b9..f8c387a1e 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -3,6 +3,7 @@ package chain_test import ( "context" "fmt" + "os" "testing" "time" @@ -25,6 +26,7 @@ import ( func init() { build.InsecurePoStValidation = true + os.Setenv("TRUST_PARAMS", "1") } const source = 0 @@ -346,7 +348,7 @@ func (tu *syncTestUtil) waitUntilSyncTarget(to int, target *types.TipSet) { } func TestSyncSimple(t *testing.T) { - H := 2 + H := 50 tu := prepSyncTest(t, H) client := tu.addClientNode() From 22f96e626b8940f33621825a5964330bcf3bb2ed Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 11:25:10 -0800 Subject: [PATCH 72/93] add flag to disable gpu to lotus-bench --- cmd/lotus-bench/main.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index 23ed366ab..33fdfcbf2 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -64,8 +64,15 @@ func main() { Name: "sector-size", Value: 1024, }, + &cli.BoolFlag{ + Name: "no-gpu", + Usage: "disable gpu usage for the benchmark run", + }, }, Action: func(c *cli.Context) error { + if c.Bool("no-gpu") { + os.Setenv("BELLMAN_NO_GPU", "1") + } sdir, err := homedir.Expand(c.String("storage-dir")) if err != nil { return err From 28ddc904b41689786f14021fbc7fd583d1fcd9e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 20:51:41 +0100 Subject: [PATCH 73/93] Miner can have no power without being slashed --- miner/miner.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/miner/miner.go b/miner/miner.go index 232910aed..d21f6cf6c 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -237,7 +237,7 @@ func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) }, nil } -func (m *Miner) isSlashed(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) { +func (m *Miner) hasPower(ctx context.Context, addr address.Address, ts *types.TipSet) (bool, error) { power, err := m.api.StateMinerPower(ctx, addr, ts) if err != nil { return false, err @@ -250,12 +250,12 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB log.Debugw("attempting to mine a block", "tipset", types.LogCids(base.ts.Cids())) start := time.Now() - slashed, err := m.isSlashed(ctx, addr, base.ts) + hasPower, err := m.hasPower(ctx, addr, base.ts) if err != nil { return nil, xerrors.Errorf("checking if miner is slashed: %w", err) } - if slashed { - log.Warnf("Slashed at epoch %d, not attempting to mine a block", base.ts.Height()+base.nullRounds) + if hasPower { + // slashed or just have no power yet base.nullRounds++ return nil, nil } From b255b57de8b73c5f916c9c397b7dc0d8f0b52ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 21:04:04 +0100 Subject: [PATCH 74/93] Demote BestMiningCandidate error to wanning --- miner/miner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/miner.go b/miner/miner.go index d21f6cf6c..370014777 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -153,7 +153,7 @@ eventLoop: continue } if base.ts.Equals(lastBase.ts) && lastBase.nullRounds == base.nullRounds { - log.Errorf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds) + log.Warnf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds) time.Sleep(build.BlockDelay * time.Second) continue } From 4edbd4dded819e229584b7b2358fe1dab6501bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 21:05:38 +0100 Subject: [PATCH 75/93] Try to fix circle buildall --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 827c9f77b..30dc273b8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,6 +52,8 @@ jobs: - install-deps - prepare - go/mod-download + - run: sudo apt-get update + - run: sudo apt-get install npm - run: command: make buildall From 4fa602076fe332b7475021c68e0e67bc95cc44af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 21:47:27 +0100 Subject: [PATCH 76/93] Fix pond ci build --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d492060e5..e31baa048 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ benchmarks: pond: build go build -o pond ./lotuspond - (cd lotuspond/front && npm i && npm run build) + (cd lotuspond/front && npm i && CI=false npm run build) .PHONY: pond BINS+=pond From f5a35c32a34582a82442ac2e5679c62fa52ea503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 22:25:43 +0100 Subject: [PATCH 77/93] Update filecoin-ffi --- extern/filecoin-ffi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index c5f3530f7..9faf00cb5 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit c5f3530f78b8152de92fcb3b4506ed00722c5076 +Subproject commit 9faf00cb536fd86559440a09de9131520ae1ca0e From 923748e5515569ed8d99830b497c7042dcf58cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 23:10:22 +0100 Subject: [PATCH 78/93] Expand paths in node init --- cmd/lotus-storage-miner/init.go | 5 +++++ node/modules/testing/genesis.go | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index c54794913..9e95feb96 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -123,6 +123,11 @@ var initCmd = &cli.Command{ } if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { + pssb, err := homedir.Expand(pssb) + if err != nil { + return err + } + log.Infof("moving pre-sealed-sectors from %s into newly created storage miner repo", pssb) lr, err := r.Lock(repo.StorageMiner) if err != nil { diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 4f6081c04..f61498e2b 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/mitchellh/go-homedir" "io" "io/ioutil" "os" @@ -67,11 +68,16 @@ func MakeGenesisMem(out io.Writer, gmc *gen.GenMinerCfg) func(bs dtypes.ChainBlo } } -func MakeGenesis(outFile, preseal string) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { +func MakeGenesis(outFile, presealInfo string) func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func(bs dtypes.ChainBlockstore, w *wallet.Wallet) modules.Genesis { return func() (*types.BlockHeader, error) { glog.Warn("Generating new random genesis block, note that this SHOULD NOT happen unless you are setting up new network") - fdata, err := ioutil.ReadFile(preseal) + presealInfo, err := homedir.Expand(presealInfo) + if err != nil { + return nil, err + } + + fdata, err := ioutil.ReadFile(presealInfo) if err != nil { return nil, err } From 8da3cc875ef80d369dacd36937a9b96a8eec8e9f Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sun, 1 Dec 2019 16:22:10 -0600 Subject: [PATCH 79/93] Fix message nonce tracking during head changes --- chain/messagepool.go | 112 ++++++++++++++++++++++++----- chain/messagepool_test.go | 147 ++++++++++++++++++++++++++++++++++++++ chain/store/store.go | 1 + chain/types/mock/chain.go | 22 ++++++ miner/miner.go | 2 +- node/modules/chain.go | 3 +- 6 files changed, 269 insertions(+), 18 deletions(-) create mode 100644 chain/messagepool_test.go diff --git a/chain/messagepool.go b/chain/messagepool.go index f0a3ed383..79b0ac315 100644 --- a/chain/messagepool.go +++ b/chain/messagepool.go @@ -9,6 +9,7 @@ import ( "time" lru "github.com/hashicorp/golang-lru" + "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/query" @@ -21,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/stmgr" + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -56,9 +58,10 @@ type MessagePool struct { pending map[address.Address]*msgSet pendingCount int - sm *stmgr.StateManager + curTsLk sync.RWMutex + curTs *types.TipSet - ps *pubsub.PubSub + api MpoolProvider minGasPrice types.BigInt @@ -98,20 +101,61 @@ func (ms *msgSet) add(m *types.SignedMessage) error { return nil } -func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*MessagePool, error) { +type MpoolProvider interface { + SubscribeHeadChanges(func(rev, app []*types.TipSet) error) + PutMessage(m store.ChainMsg) (cid.Cid, error) + PubSubPublish(string, []byte) error + StateGetActor(address.Address, *types.TipSet) (*types.Actor, error) + MessagesForBlock(*types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) + MessagesForTipset(*types.TipSet) ([]store.ChainMsg, error) +} + +type mpoolProvider struct { + sm *stmgr.StateManager + ps *pubsub.PubSub +} + +func NewMpoolProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) MpoolProvider { + return &mpoolProvider{sm, ps} +} + +func (mpp *mpoolProvider) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) { + mpp.sm.ChainStore().SubscribeHeadChanges(cb) +} + +func (mpp *mpoolProvider) PutMessage(m store.ChainMsg) (cid.Cid, error) { + return mpp.sm.ChainStore().PutMessage(m) +} + +func (mpp *mpoolProvider) PubSubPublish(k string, v []byte) error { + return mpp.ps.Publish(k, v) +} + +func (mpp *mpoolProvider) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) { + return mpp.sm.GetActor(addr, ts) +} + +func (mpp *mpoolProvider) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) { + return mpp.sm.ChainStore().MessagesForBlock(h) +} + +func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, error) { + return mpp.sm.ChainStore().MessagesForTipset(ts) +} + +func NewMessagePool(api MpoolProvider, ds dtypes.MetadataDS) (*MessagePool, error) { cache, _ := lru.New2Q(build.BlsSignatureCacheSize) mp := &MessagePool{ closer: make(chan struct{}), repubTk: time.NewTicker(build.BlockDelay * 10 * time.Second), localAddrs: make(map[address.Address]struct{}), pending: make(map[address.Address]*msgSet), - sm: sm, - ps: ps, minGasPrice: types.NewInt(0), maxTxPoolSize: 5000, blsSigCache: cache, changes: lps.New(50), localMsgs: namespace.Wrap(ds, datastore.NewKey(localMsgsDs)), + api: api, } if err := mp.loadLocal(); err != nil { @@ -120,7 +164,7 @@ func NewMessagePool(sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.Metadat go mp.repubLocal() - sm.ChainStore().SubscribeHeadChanges(func(rev, app []*types.TipSet) error { + api.SubscribeHeadChanges(func(rev, app []*types.TipSet) error { err := mp.HeadChange(rev, app) if err != nil { log.Errorf("mpool head notif handler error: %+v", err) @@ -155,7 +199,7 @@ func (mp *MessagePool) repubLocal() { continue } - err = mp.ps.Publish(msgTopic, msgb) + err = mp.api.PubSubPublish(msgTopic, msgb) if err != nil { errout = multierr.Append(errout, xerrors.Errorf("could not publish: %w", err)) continue @@ -200,7 +244,7 @@ func (mp *MessagePool) Push(m *types.SignedMessage) error { } mp.lk.Unlock() - return mp.ps.Publish(msgTopic, msgb) + return mp.api.PubSubPublish(msgTopic, msgb) } func (mp *MessagePool) Add(m *types.SignedMessage) error { @@ -252,12 +296,12 @@ func (mp *MessagePool) addLocked(m *types.SignedMessage) error { mp.blsSigCache.Add(m.Cid(), m.Signature) } - if _, err := mp.sm.ChainStore().PutMessage(m); err != nil { + if _, err := mp.api.PutMessage(m); err != nil { log.Warnf("mpooladd cs.PutMessage failed: %s", err) return err } - if _, err := mp.sm.ChainStore().PutMessage(&m.Message); err != nil { + if _, err := mp.api.PutMessage(&m.Message); err != nil { log.Warnf("mpooladd cs.PutMessage failed: %s", err) return err } @@ -307,16 +351,44 @@ func (mp *MessagePool) getNonceLocked(addr address.Address) (uint64, error) { } func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) { - act, err := mp.sm.GetActor(addr, nil) + // TODO: this method probably should be cached + mp.curTsLk.RLock() + defer mp.curTsLk.RUnlock() + + act, err := mp.api.StateGetActor(addr, mp.curTs) if err != nil { return 0, err } - return act.Nonce, nil + baseNonce := act.Nonce + + // TODO: the correct thing to do here is probably to set curTs to chain.head + // but since we have an accurate view of the world until a head change occurs, + // this should be fine + if mp.curTs == nil { + return baseNonce, nil + } + + msgs, err := mp.api.MessagesForTipset(mp.curTs) + if err != nil { + return 0, xerrors.Errorf("failed to check messages for tipset: %w", err) + } + + for _, m := range msgs { + msg := m.VMMessage() + if msg.From == addr { + if msg.Nonce != baseNonce { + return 0, xerrors.Errorf("tipset %s has bad nonce ordering", mp.curTs) + } + baseNonce++ + } + } + + return baseNonce, nil } func (mp *MessagePool) getStateBalance(addr address.Address) (types.BigInt, error) { - act, err := mp.sm.GetActor(addr, nil) + act, err := mp.api.StateGetActor(addr, nil) if err != nil { return types.EmptyInt, err } @@ -327,6 +399,9 @@ func (mp *MessagePool) getStateBalance(addr address.Address) (types.BigInt, erro func (mp *MessagePool) PushWithNonce(addr address.Address, cb func(uint64) (*types.SignedMessage, error)) (*types.SignedMessage, error) { mp.lk.Lock() defer mp.lk.Unlock() + if addr.Protocol() == address.ID { + log.Warnf("Called pushWithNonce with ID address (%s) this might not be handled properly yet", addr) + } nonce, err := mp.getNonceLocked(addr) if err != nil { @@ -350,7 +425,7 @@ func (mp *MessagePool) PushWithNonce(addr address.Address, cb func(uint64) (*typ log.Errorf("addLocal failed: %+v", err) } - return msg, mp.ps.Publish(msgTopic, msgb) + return msg, mp.api.PubSubPublish(msgTopic, msgb) } func (mp *MessagePool) Remove(from address.Address, nonce uint64) { @@ -421,9 +496,12 @@ func (mp *MessagePool) pendingFor(a address.Address) []*types.SignedMessage { } func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) error { + mp.curTsLk.Lock() + defer mp.curTsLk.Unlock() + for _, ts := range revert { for _, b := range ts.Blocks() { - bmsgs, smsgs, err := mp.sm.ChainStore().MessagesForBlock(b) + bmsgs, smsgs, err := mp.api.MessagesForBlock(b) if err != nil { return xerrors.Errorf("failed to get messages for revert block %s(height %d): %w", b.Cid(), b.Height, err) } @@ -444,11 +522,12 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) } } } + mp.curTs = ts } for _, ts := range apply { for _, b := range ts.Blocks() { - bmsgs, smsgs, err := mp.sm.ChainStore().MessagesForBlock(b) + bmsgs, smsgs, err := mp.api.MessagesForBlock(b) if err != nil { return xerrors.Errorf("failed to get messages for apply block %s(height %d) (msgroot = %s): %w", b.Cid(), b.Height, b.Messages, err) } @@ -460,6 +539,7 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) mp.Remove(msg.From, msg.Nonce) } } + mp.curTs = ts } return nil diff --git a/chain/messagepool_test.go b/chain/messagepool_test.go new file mode 100644 index 000000000..f76ed5422 --- /dev/null +++ b/chain/messagepool_test.go @@ -0,0 +1,147 @@ +package chain + +import ( + "testing" + + "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/store" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/types/mock" + "github.com/filecoin-project/lotus/chain/wallet" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" +) + +type testMpoolApi struct { + cb func(rev, app []*types.TipSet) error + + bmsgs map[cid.Cid][]*types.SignedMessage + statenonce map[address.Address]uint64 +} + +func newTestMpoolApi() *testMpoolApi { + return &testMpoolApi{ + bmsgs: make(map[cid.Cid][]*types.SignedMessage), + statenonce: make(map[address.Address]uint64), + } +} + +func (tma *testMpoolApi) applyBlock(t *testing.T, b *types.BlockHeader) { + t.Helper() + if err := tma.cb(nil, []*types.TipSet{mock.TipSet(b)}); err != nil { + t.Fatal(err) + } +} + +func (tma *testMpoolApi) setStateNonce(addr address.Address, v uint64) { + tma.statenonce[addr] = v +} + +func (tma *testMpoolApi) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) { + tma.bmsgs[h.Cid()] = msgs +} + +func (tma *testMpoolApi) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) { + tma.cb = cb +} + +func (tma *testMpoolApi) PutMessage(m store.ChainMsg) (cid.Cid, error) { + return cid.Undef, nil +} + +func (tma *testMpoolApi) PubSubPublish(string, []byte) error { + return nil +} + +func (tma *testMpoolApi) StateGetActor(addr address.Address, ts *types.TipSet) (*types.Actor, error) { + return &types.Actor{ + Nonce: tma.statenonce[addr], + Balance: types.NewInt(90000000), + }, nil +} + +func (tma *testMpoolApi) MessagesForBlock(h *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) { + return nil, tma.bmsgs[h.Cid()], nil +} + +func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, error) { + if len(ts.Blocks()) != 1 { + panic("cant deal with multiblock tipsets in this test") + } + + bm, sm, err := tma.MessagesForBlock(ts.Blocks()[0]) + if err != nil { + return nil, err + } + + var out []store.ChainMsg + for _, m := range bm { + out = append(out, m) + } + + for _, m := range sm { + out = append(out, m) + } + + return out, nil +} + +func assertNonce(t *testing.T, mp *MessagePool, addr address.Address, val uint64) { + t.Helper() + n, err := mp.GetNonce(addr) + if err != nil { + t.Fatal(err) + } + + if n != val { + t.Fatalf("expected nonce of %d, got %d", val, n) + } +} + +func mustAdd(t *testing.T, mp *MessagePool, msg *types.SignedMessage) { + t.Helper() + if err := mp.Add(msg); err != nil { + t.Fatal(err) + } +} + +func TestMessagePool(t *testing.T) { + tma := newTestMpoolApi() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + ds := datastore.NewMapDatastore() + + mp, err := NewMessagePool(tma, ds) + if err != nil { + t.Fatal(err) + } + + a := mock.MkBlock(nil, 1, 1) + + sender, err := w.GenerateKey(types.KTBLS) + if err != nil { + t.Fatal(err) + } + target := mock.Address(1001) + + var msgs []*types.SignedMessage + for i := 0; i < 5; i++ { + msgs = append(msgs, mock.MkMessage(sender, target, uint64(i), w)) + } + + tma.setStateNonce(sender, 0) + assertNonce(t, mp, sender, 0) + mustAdd(t, mp, msgs[0]) + assertNonce(t, mp, sender, 1) + mustAdd(t, mp, msgs[1]) + assertNonce(t, mp, sender, 2) + + tma.setBlockMessages(a, msgs[0], msgs[1]) + tma.applyBlock(t, a) + + assertNonce(t, mp, sender, 2) +} diff --git a/chain/store/store.go b/chain/store/store.go index 879f16c32..9f977b161 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -601,6 +601,7 @@ func (cs *ChainStore) readAMTCids(root cid.Cid) ([]cid.Cid, error) { type ChainMsg interface { Cid() cid.Cid VMMessage() *types.Message + ToStorageBlock() (block.Block, error) } func (cs *ChainStore) MessagesForTipset(ts *types.TipSet) ([]ChainMsg, error) { diff --git a/chain/types/mock/chain.go b/chain/types/mock/chain.go index 37d2e8a53..f51573d03 100644 --- a/chain/types/mock/chain.go +++ b/chain/types/mock/chain.go @@ -1,10 +1,12 @@ package mock import ( + "context" "fmt" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/wallet" "github.com/ipfs/go-cid" ) @@ -16,6 +18,26 @@ func Address(i uint64) address.Address { return a } +func MkMessage(from, to address.Address, nonce uint64, w *wallet.Wallet) *types.SignedMessage { + msg := &types.Message{ + To: to, + From: from, + Value: types.NewInt(1), + Nonce: nonce, + GasLimit: types.NewInt(1), + GasPrice: types.NewInt(0), + } + + sig, err := w.Sign(context.TODO(), from, msg.Cid().Bytes()) + if err != nil { + panic(err) + } + return &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } +} + func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types.BlockHeader { addr := Address(123561) diff --git a/miner/miner.go b/miner/miner.go index 370014777..f15b8e013 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -279,7 +279,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB if err != nil { return nil, xerrors.Errorf("failed to create block: %w", err) } - log.Infow("mined new block", "cid", b.Cid()) + log.Infow("mined new block", "cid", b.Cid(), "height", b.Header.Height) dur := time.Now().Sub(start) log.Infof("Creating block took %s", dur) diff --git a/node/modules/chain.go b/node/modules/chain.go index b6fb29c8c..4e0b9d1e8 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -42,7 +42,8 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt } func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*chain.MessagePool, error) { - mp, err := chain.NewMessagePool(sm, ps, ds) + mpp := chain.NewMpoolProvider(sm, ps) + mp, err := chain.NewMessagePool(mpp, ds) if err != nil { return nil, xerrors.Errorf("constructing mpool: %w", err) } From b58e7344e87234816c82ae3b69723e5860b50881 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Sun, 1 Dec 2019 16:11:43 -0700 Subject: [PATCH 80/93] pull messagepool into separate package --- chain/{ => messagepool}/messagepool.go | 8 ++++++-- chain/{ => messagepool}/messagepool_test.go | 2 +- chain/sub/incoming.go | 3 ++- chain/sync.go | 8 ++++---- node/builder.go | 3 ++- node/impl/full/mpool.go | 4 ++-- node/modules/chain.go | 7 ++++--- node/modules/services.go | 3 ++- 8 files changed, 23 insertions(+), 15 deletions(-) rename chain/{ => messagepool}/messagepool.go (98%) rename chain/{ => messagepool}/messagepool_test.go (99%) diff --git a/chain/messagepool.go b/chain/messagepool/messagepool.go similarity index 98% rename from chain/messagepool.go rename to chain/messagepool/messagepool.go index 79b0ac315..586e71432 100644 --- a/chain/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -1,4 +1,4 @@ -package chain +package messagepool import ( "bytes" @@ -13,6 +13,7 @@ import ( "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/query" + logging "github.com/ipfs/go-log" pubsub "github.com/libp2p/go-libp2p-pubsub" lps "github.com/whyrusleeping/pubsub" "go.uber.org/multierr" @@ -20,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/address" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -27,6 +29,8 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" ) +var log = logging.Logger("messagepool") + var ( ErrMessageTooBig = errors.New("message too big") @@ -567,7 +571,7 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err sub := mp.changes.Sub(localUpdates) go func() { - defer mp.changes.Unsub(sub, localIncoming) + defer mp.changes.Unsub(sub, chain.LocalIncoming) for { select { diff --git a/chain/messagepool_test.go b/chain/messagepool/messagepool_test.go similarity index 99% rename from chain/messagepool_test.go rename to chain/messagepool/messagepool_test.go index f76ed5422..d7c462d3e 100644 --- a/chain/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -1,4 +1,4 @@ -package chain +package messagepool import ( "testing" diff --git a/chain/sub/incoming.go b/chain/sub/incoming.go index a2d46a824..b09d0c227 100644 --- a/chain/sub/incoming.go +++ b/chain/sub/incoming.go @@ -7,6 +7,7 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/filecoin-project/lotus/chain" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" ) @@ -54,7 +55,7 @@ func HandleIncomingBlocks(ctx context.Context, bsub *pubsub.Subscription, s *cha } } -func HandleIncomingMessages(ctx context.Context, mpool *chain.MessagePool, msub *pubsub.Subscription) { +func HandleIncomingMessages(ctx context.Context, mpool *messagepool.MessagePool, msub *pubsub.Subscription) { for { msg, err := msub.Next(ctx) if err != nil { diff --git a/chain/sync.go b/chain/sync.go index dbf974cfa..774f18f95 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -39,7 +39,7 @@ import ( var log = logging.Logger("chain") -var localIncoming = "incoming" +var LocalIncoming = "incoming" type Syncer struct { // The heaviest known tipset in the network. @@ -119,7 +119,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) { } } - syncer.incoming.Pub(fts.TipSet().Blocks(), localIncoming) + syncer.incoming.Pub(fts.TipSet().Blocks(), LocalIncoming) if from == syncer.self { // TODO: this is kindof a hack... @@ -152,11 +152,11 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) { } func (syncer *Syncer) IncomingBlocks(ctx context.Context) (<-chan *types.BlockHeader, error) { - sub := syncer.incoming.Sub(localIncoming) + sub := syncer.incoming.Sub(LocalIncoming) out := make(chan *types.BlockHeader, 10) go func() { - defer syncer.incoming.Unsub(sub, localIncoming) + defer syncer.incoming.Unsub(sub, LocalIncoming) for { select { diff --git a/node/builder.go b/node/builder.go index 412730fab..bc8dbea59 100644 --- a/node/builder.go +++ b/node/builder.go @@ -24,6 +24,7 @@ import ( "github.com/filecoin-project/lotus/chain/deals" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/market" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/metrics" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" @@ -202,7 +203,7 @@ func Online() Option { // Filecoin services Override(new(*chain.Syncer), modules.NewSyncer), Override(new(*blocksync.BlockSync), blocksync.NewBlockSyncClient), - Override(new(*chain.MessagePool), modules.MessagePool), + Override(new(*messagepool.MessagePool), modules.MessagePool), Override(new(modules.Genesis), modules.ErrorGenesis), Override(SetGenesisKey, modules.SetGenesis), diff --git a/node/impl/full/mpool.go b/node/impl/full/mpool.go index db318a083..9ea34a7d1 100644 --- a/node/impl/full/mpool.go +++ b/node/impl/full/mpool.go @@ -7,8 +7,8 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/lotus/api" - "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/address" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/types" ) @@ -17,7 +17,7 @@ type MpoolAPI struct { WalletAPI - Mpool *chain.MessagePool + Mpool *messagepool.MessagePool } func (a *MpoolAPI) MpoolPending(ctx context.Context, ts *types.TipSet) ([]*types.SignedMessage, error) { diff --git a/node/modules/chain.go b/node/modules/chain.go index 4e0b9d1e8..093573d76 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -19,6 +19,7 @@ import ( "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/blocksync" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -41,9 +42,9 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt return exch } -func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*chain.MessagePool, error) { - mpp := chain.NewMpoolProvider(sm, ps) - mp, err := chain.NewMessagePool(mpp, ds) +func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*messagepool.MessagePool, error) { + mpp := messagepool.NewMpoolProvider(sm, ps) + mp, err := messagepool.NewMessagePool(mpp, ds) if err != nil { return nil, xerrors.Errorf("constructing mpool: %w", err) } diff --git a/node/modules/services.go b/node/modules/services.go index 8cf298d8a..12b3f02c5 100644 --- a/node/modules/services.go +++ b/node/modules/services.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/lotus/chain" "github.com/filecoin-project/lotus/chain/blocksync" "github.com/filecoin-project/lotus/chain/deals" + "github.com/filecoin-project/lotus/chain/messagepool" "github.com/filecoin-project/lotus/chain/sub" "github.com/filecoin-project/lotus/node/hello" "github.com/filecoin-project/lotus/node/modules/helpers" @@ -53,7 +54,7 @@ func HandleIncomingBlocks(mctx helpers.MetricsCtx, lc fx.Lifecycle, pubsub *pubs go sub.HandleIncomingBlocks(ctx, blocksub, s) } -func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, pubsub *pubsub.PubSub, mpool *chain.MessagePool) { +func HandleIncomingMessages(mctx helpers.MetricsCtx, lc fx.Lifecycle, pubsub *pubsub.PubSub, mpool *messagepool.MessagePool) { ctx := helpers.LifecycleCtx(mctx, lc) msgsub, err := pubsub.Subscribe("/fil/messages") From 68e25b36f1bf2a18251f91fe85703b9f4bb7f8b9 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 11:39:50 -0800 Subject: [PATCH 81/93] rename to avoid stuttering --- chain/messagepool/messagepool.go | 8 ++++---- chain/messagepool/messagepool_test.go | 2 +- node/modules/chain.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 586e71432..0ae7791d1 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -65,7 +65,7 @@ type MessagePool struct { curTsLk sync.RWMutex curTs *types.TipSet - api MpoolProvider + api Provider minGasPrice types.BigInt @@ -105,7 +105,7 @@ func (ms *msgSet) add(m *types.SignedMessage) error { return nil } -type MpoolProvider interface { +type Provider interface { SubscribeHeadChanges(func(rev, app []*types.TipSet) error) PutMessage(m store.ChainMsg) (cid.Cid, error) PubSubPublish(string, []byte) error @@ -119,7 +119,7 @@ type mpoolProvider struct { ps *pubsub.PubSub } -func NewMpoolProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) MpoolProvider { +func NewProvider(sm *stmgr.StateManager, ps *pubsub.PubSub) Provider { return &mpoolProvider{sm, ps} } @@ -147,7 +147,7 @@ func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, return mpp.sm.ChainStore().MessagesForTipset(ts) } -func NewMessagePool(api MpoolProvider, ds dtypes.MetadataDS) (*MessagePool, error) { +func New(api Provider, ds dtypes.MetadataDS) (*MessagePool, error) { cache, _ := lru.New2Q(build.BlsSignatureCacheSize) mp := &MessagePool{ closer: make(chan struct{}), diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index d7c462d3e..1c42e5b18 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -115,7 +115,7 @@ func TestMessagePool(t *testing.T) { ds := datastore.NewMapDatastore() - mp, err := NewMessagePool(tma, ds) + mp, err := New(tma, ds) if err != nil { t.Fatal(err) } diff --git a/node/modules/chain.go b/node/modules/chain.go index 093573d76..728b4e7a1 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -43,8 +43,8 @@ func ChainExchange(mctx helpers.MetricsCtx, lc fx.Lifecycle, host host.Host, rt } func MessagePool(lc fx.Lifecycle, sm *stmgr.StateManager, ps *pubsub.PubSub, ds dtypes.MetadataDS) (*messagepool.MessagePool, error) { - mpp := messagepool.NewMpoolProvider(sm, ps) - mp, err := messagepool.NewMessagePool(mpp, ds) + mpp := messagepool.NewProvider(sm, ps) + mp, err := messagepool.New(mpp, ds) if err != nil { return nil, xerrors.Errorf("constructing mpool: %w", err) } From e366db00fe13f9faff4b7656f18d581016e535f7 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 12:46:25 -0800 Subject: [PATCH 82/93] fix lame deadlock and revert handling --- chain/messagepool/messagepool.go | 41 ++++++++++++++++++++------- chain/messagepool/messagepool_test.go | 4 +++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 0ae7791d1..dfa82c3fa 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -62,7 +62,7 @@ type MessagePool struct { pending map[address.Address]*msgSet pendingCount int - curTsLk sync.RWMutex + curTsLk sync.Mutex curTs *types.TipSet api Provider @@ -112,6 +112,7 @@ type Provider interface { StateGetActor(address.Address, *types.TipSet) (*types.Actor, error) MessagesForBlock(*types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) MessagesForTipset(*types.TipSet) ([]store.ChainMsg, error) + LoadTipSet(cids []cid.Cid) (*types.TipSet, error) } type mpoolProvider struct { @@ -147,6 +148,10 @@ func (mpp *mpoolProvider) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, return mpp.sm.ChainStore().MessagesForTipset(ts) } +func (mpp *mpoolProvider) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) { + return mpp.sm.ChainStore().LoadTipSet(cids) +} + func New(api Provider, ds dtypes.MetadataDS) (*MessagePool, error) { cache, _ := lru.New2Q(build.BlsSignatureCacheSize) mp := &MessagePool{ @@ -354,12 +359,23 @@ func (mp *MessagePool) getNonceLocked(addr address.Address) (uint64, error) { return stateNonce, nil } +func (mp *MessagePool) setCurTipset(ts *types.TipSet) { + mp.curTsLk.Lock() + defer mp.curTsLk.Unlock() + mp.curTs = ts +} + +func (mp *MessagePool) getCurTipset() *types.TipSet { + mp.curTsLk.Lock() + defer mp.curTsLk.Unlock() + return mp.curTs +} + func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) { // TODO: this method probably should be cached - mp.curTsLk.RLock() - defer mp.curTsLk.RUnlock() - act, err := mp.api.StateGetActor(addr, mp.curTs) + curTs := mp.getCurTipset() + act, err := mp.api.StateGetActor(addr, curTs) if err != nil { return 0, err } @@ -369,11 +385,11 @@ func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) { // TODO: the correct thing to do here is probably to set curTs to chain.head // but since we have an accurate view of the world until a head change occurs, // this should be fine - if mp.curTs == nil { + if curTs == nil { return baseNonce, nil } - msgs, err := mp.api.MessagesForTipset(mp.curTs) + msgs, err := mp.api.MessagesForTipset(curTs) if err != nil { return 0, xerrors.Errorf("failed to check messages for tipset: %w", err) } @@ -382,7 +398,7 @@ func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) { msg := m.VMMessage() if msg.From == addr { if msg.Nonce != baseNonce { - return 0, xerrors.Errorf("tipset %s has bad nonce ordering", mp.curTs) + return 0, xerrors.Errorf("tipset %s has bad nonce ordering", curTs) } baseNonce++ } @@ -500,10 +516,14 @@ func (mp *MessagePool) pendingFor(a address.Address) []*types.SignedMessage { } func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) error { - mp.curTsLk.Lock() - defer mp.curTsLk.Unlock() for _, ts := range revert { + pts, err := mp.api.LoadTipSet(ts.Parents()) + if err != nil { + return err + } + + mp.setCurTipset(pts) for _, b := range ts.Blocks() { bmsgs, smsgs, err := mp.api.MessagesForBlock(b) if err != nil { @@ -526,7 +546,6 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) } } } - mp.curTs = ts } for _, ts := range apply { @@ -543,7 +562,7 @@ func (mp *MessagePool) HeadChange(revert []*types.TipSet, apply []*types.TipSet) mp.Remove(msg.From, msg.Nonce) } } - mp.curTs = ts + mp.setCurTipset(ts) } return nil diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 1c42e5b18..d830e9fd6 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -86,6 +86,10 @@ func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, return out, nil } +func (tma *testMpoolApi) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) { + panic("dont call me unless you implement me") +} + func assertNonce(t *testing.T, mp *MessagePool, addr address.Address, val uint64) { t.Helper() n, err := mp.GetNonce(addr) From 481cc63181270af998dda7cbb62ea86bb59a540c Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 14:28:28 -0800 Subject: [PATCH 83/93] add a test for the revert messages issue --- chain/messagepool/messagepool.go | 2 +- chain/messagepool/messagepool_test.go | 74 ++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index dfa82c3fa..38b7e1fc4 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -398,7 +398,7 @@ func (mp *MessagePool) getStateNonce(addr address.Address) (uint64, error) { msg := m.VMMessage() if msg.From == addr { if msg.Nonce != baseNonce { - return 0, xerrors.Errorf("tipset %s has bad nonce ordering", curTs) + return 0, xerrors.Errorf("tipset %s has bad nonce ordering (%d != %d)", curTs.Cids(), msg.Nonce, baseNonce) } baseNonce++ } diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index d830e9fd6..1cd8f8a75 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -1,6 +1,7 @@ package messagepool import ( + "fmt" "testing" "github.com/filecoin-project/lotus/chain/address" @@ -17,6 +18,8 @@ type testMpoolApi struct { bmsgs map[cid.Cid][]*types.SignedMessage statenonce map[address.Address]uint64 + + tipsets []*types.TipSet } func newTestMpoolApi() *testMpoolApi { @@ -33,12 +36,20 @@ func (tma *testMpoolApi) applyBlock(t *testing.T, b *types.BlockHeader) { } } +func (tma *testMpoolApi) revertBlock(t *testing.T, b *types.BlockHeader) { + t.Helper() + if err := tma.cb([]*types.TipSet{mock.TipSet(b)}, nil); err != nil { + t.Fatal(err) + } +} + func (tma *testMpoolApi) setStateNonce(addr address.Address, v uint64) { tma.statenonce[addr] = v } func (tma *testMpoolApi) setBlockMessages(h *types.BlockHeader, msgs ...*types.SignedMessage) { tma.bmsgs[h.Cid()] = msgs + tma.tipsets = append(tma.tipsets, mock.TipSet(h)) } func (tma *testMpoolApi) SubscribeHeadChanges(cb func(rev, app []*types.TipSet) error) { @@ -87,7 +98,13 @@ func (tma *testMpoolApi) MessagesForTipset(ts *types.TipSet) ([]store.ChainMsg, } func (tma *testMpoolApi) LoadTipSet(cids []cid.Cid) (*types.TipSet, error) { - panic("dont call me unless you implement me") + for _, ts := range tma.tipsets { + if types.CidArrsEqual(cids, ts.Cids()) { + return ts, nil + } + } + + return nil, fmt.Errorf("tipset not found") } func assertNonce(t *testing.T, mp *MessagePool, addr address.Address, val uint64) { @@ -149,3 +166,58 @@ func TestMessagePool(t *testing.T) { assertNonce(t, mp, sender, 2) } + +func TestRevertMessages(t *testing.T) { + tma := newTestMpoolApi() + + w, err := wallet.NewWallet(wallet.NewMemKeyStore()) + if err != nil { + t.Fatal(err) + } + + ds := datastore.NewMapDatastore() + + mp, err := New(tma, ds) + if err != nil { + t.Fatal(err) + } + + a := mock.MkBlock(nil, 1, 1) + b := mock.MkBlock(mock.TipSet(a), 1, 1) + + sender, err := w.GenerateKey(types.KTBLS) + if err != nil { + t.Fatal(err) + } + target := mock.Address(1001) + + var msgs []*types.SignedMessage + for i := 0; i < 5; i++ { + msgs = append(msgs, mock.MkMessage(sender, target, uint64(i), w)) + } + + tma.setBlockMessages(a, msgs[0]) + tma.setBlockMessages(b, msgs[1], msgs[2], msgs[3]) + + mustAdd(t, mp, msgs[0]) + mustAdd(t, mp, msgs[1]) + mustAdd(t, mp, msgs[2]) + mustAdd(t, mp, msgs[3]) + + tma.setStateNonce(sender, 0) + tma.applyBlock(t, a) + assertNonce(t, mp, sender, 4) + + tma.setStateNonce(sender, 1) + tma.applyBlock(t, b) + assertNonce(t, mp, sender, 4) + tma.setStateNonce(sender, 0) + tma.revertBlock(t, b) + + assertNonce(t, mp, sender, 4) + + if len(mp.Pending()) != 3 { + t.Fatal("expected three messages in mempool") + } + +} From ab36a5aa04b3210cc514150ae037b175e7c41d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 23:46:49 +0100 Subject: [PATCH 84/93] wip fixing IsTicketWinner --- chain/gen/gen.go | 5 +---- chain/sync.go | 7 ++----- chain/types/blockheader.go | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 35bf58a38..384a89bde 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -519,10 +519,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add var winners []sectorbuilder.EPostCandidate for _, c := range candidates { - sectors := types.BigDiv(pow.MinerPower, types.NewInt(ssize)) - challangeCount := sectorbuilder.ElectionPostChallengeCount(sectors.Uint64()) - - if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower, int64(challangeCount)) { + if types.IsTicketWinner(c.PartialTicket[:], ssize, pow.TotalPower) { winners = append(winners, c) } } diff --git a/chain/sync.go b/chain/sync.go index dbf974cfa..abf8fe26d 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -545,7 +545,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } winnerCheck := async.Err(func() error { - mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) + _, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner) if err != nil { return xerrors.Errorf("failed getting power: %w", err) } @@ -556,10 +556,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } for _, t := range h.EPostProof.Candidates { - sectors := types.BigDiv(mpow, types.NewInt(ssize)) - challangeCount := sectorbuilder.ElectionPostChallengeCount(sectors.Uint64()) - - if !types.IsTicketWinner(t.Partial, ssize, tpow, int64(challangeCount)) { + if !types.IsTicketWinner(t.Partial, ssize, tpow) { return xerrors.Errorf("miner created a block but was not a winner") } } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 79585f1d2..03b03c0f3 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -172,7 +172,7 @@ func CidArrsEqual(a, b []cid.Cid) bool { var blocksPerEpoch = NewInt(build.BlocksPerEpoch) -func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt, sampleRate int64) bool { +func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt) bool { ssize := NewInt(ssizeI) /* @@ -189,7 +189,7 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt, sampleRa lhs := BigFromBytes(h[:]).Int lhs = lhs.Mul(lhs, totpow.Int) - lhs = lhs.Mul(lhs, big.NewInt(sampleRate)) + lhs = lhs.Mul(lhs, big.NewInt(build.SectorChallengeRatioDiv)) // rhs = sectorSize * 2^256 // rhs = sectorSize << 256 From fd92b8f19a6b781c26ffa77177505623aa827528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 2 Dec 2019 23:49:41 +0100 Subject: [PATCH 85/93] Type 256 differently --- chain/types/blockheader.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 03b03c0f3..f00e8a0c3 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -172,6 +172,8 @@ func CidArrsEqual(a, b []cid.Cid) bool { var blocksPerEpoch = NewInt(build.BlocksPerEpoch) +const sha256bits = 256 + func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt) bool { ssize := NewInt(ssizeI) @@ -193,7 +195,7 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt) bool { // rhs = sectorSize * 2^256 // rhs = sectorSize << 256 - rhs := new(big.Int).Lsh(ssize.Int, 256) + rhs := new(big.Int).Lsh(ssize.Int, sha256bits) rhs = rhs.Mul(rhs, blocksPerEpoch.Int) // h(vrfout) * totalPower < e * sectorSize * 2^256? From adcda68d6266e7332d562cf7186020357e8a977d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 00:18:27 +0100 Subject: [PATCH 86/93] fix winner math --- chain/types/blockheader.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index f00e8a0c3..aec7d8514 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -191,15 +191,15 @@ func IsTicketWinner(partialTicket []byte, ssizeI uint64, totpow BigInt) bool { lhs := BigFromBytes(h[:]).Int lhs = lhs.Mul(lhs, totpow.Int) - lhs = lhs.Mul(lhs, big.NewInt(build.SectorChallengeRatioDiv)) // rhs = sectorSize * 2^256 // rhs = sectorSize << 256 rhs := new(big.Int).Lsh(ssize.Int, sha256bits) + rhs = rhs.Mul(rhs, big.NewInt(build.SectorChallengeRatioDiv)) rhs = rhs.Mul(rhs, blocksPerEpoch.Int) // h(vrfout) * totalPower < e * sectorSize * 2^256? - return lhs.Cmp(rhs) == -1 + return lhs.Cmp(rhs) < 0 } func (t *Ticket) Equals(ot *Ticket) bool { From 96f17d4408c918c9a63ef57803af68494d921de7 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 15:24:46 -0800 Subject: [PATCH 87/93] remove dead code --- chain/gen/gen.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 384a89bde..c35ca5ce9 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -612,16 +612,3 @@ func ComputeVRF(ctx context.Context, sign SignFunc, worker, miner address.Addres return sig.Data, nil } - -func TicketHash(t *types.Ticket, addr address.Address) []byte { - h := sha256.New() - - h.Write(t.VRFProof) - - // Field Delimeter - h.Write([]byte{0}) - - h.Write(addr.Bytes()) - - return h.Sum(nil) -} From 4500a36ec68e40767bc65439cf8351975b9bf504 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Mon, 2 Dec 2019 16:08:08 -0800 Subject: [PATCH 88/93] some useful log messages --- miner/miner.go | 3 +++ storage/miner.go | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/miner/miner.go b/miner/miner.go index f15b8e013..ef5ef0b7c 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -283,6 +283,9 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB dur := time.Now().Sub(start) log.Infof("Creating block took %s", dur) + if dur > time.Second*build.BlockDelay { + log.Warn("CAUTION: block production took longer than the block delay. Your computer may not be fast enough to keep up") + } return b, nil } diff --git a/storage/miner.go b/storage/miner.go index 3f78e7ca7..524319033 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -4,6 +4,7 @@ import ( "context" "errors" "sync" + "time" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" @@ -154,11 +155,17 @@ func NewElectionPoStProver(sb *sectorbuilder.SectorBuilder) *SectorBuilderEpp { var _ gen.ElectionPoStProver = (*SectorBuilderEpp)(nil) func (epp *SectorBuilderEpp) GenerateCandidates(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte) ([]sectorbuilder.EPostCandidate, error) { + start := time.Now() var faults []uint64 // TODO var randbuf [32]byte copy(randbuf[:], rand) - return epp.sb.GenerateEPostCandidates(ssi, randbuf, faults) + cds, err := epp.sb.GenerateEPostCandidates(ssi, randbuf, faults) + if err != nil { + return nil, err + } + log.Infof("Generate candidates took %s", time.Since(start)) + return cds, nil } func (epp *SectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo, rand []byte, winners []sectorbuilder.EPostCandidate) ([]byte, error) { @@ -166,5 +173,11 @@ func (epp *SectorBuilderEpp) ComputeProof(ctx context.Context, ssi sectorbuilder log.Warn("Generating fake EPost proof! You should only see this while running tests!") return []byte("valid proof"), nil } - return epp.sb.ComputeElectionPoSt(ssi, rand, winners) + start := time.Now() + proof, err := epp.sb.ComputeElectionPoSt(ssi, rand, winners) + if err != nil { + return nil, err + } + log.Infof("ComputeElectionPost took %s", time.Since(start)) + return proof, nil } From 5ba4dfdf148df156262509384500fc5ed19e7f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 01:44:52 +0100 Subject: [PATCH 89/93] Devnet 9 --- build/genesis/devnet.car | Bin 2419 -> 3055 bytes build/params_devnet.go | 8 ++++---- build/params_shared.go | 1 - cmd/lotus-storage-miner/init.go | 7 ++++++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/build/genesis/devnet.car b/build/genesis/devnet.car index 07aa06257a319e7c53e1204938282c06a8ada6ba..ab806416a9e8163724cc699d24aca782b1145440 100644 GIT binary patch literal 3055 zcmcCnlvK<76H9C=ycVQz+S&8d4* z>V=MLvg;pJ@AGxsa_spTB&CdJC)M9MTWRrYmyw;(a~_uv>8|Flcc#crXiH6fANA1- zNoj9BALj#Cv(_Dr8B@=OEq|wfE`dSqo$?x&*oqGd2TwWpG8Jd0=Ovbu7Nr7#RP57r zcY~Rda`Kb26_6!%utI{0kRzKSG0OUk&h!b-&^HPhD{3_m)H$UdB#&zCn>yEGTbBVs2 zG(n%ke4a{=e4zBB88Xipy%`u2V&}bVQx|}n$qY0z5M(9~)Xc=9>{Mi5OP$$W!F`)S znf?1yjkjE@6ZZO=Z<&(guy9`Mi}Iq?8oS}XPNCS>K=%osS*r2<$oT@e`MD;2?pT#t^AZ9g?C6rL+bl z13-xjVgQI03Ne6C5^F+^q7MtV{8$if#J}8e`=s4>m&Ju8-(zrg3(;b#Ju~}sSGXke zi|LFIW5o$5Z3>6wENBLUP!0@D;N((a$lUq!mGq+9R$k}K60@~#m*$=9I?lCY<>#&s zH@YHC_P?z8$o%U1*9+eq#r4a7JjmTAC6NNwS<0m4`Kn)Ry7)%dP~L?MQ57$~RNVU{ zkt&CgIUqp+%_-2}B$P`QNTDTQXu1QX`(>E;GG~V~lgU%6zB%NCxA(u}?Hmac)hE3>soU&)Ctt4VBFE|5Wk3Jx zn>#W%GPr^Zx-Se2#gG^yj~k`4*g@m*W;BJ$V7 zkIM`8G^_|Y zv?YS{gg}Ot%!1U^A_Y$u1w$!N=`Vv`qCjIAT)Najf{Ree(u@>y692N!BraZ@&0}uk zW!1OLyHWeoso6md0Tbp_T;T}q;z3gSSZVp~vnDrHgI$)Z9@ChvV`ls*fbZ#(N0lqq ziF8T*T*9acv7V5TO%4tBpzQ-fMuH=j5g4&eU4$b}is2tHfXE19Cx%o>Wep&5aEM4` znh$u zT&_bB37FXmP2Pmc_g18sw|8C>bD}c!(q<;*X8y*1Pn@)+cLzIcJLR^eFL;i|?E^?k z%bm5A84Tjr{ZPKw__iZ?sRF0m7vI-@p(iRUW3SF$)5{3W+%Ax`LdfK%AYhG(1{z_t zHe)2j5JGmsQW26fMITJ!FyVQpv00wy@xx=E=AK(|p|~Qp?6|#O`-HzcolZfWM@Si7 k=Y7+KIFC@9vYCOQ*`cAK7NVL^vl6+|BV;m?hY2YK00VagGynhq delta 1002 zcmaDa{#j^(NZ9_kgowpF6FTRXNzT97BAlB(CB0?e+m4RkYx0bjf7~vWUY1%^oSC1; z*v-UPxZnws0wE1OP7Dl<6El?^0!uPd72H$vQj0T-6_RrDld~Hf7;b1qs53wes$=kN zIng0zGST+U>5RPkJ^x?&9enfef5@aPGr{%+>0c+lPP0GzB|Vr4tXH8pGd(Y{q_ij% z2tKe7XT;RjE>Jf-C=mw zuAUgR}wdlItxBfV5dX<}ZF}+;+l9Dy*ogWZ^L x0=ms^KJgncFdGt@7HlGY@yNET2~OpfPzGP#hu4giLPwaNeh diff --git a/build/params_devnet.go b/build/params_devnet.go index 2a18b9372..c2c1c3905 100644 --- a/build/params_devnet.go +++ b/build/params_devnet.go @@ -3,19 +3,19 @@ package build // Seconds -const BlockDelay = 12 +const BlockDelay = 30 // FallbackPoStDelay is the number of epochs the miner needs to wait after // ElectionPeriodStart before starting fallback post computation // // Epochs -const FallbackPoStDelay = 1000 +const FallbackPoStDelay = 30 // SlashablePowerDelay is the number of epochs after ElectionPeriodStart, after // which the miner is slashed // // Epochs -const SlashablePowerDelay = 2000 +const SlashablePowerDelay = 200 // Epochs -const InteractivePoRepDelay = 10 +const InteractivePoRepDelay = 8 diff --git a/build/params_shared.go b/build/params_shared.go index 0134084bf..40eb643f0 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -13,7 +13,6 @@ const UnixfsChunkSize uint64 = 1 << 20 const UnixfsLinksPerLevel = 1024 var SectorSizes = []uint64{ - 1 << 10, 16 << 20, 256 << 20, 1 << 30, diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 9e95feb96..5250b8f7f 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -367,9 +367,14 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api lapi.FullNode, } if pssb := cctx.String("pre-sealed-sectors"); pssb != "" { + pssb, err := homedir.Expand(pssb) + if err != nil { + return err + } + log.Infof("Importing pre-sealed sector metadata for %s", a) - if err := migratePreSealMeta(ctx, api, cctx.String("pre-sealed-sectors"), a, mds); err != nil { + if err := migratePreSealMeta(ctx, api, pssb, a, mds); err != nil { return xerrors.Errorf("migrating presealed sector metadata: %w", err) } } From 536c9985ab77b6770901372497b62730476f8cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 01:53:15 +0100 Subject: [PATCH 90/93] bootstrap addresses --- build/bootstrap/bootstrappers.pi | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 build/bootstrap/bootstrappers.pi diff --git a/build/bootstrap/bootstrappers.pi b/build/bootstrap/bootstrappers.pi new file mode 100644 index 000000000..124dcce60 --- /dev/null +++ b/build/bootstrap/bootstrappers.pi @@ -0,0 +1,3 @@ +/ip4/147.75.80.17/tcp/1347/p2p/12D3KooWPWCCqUN3gPEaFAMpAwfh5a6SryBEsFt5R2oK8oW86a4C +/ip6/2604:1380:2000:f400::1/tcp/36137/p2p/12D3KooWNL1fJPBArhsoqwg2wbXgCDTByMyg4ZGp6HjgWr9bgnaJ +/ip4/147.75.80.29/tcp/44397/p2p/12D3KooWNL1fJPBArhsoqwg2wbXgCDTByMyg4ZGp6HjgWr9bgnaJ From ad27131dcf0aa869f48173c7dd63b88c6e66d9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 02:41:31 +0100 Subject: [PATCH 91/93] fix node_test --- node/node_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/node/node_test.go b/node/node_test.go index 190440416..2e64c1fbc 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/rand" + "github.com/filecoin-project/lotus/build" "io/ioutil" "net/http/httptest" "path/filepath" @@ -39,6 +40,8 @@ import ( func init() { _ = logging.SetLogLevel("*", "INFO") + + build.SectorSizes = []uint64{1024} } func testStorageNode(ctx context.Context, t *testing.T, waddr address.Address, act address.Address, pk crypto.PrivKey, tnd test.TestNode, mn mocknet.Mocknet) test.TestStorageNode { From dab80b30f6d570d45af749a7364168206dca633d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 02:46:29 +0100 Subject: [PATCH 92/93] storageminer: print fallback start in info --- cmd/lotus-storage-miner/info.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/lotus-storage-miner/info.go b/cmd/lotus-storage-miner/info.go index 27c6271ef..917b71bc7 100644 --- a/cmd/lotus-storage-miner/info.go +++ b/cmd/lotus-storage-miner/info.go @@ -72,11 +72,15 @@ var infoCmd = &cli.Command{ lastEps := int64(head.Height() - eps) lastEpsS := lastEps * build.BlockDelay + fallback := lastEps + build.FallbackPoStDelay + fallbackS := fallback * build.BlockDelay + next := lastEps + build.SlashablePowerDelay nextS := next * build.BlockDelay fmt.Printf("PoSt Submissions:\n") fmt.Printf("\tPrevious: Epoch %d (%d block(s), ~%dm %ds ago)\n", eps, lastEps, lastEpsS/60, lastEpsS%60) + fmt.Printf("\tFallback: Epoch %d (in %d blocks, ~%dm %ds)\n", eps+build.FallbackPoStDelay, fallback, fallbackS/60, fallbackS%60) fmt.Printf("\tDeadline: Epoch %d (in %d blocks, ~%dm %ds)\n", eps+build.SlashablePowerDelay, next, nextS/60, nextS%60) } else { From 7d13b284395bad43291334f69e035b329689eb7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 02:55:10 +0100 Subject: [PATCH 93/93] Fix tests using 1k sectors --- chain/gen/gen_test.go | 6 ++++++ chain/sync_test.go | 1 + 2 files changed, 7 insertions(+) diff --git a/chain/gen/gen_test.go b/chain/gen/gen_test.go index 399742f5f..3ab989e72 100644 --- a/chain/gen/gen_test.go +++ b/chain/gen/gen_test.go @@ -2,8 +2,14 @@ package gen import ( "testing" + + "github.com/filecoin-project/lotus/build" ) +func init() { + build.SectorSizes = []uint64{1024} +} + func testGeneration(t testing.TB, n int, msgs int) { g, err := NewGenerator() if err != nil { diff --git a/chain/sync_test.go b/chain/sync_test.go index f8c387a1e..30c770195 100644 --- a/chain/sync_test.go +++ b/chain/sync_test.go @@ -27,6 +27,7 @@ import ( func init() { build.InsecurePoStValidation = true os.Setenv("TRUST_PARAMS", "1") + build.SectorSizes = []uint64{1024} } const source = 0
idActiveClientProviderSizePriceDuration