diff --git a/build/params.go b/build/params.go index f69fb05ef..ef55c01bd 100644 --- a/build/params.go +++ b/build/params.go @@ -37,7 +37,7 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours // Consensus / Network // Seconds -const BlockDelay = 10 +const BlockDelay = 2 // Seconds const AllowableClockDrift = BlockDelay * 2 diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 46ab1b00e..010d32729 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -227,11 +227,11 @@ func (sma StorageMinerActor) PreCommitSector(act *types.Actor, vmctx types.VMCon return nil, err } - if params.Epoch >= vmctx.BlockHeight() { - return nil, aerrors.Newf(1, "sector commitment must be based off past randomness (%d >= %d)", params.Epoch, vmctx.BlockHeight()) + if params.Epoch >= vmctx.BlockHeight()+build.SealRandomnessLookback { + return nil, aerrors.Newf(1, "sector commitment must be based off past randomness (%d >= %d)", params.Epoch, vmctx.BlockHeight()+build.SealRandomnessLookback) } - if vmctx.BlockHeight()-params.Epoch > 1000 { + if vmctx.BlockHeight()-params.Epoch+build.SealRandomnessLookback > 1000 { return nil, aerrors.New(2, "sector commitment must be recent enough") } @@ -318,7 +318,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC // TODO: ensure normalization to ID address maddr := vmctx.Message().To - ticket, err := vmctx.GetRandomness(us.TicketEpoch) + ticket, err := vmctx.GetRandomness(us.TicketEpoch - build.SealRandomnessLookback) if err != nil { return nil, aerrors.Wrap(err, "failed to get ticket randomness") } diff --git a/chain/actors/cbor_gen.go b/chain/actors/cbor_gen.go index 63202da1a..03a59bd4a 100644 --- a/chain/actors/cbor_gen.go +++ b/chain/actors/cbor_gen.go @@ -3771,3 +3771,112 @@ func (t *ComputeDataCommitmentParams) UnmarshalCBOR(r io.Reader) error { t.SectorSize = extra return nil } + +func (t *SectorProveCommitInfo) 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) + 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.SectorID (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.SectorID)); err != nil { + return err + } + + // t.t.DealIDs ([]uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.DealIDs)))); err != nil { + return err + } + for _, v := range t.DealIDs { + if err := cbg.CborWriteHeader(w, cbg.MajUnsignedInt, v); err != nil { + return err + } + } + return nil +} + +func (t *SectorProveCommitInfo) 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) + + 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.SectorID (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 = extra + // t.t.DealIDs ([]uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if extra > 8192 { + return fmt.Errorf("t.DealIDs: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + if extra > 0 { + t.DealIDs = make([]uint64, extra) + } + for i := 0; i < int(extra); i++ { + + maj, val, err := cbg.CborReadHeader(br) + if err != nil { + return xerrors.Errorf("failed to read uint64 for t.DealIDs slice: %w", err) + } + + if maj != cbg.MajUnsignedInt { + return xerrors.Errorf("value read for array t.DealIDs was not a uint, instead got %d", maj) + } + + t.DealIDs[i] = val + } + + return nil +} diff --git a/gen/main.go b/gen/main.go index 335aa0584..2d8d10e26 100644 --- a/gen/main.go +++ b/gen/main.go @@ -91,6 +91,7 @@ func main() { actors.ProcessStorageDealsPaymentParams{}, actors.OnChainDeal{}, actors.ComputeDataCommitmentParams{}, + actors.SectorProveCommitInfo{}, ) if err != nil { fmt.Println(err) diff --git a/node/impl/storminer.go b/node/impl/storminer.go index d9ee34463..e6bae6a22 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -2,9 +2,6 @@ package impl import ( "context" - "fmt" - "io" - "math/rand" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/address" @@ -12,8 +9,6 @@ import ( "github.com/filecoin-project/lotus/storage" "github.com/filecoin-project/lotus/storage/sector" "github.com/filecoin-project/lotus/storage/sectorblocks" - - "golang.org/x/xerrors" ) type StorageMinerAPI struct { @@ -25,6 +20,7 @@ type StorageMinerAPI struct { SectorBlocks *sectorblocks.SectorBlocks Miner *storage.Miner + Full api.FullNode } func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error) { @@ -32,28 +28,7 @@ func (sm *StorageMinerAPI) ActorAddress(context.Context) (address.Address, error } func (sm *StorageMinerAPI) StoreGarbageData(ctx context.Context) error { - ssize, err := sm.Miner.SectorSize(ctx) - if err != nil { - return xerrors.Errorf("failed to get miner sector size: %w", err) - } - go func() { - size := sectorbuilder.UserBytesForSectorSize(ssize) - - // TODO: create a deal - name := fmt.Sprintf("fake-file-%d", rand.Intn(100000000)) - sectorId, err := sm.Sectors.AddPiece(name, size, io.LimitReader(rand.New(rand.NewSource(42)), int64(size))) - if err != nil { - log.Error(err) - return - } - - if err := sm.Miner.SealSector(context.TODO(), sectorId); err != nil { - log.Error(err) - return - } - }() - - return err + return sm.Miner.StoreGarbageData(ctx) } func (sm *StorageMinerAPI) SectorsStatus(ctx context.Context, sid uint64) (sectorbuilder.SectorSealingStatus, error) { diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index a7580f84c..b95500305 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -184,7 +184,7 @@ func SealTicketGen(api api.FullNode) sector.TicketFn { } return §orbuilder.SealTicket{ - BlockHeight: ts.Height() - build.SealRandomnessLookback, + BlockHeight: ts.Height(), TicketBytes: tkt, }, nil } diff --git a/storage/garbage.go b/storage/garbage.go new file mode 100644 index 000000000..d1f396299 --- /dev/null +++ b/storage/garbage.go @@ -0,0 +1,140 @@ +package storage + +import ( + "bytes" + "context" + "fmt" + "io" + "math" + "math/rand" + + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/sectorbuilder" +) + +func (m *Miner) StoreGarbageData(_ context.Context) error { + ctx := context.TODO() + ssize, err := m.SectorSize(ctx) + if err != nil { + return xerrors.Errorf("failed to get miner sector size: %w", err) + } + go func() { + size := sectorbuilder.UserBytesForSectorSize(ssize) + + /*// Add market funds + smsg, err := m.api.MpoolPushMessage(ctx, &types.Message{ + To: actors.StorageMarketAddress, + From: m.worker, + Value: types.NewInt(size), + GasPrice: types.NewInt(0), + GasLimit: types.NewInt(1000000), + Method: actors.SMAMethods.AddBalance, + }) + if err != nil { + log.Error(err) + return + } + + r, err := m.api.StateWaitMsg(ctx, smsg.Cid()) + if err != nil { + log.Error(err) + return + } + + if r.Receipt.ExitCode != 0 { + log.Error(xerrors.Errorf("adding funds to storage miner market actor failed: exit %d", r.Receipt.ExitCode)) + return + }*/ + // Publish a deal + + // TODO: Maybe cache + commP, err := sectorbuilder.GeneratePieceCommitment(io.LimitReader(rand.New(rand.NewSource(42)), int64(size)), size) + if err != nil { + log.Error(err) + return + } + + sdp := actors.StorageDealProposal{ + PieceRef: commP[:], + PieceSize: size, + PieceSerialization: actors.SerializationUnixFSv0, + Client: m.worker, + Provider: m.worker, + ProposalExpiration: math.MaxUint64, + Duration: math.MaxUint64 / 2, // /2 because overflows + StoragePricePerEpoch: types.NewInt(0), + StorageCollateral: types.NewInt(0), + ProposerSignature: nil, + } + + if err := api.SignWith(ctx, m.api.WalletSign, m.worker, &sdp); err != nil { + log.Error(xerrors.Errorf("signing storage deal failed: ", err)) + return + } + + storageDeal := actors.StorageDeal{ + Proposal: sdp, + } + if err := api.SignWith(ctx, m.api.WalletSign, m.worker, &storageDeal); err != nil { + log.Error(xerrors.Errorf("signing storage deal failed: ", err)) + return + } + + params, err := actors.SerializeParams(&actors.PublishStorageDealsParams{ + Deals: []actors.StorageDeal{storageDeal}, + }) + if err != nil { + log.Error(xerrors.Errorf("serializing PublishStorageDeals params failed: ", err)) + } + + // TODO: We may want this to happen after fetching data + smsg, err := m.api.MpoolPushMessage(ctx, &types.Message{ + To: actors.StorageMarketAddress, + From: m.worker, + Value: types.NewInt(0), + GasPrice: types.NewInt(0), + GasLimit: types.NewInt(1000000), + Method: actors.SMAMethods.PublishStorageDeals, + Params: params, + }) + if err != nil { + log.Error(err) + return + } + r, err := m.api.StateWaitMsg(ctx, smsg.Cid()) + if err != nil { + log.Error(err) + return + } + if r.Receipt.ExitCode != 0 { + log.Error(xerrors.Errorf("publishing deal failed: exit %d", r.Receipt.ExitCode)) + } + var resp actors.PublishStorageDealResponse + if err := resp.UnmarshalCBOR(bytes.NewReader(r.Receipt.Return)); err != nil { + log.Error(err) + return + } + if len(resp.DealIDs) != 1 { + log.Error("got unexpected number of DealIDs from") + return + } + + name := fmt.Sprintf("fake-file-%d", rand.Intn(100000000)) + sectorId, err := m.secst.AddPiece(name, size, io.LimitReader(rand.New(rand.NewSource(42)), int64(size)), resp.DealIDs[0]) + if err != nil { + log.Error(err) + return + } + + if err := m.SealSector(context.TODO(), sectorId); err != nil { + log.Error(err) + return + } + }() + + return err +} diff --git a/storage/miner.go b/storage/miner.go index 4cec6c94b..ae93e78f5 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -67,6 +67,7 @@ type storageMinerApi interface { ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error) ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error) + WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) WalletBalance(context.Context, address.Address) (types.BigInt, error) WalletHas(context.Context, address.Address) (bool, error) } diff --git a/storage/sector_states.go b/storage/sector_states.go index ce4a8b28c..3e8a0f67a 100644 --- a/storage/sector_states.go +++ b/storage/sector_states.go @@ -135,14 +135,18 @@ func (m *Miner) committing(ctx context.Context, sector SectorInfo) (func(*Sector return nil, xerrors.Errorf("computing seal proof failed: %w", err) } + deals, err := m.secst.DealsForCommit(sector.SectorID) + if err != nil { + return nil, err + } + params := &actors.SectorProveCommitInfo{ Proof: proof, SectorID: sector.SectorID, - //DealIDs: deals, + DealIDs: deals, } - _ = params - enc, aerr := actors.SerializeParams(nil) + enc, aerr := actors.SerializeParams(params) if aerr != nil { return nil, xerrors.Errorf("could not serialize commit sector parameters: %w", aerr) }