From b7c6333fef6e49a7e0e115abbd067b33e25b054e Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Tue, 6 Aug 2019 23:35:57 -0700 Subject: [PATCH 1/4] implement sector commitments and proof verification --- api/api.go | 9 ++ api/struct.go | 11 +++ chain/actors/actor_miner.go | 54 ++++++++--- chain/actors/params.go | 1 + chain/vm/invoker.go | 18 ++-- cli/cmd.go | 1 + cli/state.go | 140 +++++++++++++++++++++++++++++ go.mod | 10 +-- go.sum | 8 ++ lib/sectorbuilder/sectorbuilder.go | 30 +++++-- node/impl/full.go | 125 ++++++++++++++++++++++++++ storage/miner.go | 2 +- 12 files changed, 379 insertions(+), 30 deletions(-) create mode 100644 cli/state.go diff --git a/api/api.go b/api/api.go index 068997bc9..6ffbdd3e7 100644 --- a/api/api.go +++ b/api/api.go @@ -46,6 +46,12 @@ type BlockMessages struct { SecpkMessages []*types.SignedMessage } +type SectorInfo struct { + SectorID uint64 + CommD []byte + CommR []byte +} + type Common interface { // Auth AuthVerify(ctx context.Context, token string) ([]string, error) @@ -117,6 +123,9 @@ type FullNode interface { ClientListImports(ctx context.Context) ([]Import, error) //ClientListAsks() []Ask + + StateMinerSectors(context.Context, address.Address) ([]*SectorInfo, error) + StateMinerProvingSet(context.Context, address.Address) ([]*SectorInfo, error) } // Full API is a low-level interface to the Filecoin network storage miner node diff --git a/api/struct.go b/api/struct.go index bf08bda83..a0032de64 100644 --- a/api/struct.go +++ b/api/struct.go @@ -63,6 +63,9 @@ type FullNodeStruct struct { ClientImport func(ctx context.Context, path string) (cid.Cid, error) `perm:"write"` ClientListImports func(ctx context.Context) ([]Import, error) `perm:"read"` + + StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"` + StateMinerProvingSet func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"` } } @@ -196,6 +199,14 @@ func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan *store.HeadCha return c.Internal.ChainNotify(ctx) } +func (c *FullNodeStruct) StateMinerSectors(ctx context.Context, addr address.Address) ([]*SectorInfo, error) { + return c.Internal.StateMinerSectors(ctx, addr) +} + +func (c *FullNodeStruct) StateMinerProvingSet(ctx context.Context, addr address.Address) ([]*SectorInfo, error) { + return c.Internal.StateMinerProvingSet(ctx, addr) +} + func (c *StorageMinerStruct) StoreGarbageData(ctx context.Context) (uint64, error) { return c.Internal.StoreGarbageData(ctx) } diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 4fc7fc6fa..a3f9faab9 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -6,6 +6,7 @@ import ( "github.com/filecoin-project/go-lotus/chain/actors/aerrors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/types" + "github.com/filecoin-project/go-lotus/lib/sectorbuilder" "golang.org/x/xerrors" cid "github.com/ipfs/go-cid" @@ -190,7 +191,7 @@ func (sma StorageMinerActor) StorageMinerConstructor(act *types.Actor, vmctx typ } type CommitSectorParams struct { - SectorId types.BigInt + SectorID types.BigInt CommD []byte CommR []byte CommRStar []byte @@ -208,12 +209,17 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex return nil, err } - if !ValidatePoRep(mi.SectorSize, params) { + // TODO: this needs to get normalized to either the ID address or the actor address + maddr := vmctx.Message().To + + if ok, err := ValidatePoRep(maddr, mi.SectorSize, params); err != nil { + return nil, err + } else if !ok { return nil, aerrors.New(1, "bad proof!") } // make sure the miner isnt trying to submit a pre-existing sector - unique, err := SectorIsUnique(vmctx.Ipld(), self.Sectors, params.SectorId) + unique, err := SectorIsUnique(vmctx.Ipld(), self.Sectors, params.SectorID) if err != nil { return nil, err } @@ -237,7 +243,7 @@ func (sma StorageMinerActor) CommitSector(act *types.Actor, vmctx types.VMContex // 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(self.Sectors, params.SectorId, params.CommR, params.CommD) + nssroot, err := AddToSectorSet(context.TODO(), vmctx.Ipld(), self.Sectors, params.SectorID, params.CommR, params.CommD) if err != nil { return nil, err } @@ -330,25 +336,53 @@ func (sma StorageMinerActor) GetPower(act *types.Actor, vmctx types.VMContext, p func SectorIsUnique(cst *hamt.CborIpldStore, sroot cid.Cid, sid types.BigInt) (bool, ActorError) { nd, err := hamt.LoadNode(context.TODO(), cst, sroot) if err != nil { - return false, aerrors.Absorb(err, 1, "could not load node in HAMT") + return false, aerrors.Escalate(err, "could not load node in HAMT") } if _, err := nd.Find(context.TODO(), sid.String()); err != nil { if xerrors.Is(err, hamt.ErrNotFound) { return true, nil } - return false, aerrors.Absorb(err, 1, "could not find node in HAMT") + return false, aerrors.Escalate(err, "could not find node in HAMT") } return false, nil } -func AddToSectorSet(ss cid.Cid, sectorID types.BigInt, commR, commD []byte) (cid.Cid, ActorError) { - panic("NYI") +func AddToSectorSet(ctx context.Context, cst *hamt.CborIpldStore, ss cid.Cid, sectorID types.BigInt, commR, commD []byte) (cid.Cid, ActorError) { + nd, err := hamt.LoadNode(ctx, cst, ss) + if err != nil { + return cid.Undef, aerrors.Escalate(err, "could not load HAMT node") + } + + enc, aerr := SerializeParams([][]byte{commR, commD}) + if err != nil { + return cid.Undef, aerrors.Wrap(aerr, "failed to serialize commR and commD for sector set") + } + + if err := nd.Set(ctx, sectorID.String(), enc); err != nil { + return cid.Undef, aerrors.Escalate(err, "failed to set new sector in sector set") + } + + if err := nd.Flush(ctx); err != nil { + return cid.Undef, aerrors.Escalate(err, "failed to flush sector set") + } + + ssroot, err := cst.Put(ctx, nd) + if err != nil { + return cid.Undef, aerrors.Escalate(err, "failed to store new sector set root") + } + + return ssroot, nil } -func ValidatePoRep(ssize types.BigInt, params *CommitSectorParams) bool { - return true +func ValidatePoRep(maddr address.Address, ssize types.BigInt, params *CommitSectorParams) (bool, ActorError) { + ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID.Uint64(), params.Proof) + if err != nil { + return false, aerrors.Escalate(err, "verify seal failed") + } + + return ok, nil } func CollateralForPower(power types.BigInt) types.BigInt { diff --git a/chain/actors/params.go b/chain/actors/params.go index 208673bcb..b899e10c0 100644 --- a/chain/actors/params.go +++ b/chain/actors/params.go @@ -12,6 +12,7 @@ var ( func SerializeParams(i interface{}) ([]byte, aerrors.ActorError) { dump, err := cbor.DumpObject(i) if err != nil { + // TODO: shouldnt this be a fatal error? return nil, aerrors.Absorb(err, 1, "failed to encode parameter") } return dump, nil diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 795cdf03e..7052a03af 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -114,14 +114,16 @@ func (*invoker) transform(instance Invokee) (nativeCode, error) { param := reflect.New(paramT) inBytes := in[2].Interface().([]byte) - err := cbor.DecodeInto(inBytes, param.Interface()) - if err != nil { - aerr := aerrors.Absorb(err, 1, "failed to decode parameters") - return []reflect.Value{ - reflect.ValueOf([]byte{}), - // Below is a hack, fixed in Go 1.13 - // https://git.io/fjXU6 - reflect.ValueOf(&aerr).Elem(), + if len(inBytes) > 0 { + err := cbor.DecodeInto(inBytes, param.Interface()) + if err != nil { + aerr := aerrors.Absorb(err, 1, "failed to decode parameters") + return []reflect.Value{ + reflect.ValueOf([]byte{}), + // Below is a hack, fixed in Go 1.13 + // https://git.io/fjXU6 + reflect.ValueOf(&aerr).Elem(), + } } } diff --git a/cli/cmd.go b/cli/cmd.go index 9d444f533..1816122fb 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -108,4 +108,5 @@ var Commands = []*cli.Command{ versionCmd, walletCmd, createMinerCmd, + stateCmd, } diff --git a/cli/state.go b/cli/state.go new file mode 100644 index 000000000..e195a6e12 --- /dev/null +++ b/cli/state.go @@ -0,0 +1,140 @@ +package cli + +import ( + "fmt" + "math/big" + + "gopkg.in/urfave/cli.v2" + + "github.com/filecoin-project/go-lotus/chain/actors" + "github.com/filecoin-project/go-lotus/chain/address" + types "github.com/filecoin-project/go-lotus/chain/types" +) + +var stateCmd = &cli.Command{ + Name: "state", + Usage: "Interact with and query filecoin chain state", + Subcommands: []*cli.Command{ + statePowerCmd, + stateSectorsCmd, + stateProvingSetCmd, + }, +} + +var statePowerCmd = &cli.Command{ + Name: "power", + Usage: "Query network or miner power", + Action: func(cctx *cli.Context) error { + api, err := GetAPI(cctx) + if err != nil { + return err + } + + ctx := ReqContext(cctx) + + var msg *types.Message + if cctx.Args().Present() { + maddr, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + enc, err := actors.SerializeParams(&actors.PowerLookupParams{ + Miner: maddr, + }) + if err != nil { + return err + } + + msg = &types.Message{ + To: actors.StorageMarketAddress, + From: actors.StorageMarketAddress, + Method: actors.SMAMethods.PowerLookup, + Params: enc, + } + } else { + msg = &types.Message{ + To: actors.StorageMarketAddress, + From: actors.StorageMarketAddress, + Method: actors.SMAMethods.GetTotalStorage, + } + } + ret, err := api.ChainCall(ctx, msg, nil) + if err != nil { + return err + } + if ret.ExitCode != 0 { + return fmt.Errorf("call to get power failed: %d", ret.ExitCode) + } + + v := big.NewInt(0).SetBytes(ret.Return) + fmt.Println(v.String()) + return nil + }, +} + +var stateSectorsCmd = &cli.Command{ + Name: "sectors", + Usage: "Query the sector set of a miner", + Action: func(cctx *cli.Context) error { + api, err := GetAPI(cctx) + if err != nil { + return err + } + + ctx := ReqContext(cctx) + + if !cctx.Args().Present() { + return fmt.Errorf("must specify miner to list sectors for") + } + + maddr, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + sectors, err := api.StateMinerSectors(ctx, maddr) + if err != nil { + return err + } + + for _, s := range sectors { + fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD) + } + + return nil + }, +} + +var stateProvingSetCmd = &cli.Command{ + Name: "proving", + Usage: "Query the proving set of a miner", + Action: func(cctx *cli.Context) error { + api, err := GetAPI(cctx) + if err != nil { + return err + } + + ctx := ReqContext(cctx) + + if !cctx.Args().Present() { + return fmt.Errorf("must specify miner to list sectors for") + } + + maddr, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + sectors, err := api.StateMinerProvingSet(ctx, maddr) + if err != nil { + return err + } + + for _, s := range sectors { + fmt.Printf("%d: %x %x\n", s.SectorID, s.CommR, s.CommD) + } + + return nil + }, +} diff --git a/go.mod b/go.mod index e46c1852e..2215a07db 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/ipfs/go-ds-badger v0.0.5 github.com/ipfs/go-filestore v0.0.2 github.com/ipfs/go-fs-lock v0.0.1 - github.com/ipfs/go-hamt-ipld v0.0.10 + github.com/ipfs/go-hamt-ipld v0.0.11 github.com/ipfs/go-ipfs-blockstore v0.0.1 github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-exchange-interface v0.0.1 @@ -61,10 +61,10 @@ require ( github.com/multiformats/go-multiaddr-net v0.0.1 github.com/multiformats/go-multihash v0.0.6 github.com/pkg/errors v0.8.1 - github.com/polydawn/refmt v0.0.0-20190731040541-eff0b363297a + github.com/polydawn/refmt v0.0.0-20190804001829-26ba426d088b github.com/prometheus/common v0.6.0 github.com/smartystreets/assertions v1.0.1 // indirect - github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect + github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect github.com/stretchr/testify v1.3.0 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d @@ -76,8 +76,8 @@ require ( go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect - golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect - golang.org/x/sys v0.0.0-20190730183949-1393eb018365 // indirect + golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect + golang.org/x/tools v0.0.0-20190806215303-88ddfcebc769 // indirect golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect diff --git a/go.sum b/go.sum index 4708c9385..599dd9db3 100644 --- a/go.sum +++ b/go.sum @@ -159,6 +159,8 @@ github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0 github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y= github.com/ipfs/go-hamt-ipld v0.0.10 h1:jmJGsV/8OPpBEmO+b1nAPpqX8SG2kLeYveKk8F7IxG4= github.com/ipfs/go-hamt-ipld v0.0.10/go.mod h1:WrX60HHX2SeMb602Z1s9Ztnf/4fzNHzwH9gxNTVpEmk= +github.com/ipfs/go-hamt-ipld v0.0.11 h1:iUHlbycdlheWf7QLU3FjHonK2lEnd+/85SeM5gvcUZE= +github.com/ipfs/go-hamt-ipld v0.0.11/go.mod h1:WrX60HHX2SeMb602Z1s9Ztnf/4fzNHzwH9gxNTVpEmk= github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc= github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08= github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= @@ -463,6 +465,8 @@ github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14 h1:2m16U/rLwVaRdz7A github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190731040541-eff0b363297a h1:TdavzKWkPcC2G+6rKJclm/JfrWC6WZFfLUR7EJJX8MA= github.com/polydawn/refmt v0.0.0-20190731040541-eff0b363297a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.0.0-20190804001829-26ba426d088b h1:JWrXOvqGFU2mv58NZSqEinWkezjkcGam1jNKSIV5Meg= +github.com/polydawn/refmt v0.0.0-20190804001829-26ba426d088b/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -488,6 +492,7 @@ github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI= github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= @@ -626,6 +631,8 @@ golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190730183949-1393eb018365 h1:SaXEMXhWzMJThc05vu6uh61Q245r4KaWMrsTedk0FDc= golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -637,6 +644,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190806215303-88ddfcebc769/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 81d036e6e..23d840ae6 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -2,6 +2,7 @@ package sectorbuilder import ( "context" + "encoding/binary" "unsafe" "github.com/filecoin-project/go-lotus/chain/address" @@ -29,10 +30,9 @@ type SectorBuilderConfig struct { } func New(cfg *SectorBuilderConfig) (*SectorBuilder, error) { - var proverId [31]byte - copy(proverId[:], cfg.Miner.Payload()) + proverId := addressToProverID(cfg.Miner) - sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, 2, 2, 1, cfg.MetadataDir, [31]byte{}, cfg.SealedDir, cfg.StagedDir, 16) + sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, 2, 2, 1, cfg.MetadataDir, proverId, cfg.SealedDir, cfg.StagedDir, 16) if err != nil { return nil, err } @@ -42,6 +42,18 @@ func New(cfg *SectorBuilderConfig) (*SectorBuilder, error) { }, nil } +func addressToProverID(a address.Address) [31]byte { + var proverId [31]byte + copy(proverId[:], a.Payload()) + return proverId +} + +func sectorIDtoBytes(sid uint64) [31]byte { + var out [31]byte + binary.LittleEndian.PutUint64(out[:], sid) + return out +} + func (sb *SectorBuilder) Run(ctx context.Context) { go sb.pollForSealedSectors(ctx) } @@ -84,9 +96,15 @@ func (sb *SectorBuilder) SealedSectorChan() <-chan SectorSealingStatus { var UserBytesForSectorSize = sectorbuilder.GetMaxUserBytesPerStagedSector -func VerifySeal(sectorSize uint64, commR, commD, commRStar [CommLen]byte, proverID address.Address, sectorID uint64, proof []byte) (bool, error) { - panic("TODO") - // return sectorbuilder.VerifySeal(sectorSize, commR, commD, commRStar, providerID, sectorID, proof) +func VerifySeal(sectorSize uint64, commR, commD, commRStar []byte, proverID address.Address, sectorID uint64, proof []byte) (bool, error) { + var commRa, commDa, commRStara [32]byte + copy(commRa[:], commR) + copy(commDa[:], commD) + copy(commRStara[:], commRStar) + proverIDa := addressToProverID(proverID) + sectorIDa := sectorIDtoBytes(sectorID) + + return sectorbuilder.VerifySeal(sectorSize, commRa, commDa, commRStara, proverIDa, sectorIDa, proof) } func VerifyPost(sectorSize uint64, sortedCommRs [][CommLen]byte, challengeSeed [CommLen]byte, proofs [][]byte, faults []uint64) (bool, error) { diff --git a/node/impl/full.go b/node/impl/full.go index 573c0830e..a996e1a91 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -2,13 +2,17 @@ package impl import ( "context" + "fmt" + "strconv" "golang.org/x/xerrors" "github.com/filecoin-project/go-lotus/api" "github.com/filecoin-project/go-lotus/chain" + "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/gen" + "github.com/filecoin-project/go-lotus/chain/state" "github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/vm" @@ -17,6 +21,8 @@ import ( "github.com/filecoin-project/go-lotus/node/client" "github.com/ipfs/go-cid" + hamt "github.com/ipfs/go-hamt-ipld" + cbor "github.com/ipfs/go-ipld-cbor" logging "github.com/ipfs/go-log" pubsub "github.com/libp2p/go-libp2p-pubsub" ) @@ -120,6 +126,9 @@ func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *typ // TODO: maybe just use the invoker directly? ret, err := vmi.ApplyMessage(ctx, msg) + if ret.ActorErr != nil { + log.Warnf("chain call failed: %s", ret.ActorErr) + } return &ret.MessageReceipt, err } @@ -201,4 +210,120 @@ func (a *FullNodeAPI) WalletDefaultAddress(ctx context.Context) (address.Address return addrs[0], nil } +func (a *FullNodeAPI) StateMinerSectors(ctx context.Context, addr address.Address) ([]*api.SectorInfo, error) { + ts := a.Chain.GetHeaviestTipSet() + + stc, err := a.Chain.TipSetState(ts.Cids()) + if err != nil { + return nil, err + } + + cst := hamt.CSTFromBstore(a.Chain.Blockstore()) + + st, err := state.LoadStateTree(cst, stc) + if err != nil { + return nil, err + } + + act, err := st.GetActor(addr) + if err != nil { + return nil, err + } + + var minerState actors.StorageMinerActorState + if err := cst.Get(ctx, act.Head, &minerState); err != nil { + return nil, err + } + + nd, err := hamt.LoadNode(ctx, cst, minerState.Sectors) + if err != nil { + return nil, err + } + + var sinfos []*api.SectorInfo + // Note to self: the hamt isnt a great data structure to use here... need to implement the sector set + err = nd.ForEach(ctx, func(k string, val interface{}) error { + sid, err := strconv.ParseUint(k, 10, 64) + if err != nil { + return err + } + + bval, ok := val.([]byte) + if !ok { + return fmt.Errorf("expected to get bytes in sector set hamt") + } + + var comms [][]byte + if err := cbor.DecodeInto(bval, &comms); err != nil { + return err + } + + sinfos = append(sinfos, &api.SectorInfo{ + SectorID: sid, + CommR: comms[0], + CommD: comms[1], + }) + return nil + }) + return sinfos, nil +} + +func (a *FullNodeAPI) StateMinerProvingSet(ctx context.Context, addr address.Address) ([]*api.SectorInfo, error) { + ts := a.Chain.GetHeaviestTipSet() + + stc, err := a.Chain.TipSetState(ts.Cids()) + if err != nil { + return nil, err + } + + cst := hamt.CSTFromBstore(a.Chain.Blockstore()) + + st, err := state.LoadStateTree(cst, stc) + if err != nil { + return nil, err + } + + act, err := st.GetActor(addr) + if err != nil { + return nil, err + } + + var minerState actors.StorageMinerActorState + if err := cst.Get(ctx, act.Head, &minerState); err != nil { + return nil, err + } + + nd, err := hamt.LoadNode(ctx, cst, minerState.ProvingSet) + if err != nil { + return nil, err + } + + var sinfos []*api.SectorInfo + // Note to self: the hamt isnt a great data structure to use here... need to implement the sector set + err = nd.ForEach(ctx, func(k string, val interface{}) error { + sid, err := strconv.ParseUint(k, 10, 64) + if err != nil { + return err + } + + bval, ok := val.([]byte) + if !ok { + return fmt.Errorf("expected to get bytes in sector set hamt") + } + + var comms [][]byte + if err := cbor.DecodeInto(bval, &comms); err != nil { + return err + } + + sinfos = append(sinfos, &api.SectorInfo{ + SectorID: sid, + CommR: comms[0], + CommD: comms[1], + }) + return nil + }) + return sinfos, nil +} + var _ api.FullNode = &FullNodeAPI{} diff --git a/storage/miner.go b/storage/miner.go index 2d99afa17..0a4ea8822 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -97,7 +97,7 @@ func (m *Miner) handlePostingSealedSectors(ctx context.Context) { func (m *Miner) commitSector(ctx context.Context, sinfo sectorbuilder.SectorSealingStatus) error { params := &actors.CommitSectorParams{ - SectorId: types.NewInt(sinfo.SectorID), + SectorID: types.NewInt(sinfo.SectorID), CommD: sinfo.CommD[:], CommR: sinfo.CommR[:], CommRStar: sinfo.CommRStar[:], From 5c32725510e122a160bb7cfe6169be389003b9c0 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 7 Aug 2019 16:22:35 -0700 Subject: [PATCH 2/4] sector commitments make it all the way to the chain --- api/api.go | 1 + api/struct.go | 5 ++ chain/gen/mining.go | 9 ++- chain/types/bigint.go | 9 +++ cli/chain.go | 11 +++- cli/cmd.go | 1 + cli/send.go | 94 ++++++++++++++++++++++++++++++ go.mod | 8 +-- lib/sectorbuilder/poll.go | 7 ++- lib/sectorbuilder/sectorbuilder.go | 5 ++ node/builder.go | 2 +- node/impl/full.go | 27 +++++++++ node/modules/storageminer.go | 1 + storage/miner.go | 5 +- 14 files changed, 174 insertions(+), 11 deletions(-) create mode 100644 cli/send.go diff --git a/api/api.go b/api/api.go index 6ffbdd3e7..9017921bd 100644 --- a/api/api.go +++ b/api/api.go @@ -84,6 +84,7 @@ type FullNode interface { ChainWaitMsg(context.Context, cid.Cid) (*MsgWait, error) ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error) ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error) + ChainGetBlockReceipts(context.Context, cid.Cid) ([]*types.MessageReceipt, error) // if tipset is nil, we'll use heaviest ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) diff --git a/api/struct.go b/api/struct.go index a0032de64..c125c7bdd 100644 --- a/api/struct.go +++ b/api/struct.go @@ -46,6 +46,7 @@ type FullNodeStruct struct { ChainWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"` ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"` ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"` + ChainGetBlockReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` ChainCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"` MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"` @@ -195,6 +196,10 @@ func (c *FullNodeStruct) ChainGetBlockMessages(ctx context.Context, b cid.Cid) ( return c.Internal.ChainGetBlockMessages(ctx, b) } +func (c *FullNodeStruct) ChainGetBlockReceipts(ctx context.Context, b cid.Cid) ([]*types.MessageReceipt, error) { + return c.Internal.ChainGetBlockReceipts(ctx, b) +} + func (c *FullNodeStruct) ChainNotify(ctx context.Context) (<-chan *store.HeadChange, error) { return c.Internal.ChainNotify(ctx) } diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 733a0a717..13804ca5b 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -2,6 +2,7 @@ package gen import ( "context" + "fmt" bls "github.com/filecoin-project/go-bls-sigs" cid "github.com/ipfs/go-cid" @@ -69,14 +70,20 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A if err != nil { return nil, errors.Wrap(err, "apply message failure") } + if rec.ActorErr != nil { + fmt.Println(rec.ActorErr) + } - receipts = append(receipts, rec) + receipts = append(receipts, rec.MessageReceipt) } for _, msg := range secpkMessages { rec, err := vmi.ApplyMessage(ctx, &msg.Message) if err != nil { return nil, errors.Wrap(err, "apply message failure") } + if rec.ActorErr != nil { + fmt.Println(rec.ActorErr) + } receipts = append(receipts, rec.MessageReceipt) } diff --git a/chain/types/bigint.go b/chain/types/bigint.go index 23027c4ab..062ea44eb 100644 --- a/chain/types/bigint.go +++ b/chain/types/bigint.go @@ -41,6 +41,15 @@ func BigFromBytes(b []byte) BigInt { return BigInt{i} } +func BigFromString(s string) (BigInt, error) { + v, ok := big.NewInt(0).SetString(s, 10) + if !ok { + return BigInt{}, fmt.Errorf("failed to parse string as a big int") + } + + return BigInt{v}, nil +} + func BigMul(a, b BigInt) BigInt { return BigInt{big.NewInt(0).Mul(a.Int, b.Int)} } diff --git a/cli/chain.go b/cli/chain.go index 5f32a2264..a3459a38b 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -86,15 +86,22 @@ var chainGetBlock = &cli.Command{ return err } + recpts, err := api.ChainGetBlockReceipts(ctx, bcid) + if err != nil { + return err + } + cblock := struct { types.BlockHeader - BlsMessages []*types.Message - SecpkMessages []*types.SignedMessage + BlsMessages []*types.Message + SecpkMessages []*types.SignedMessage + MessageReceipts []*types.MessageReceipt }{} cblock.BlockHeader = *blk cblock.BlsMessages = msgs.BlsMessages cblock.SecpkMessages = msgs.SecpkMessages + cblock.MessageReceipts = recpts out, err := json.MarshalIndent(cblock, "", " ") if err != nil { diff --git a/cli/cmd.go b/cli/cmd.go index 1816122fb..c1faa92f1 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -109,4 +109,5 @@ var Commands = []*cli.Command{ walletCmd, createMinerCmd, stateCmd, + sendCmd, } diff --git a/cli/send.go b/cli/send.go new file mode 100644 index 000000000..37d2d334d --- /dev/null +++ b/cli/send.go @@ -0,0 +1,94 @@ +package cli + +import ( + "fmt" + + "github.com/filecoin-project/go-lotus/chain/address" + types "github.com/filecoin-project/go-lotus/chain/types" + "gopkg.in/urfave/cli.v2" +) + +var sendCmd = &cli.Command{ + Name: "send", + Usage: "send funds between accounts", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "source", + Usage: "optinally specifiy the account to send funds from", + }, + }, + Action: func(cctx *cli.Context) error { + api, err := GetAPI(cctx) + if err != nil { + return err + } + + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 2 { + return fmt.Errorf("'send' expects two arguments, target and amount") + } + + toAddr, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + val, err := types.BigFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + var fromAddr address.Address + if from := cctx.String("source"); from == "" { + defaddr, err := api.WalletDefaultAddress(ctx) + if err != nil { + return err + } + + fromAddr = defaddr + } else { + addr, err := address.NewFromString(from) + if err != nil { + return err + } + + fromAddr = addr + } + + nonce, err := api.MpoolGetNonce(ctx, fromAddr) + if err != nil { + return err + } + + msg := &types.Message{ + From: fromAddr, + To: toAddr, + Value: val, + Nonce: nonce, + GasLimit: types.NewInt(10000), + GasPrice: types.NewInt(1), + } + + sermsg, err := msg.Serialize() + if err != nil { + return err + } + + sig, err := api.WalletSign(ctx, fromAddr, sermsg) + if err != nil { + return err + } + + smsg := &types.SignedMessage{ + Message: *msg, + Signature: *sig, + } + + if err := api.MpoolPush(ctx, smsg); err != nil { + return err + } + + return nil + }, +} diff --git a/go.mod b/go.mod index 2215a07db..29d51b76a 100644 --- a/go.mod +++ b/go.mod @@ -61,10 +61,10 @@ require ( github.com/multiformats/go-multiaddr-net v0.0.1 github.com/multiformats/go-multihash v0.0.6 github.com/pkg/errors v0.8.1 - github.com/polydawn/refmt v0.0.0-20190804001829-26ba426d088b + github.com/polydawn/refmt v0.0.0-20190731040541-eff0b363297a github.com/prometheus/common v0.6.0 github.com/smartystreets/assertions v1.0.1 // indirect - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect + github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect github.com/stretchr/testify v1.3.0 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d @@ -76,8 +76,8 @@ require ( go4.org v0.0.0-20190313082347-94abd6928b1d // indirect golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect - golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect - golang.org/x/tools v0.0.0-20190806215303-88ddfcebc769 // indirect + golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect + golang.org/x/sys v0.0.0-20190730183949-1393eb018365 // indirect golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect diff --git a/lib/sectorbuilder/poll.go b/lib/sectorbuilder/poll.go index 0e93efc16..d0af6270b 100644 --- a/lib/sectorbuilder/poll.go +++ b/lib/sectorbuilder/poll.go @@ -3,12 +3,12 @@ package sectorbuilder import ( "context" "time" - - "github.com/prometheus/common/log" ) // TODO: really need to get a callbacks API from the rust-sectorbuilder func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { + log.Info("starting sealed sector poller") + defer log.Info("leaving sealed sector polling routine") watching := make(map[uint64]bool) staged, err := sb.GetAllStagedSectors() @@ -33,9 +33,11 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { log.Errorf("in loop: failed to get staged sectors: %s", err) continue } + log.Info("num staged sectors: ", len(staged)) for _, s := range staged { watching[s.SectorID] = true } + log.Info("len watching: ", len(watching)) for s := range watching { status, err := sb.SealStatus(s) @@ -44,6 +46,7 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { continue } + log.Infof("sector %d has status %d", s, status.SealStatusCode) if status.SealStatusCode == 0 { // constant pls, zero implies the last step? delete(watching, s) sb.sschan <- status diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 23d840ae6..96bed72dc 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -7,8 +7,12 @@ import ( "github.com/filecoin-project/go-lotus/chain/address" sectorbuilder "github.com/filecoin-project/go-sectorbuilder" + + logging "github.com/ipfs/go-log" ) +var log = logging.Logger("sectorbuilder") + type SectorSealingStatus = sectorbuilder.SectorSealingStatus type StagedSectorMetadata = sectorbuilder.StagedSectorMetadata @@ -39,6 +43,7 @@ func New(cfg *SectorBuilderConfig) (*SectorBuilder, error) { return &SectorBuilder{ handle: sbp, + sschan: make(chan SectorSealingStatus, 32), }, nil } diff --git a/node/builder.go b/node/builder.go index a4c23a9bb..cf32623c4 100644 --- a/node/builder.go +++ b/node/builder.go @@ -211,7 +211,7 @@ func Online() Option { // Storage miner ApplyIf(func(s *Settings) bool { return s.nodeType == nodeStorageMiner }, - Override(new(*sectorbuilder.SectorBuilder), sectorbuilder.New), + Override(new(*sectorbuilder.SectorBuilder), modules.SectorBuilder), Override(new(*storage.Miner), modules.StorageMiner), ), ) diff --git a/node/impl/full.go b/node/impl/full.go index a996e1a91..d9467a403 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -100,6 +100,31 @@ func (a *FullNodeAPI) ChainGetBlockMessages(ctx context.Context, msg cid.Cid) (* }, nil } +func (a *FullNodeAPI) ChainGetBlockReceipts(ctx context.Context, bcid cid.Cid) ([]*types.MessageReceipt, error) { + b, err := a.Chain.GetBlock(bcid) + if err != nil { + return nil, err + } + + // TODO: need to get the number of messages better than this + bm, sm, err := a.Chain.MessagesForBlock(b) + if err != nil { + return nil, err + } + + var out []*types.MessageReceipt + for i := 0; i < len(bm)+len(sm); i++ { + r, err := a.Chain.GetReceipt(b, i) + if err != nil { + return nil, err + } + + out = append(out, r) + } + + return out, nil +} + func (a *FullNodeAPI) ChainCall(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) { if ts == nil { ts = a.Chain.GetHeaviestTipSet() @@ -240,6 +265,8 @@ func (a *FullNodeAPI) StateMinerSectors(ctx context.Context, addr address.Addres return nil, err } + log.Info("miner sector count: ", minerState.SectorSetSize) + var sinfos []*api.SectorInfo // Note to self: the hamt isnt a great data structure to use here... need to implement the sector set err = nd.ForEach(ctx, func(k string, val interface{}) error { diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 9668b64fd..2bcbf656a 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -76,6 +76,7 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h return nil, err } + log.Infof("setting up miner: %s", maddr) sm, err := storage.NewMiner(api, maddr, h, ds, sb, w) if err != nil { return nil, err diff --git a/storage/miner.go b/storage/miner.go index 0a4ea8822..9a3c988e0 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -73,15 +73,18 @@ func (m *Miner) Run(ctx context.Context) error { } func (m *Miner) handlePostingSealedSectors(ctx context.Context) { + defer log.Info("leaving handle posting sealed sectors routine") for { select { case sinfo, ok := <-m.sb.SealedSectorChan(): + log.Info("got a sealed sector notification!") if !ok { // TODO: set some state variable so that this state can be // visible via some status command log.Warning("sealed sector channel closed, aborting process") return } + log.Info("about to send commit sector message: ", sinfo.SectorID, m.maddr) if err := m.commitSector(ctx, sinfo); err != nil { log.Errorf("failed to commit sector: %s", err) @@ -114,7 +117,7 @@ func (m *Miner) commitSector(ctx context.Context, sinfo sectorbuilder.SectorSeal Method: actors.MAMethods.CommitSector, Params: enc, Value: types.NewInt(0), // TODO: need to ensure sufficient collateral - GasLimit: types.NewInt(10000 /* i dont know help */), + GasLimit: types.NewInt(1000 /* i dont know help */), GasPrice: types.NewInt(1), } From ba0d6485461947b2ddbe7f68528b4641969a2c29 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 7 Aug 2019 18:16:58 -0700 Subject: [PATCH 3/4] sealing garbage data into a sector that gets accepted by the chain works! --- chain/actors/actor_miner.go | 1 + chain/gen/mining.go | 7 --- lib/sectorbuilder/poll.go | 2 +- lib/sectorbuilder/sectorbuilder.go | 2 +- lib/sectorbuilder/sectorbuilder_test.go | 65 +++++++++++++++++++++++++ node/modules/storageminer.go | 32 ++++++------ storage/miner.go | 9 +++- 7 files changed, 93 insertions(+), 25 deletions(-) create mode 100644 lib/sectorbuilder/sectorbuilder_test.go diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index a3f9faab9..8eb8e6ac1 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -377,6 +377,7 @@ func AddToSectorSet(ctx context.Context, cst *hamt.CborIpldStore, ss cid.Cid, se } func ValidatePoRep(maddr address.Address, ssize types.BigInt, params *CommitSectorParams) (bool, ActorError) { + log.Infof("VALIDATE POREP: %d %x %x %x %s %d %x", ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID.Uint64(), params.Proof) ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID.Uint64(), params.Proof) if err != nil { return false, aerrors.Escalate(err, "verify seal failed") diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 13804ca5b..9872bff32 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -2,7 +2,6 @@ package gen import ( "context" - "fmt" bls "github.com/filecoin-project/go-bls-sigs" cid "github.com/ipfs/go-cid" @@ -70,9 +69,6 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A if err != nil { return nil, errors.Wrap(err, "apply message failure") } - if rec.ActorErr != nil { - fmt.Println(rec.ActorErr) - } receipts = append(receipts, rec.MessageReceipt) } @@ -81,9 +77,6 @@ func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.A if err != nil { return nil, errors.Wrap(err, "apply message failure") } - if rec.ActorErr != nil { - fmt.Println(rec.ActorErr) - } receipts = append(receipts, rec.MessageReceipt) } diff --git a/lib/sectorbuilder/poll.go b/lib/sectorbuilder/poll.go index d0af6270b..d2200af80 100644 --- a/lib/sectorbuilder/poll.go +++ b/lib/sectorbuilder/poll.go @@ -21,7 +21,7 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { watching[s.SectorID] = true } - tick := time.Tick(time.Second * 30) + tick := time.Tick(time.Second * 5) for { select { case <-tick: diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 96bed72dc..63cc10988 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -36,7 +36,7 @@ type SectorBuilderConfig struct { func New(cfg *SectorBuilderConfig) (*SectorBuilder, error) { proverId := addressToProverID(cfg.Miner) - sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, 2, 2, 1, cfg.MetadataDir, proverId, cfg.SealedDir, cfg.StagedDir, 16) + sbp, err := sectorbuilder.InitSectorBuilder(cfg.SectorSize, 1, 1, 1, cfg.MetadataDir, proverId, cfg.SealedDir, cfg.StagedDir, 16) if err != nil { return nil, err } diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go new file mode 100644 index 000000000..211bbcbbc --- /dev/null +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -0,0 +1,65 @@ +package sectorbuilder + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "math/rand" + "testing" + + "github.com/filecoin-project/go-lotus/chain/address" +) + +func TestSealAndVerify(t *testing.T) { + t.Skip("this is slow") + dir, err := ioutil.TempDir("", "sbtest") + if err != nil { + t.Fatal(err) + } + + addr, err := address.NewFromString("t1tct3nfaw2q543xtybxcyw4deyxmfwkjk43u4t5y") + if err != nil { + t.Fatal(err) + } + + sb, err := New(&SectorBuilderConfig{ + SectorSize: 1024, + SealedDir: dir, + StagedDir: dir, + MetadataDir: dir, + Miner: addr, + }) + if err != nil { + t.Fatal(err) + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + sb.Run(ctx) + + fi, err := ioutil.TempFile("", "sbtestfi") + if err != nil { + t.Fatal(err) + } + defer fi.Close() + + io.CopyN(fi, rand.New(rand.NewSource(42)), 1016) + + if _, err := sb.AddPiece("foo", 1016, fi.Name()); err != nil { + t.Fatal(err) + } + + ssinfo := <-sb.SealedSectorChan() + fmt.Println("sector sealed...") + + ok, err := VerifySeal(1024, ssinfo.CommR[:], ssinfo.CommD[:], ssinfo.CommRStar[:], addr, ssinfo.SectorID, ssinfo.Proof) + if err != nil { + t.Fatal(err) + } + + if !ok { + t.Fatal("proof failed to validate") + } +} diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index 2bcbf656a..1ff4ed221 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -18,8 +18,22 @@ import ( "github.com/filecoin-project/go-lotus/storage" ) -func SectorBuilderConfig(storagePath string) func() (*sectorbuilder.SectorBuilderConfig, error) { - return func() (*sectorbuilder.SectorBuilderConfig, error) { +func minerAddrFromDS(ds dtypes.MetadataDS) (address.Address, error) { + maddrb, err := ds.Get(datastore.NewKey("miner-address")) + if err != nil { + return address.Undef, err + } + + return address.NewFromBytes(maddrb) +} + +func SectorBuilderConfig(storagePath string) func(dtypes.MetadataDS) (*sectorbuilder.SectorBuilderConfig, error) { + return func(ds dtypes.MetadataDS) (*sectorbuilder.SectorBuilderConfig, error) { + minerAddr, err := minerAddrFromDS(ds) + if err != nil { + return nil, err + } + sp, err := homedir.Expand(storagePath) if err != nil { return nil, err @@ -29,12 +43,6 @@ func SectorBuilderConfig(storagePath string) func() (*sectorbuilder.SectorBuilde sealed := filepath.Join(sp, "sealed") staging := filepath.Join(sp, "staging") - // TODO: get the address of the miner actor - minerAddr, err := address.NewIDAddress(42) - if err != nil { - return nil, err - } - sb := §orbuilder.SectorBuilderConfig{ Miner: minerAddr, SectorSize: 1024, @@ -66,17 +74,11 @@ func SectorBuilder(mctx helpers.MetricsCtx, lc fx.Lifecycle, sbc *sectorbuilder. } func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h host.Host, ds dtypes.MetadataDS, sb *sectorbuilder.SectorBuilder, w *wallet.Wallet) (*storage.Miner, error) { - maddrb, err := ds.Get(datastore.NewKey("miner-address")) + maddr, err := minerAddrFromDS(ds) if err != nil { return nil, err } - maddr, err := address.NewFromBytes(maddrb) - if err != nil { - return nil, err - } - - log.Infof("setting up miner: %s", maddr) sm, err := storage.NewMiner(api, maddr, h, ds, sb, w) if err != nil { return nil, err diff --git a/storage/miner.go b/storage/miner.go index 9a3c988e0..d99d00620 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -99,6 +99,14 @@ func (m *Miner) handlePostingSealedSectors(ctx context.Context) { } func (m *Miner) commitSector(ctx context.Context, sinfo sectorbuilder.SectorSealingStatus) error { + ok, err := sectorbuilder.VerifySeal(1024, sinfo.CommR[:], sinfo.CommD[:], sinfo.CommRStar[:], m.maddr, sinfo.SectorID, sinfo.Proof) + if err != nil { + log.Error("failed to verify seal we just created: ", err) + } + if !ok { + log.Error("seal we just created failed verification") + } + params := &actors.CommitSectorParams{ SectorID: types.NewInt(sinfo.SectorID), CommD: sinfo.CommD[:], @@ -168,7 +176,6 @@ func (m *Miner) runPreflightChecks(ctx context.Context) error { m.worker = worker - // try signing something with that key to make sure we can has, err := m.w.HasKey(worker) if err != nil { return errors.Wrap(err, "failed to check wallet for worker key") From 95e7b230ecc8fbf0f691494e48f17c83441de70e Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 7 Aug 2019 18:23:44 -0700 Subject: [PATCH 4/4] cleanup from self review --- chain/actors/actor_miner.go | 1 - lib/sectorbuilder/poll.go | 6 +----- storage/miner.go | 3 --- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 8eb8e6ac1..a3f9faab9 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -377,7 +377,6 @@ func AddToSectorSet(ctx context.Context, cst *hamt.CborIpldStore, ss cid.Cid, se } func ValidatePoRep(maddr address.Address, ssize types.BigInt, params *CommitSectorParams) (bool, ActorError) { - log.Infof("VALIDATE POREP: %d %x %x %x %s %d %x", ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID.Uint64(), params.Proof) ok, err := sectorbuilder.VerifySeal(ssize.Uint64(), params.CommR, params.CommD, params.CommRStar, maddr, params.SectorID.Uint64(), params.Proof) if err != nil { return false, aerrors.Escalate(err, "verify seal failed") diff --git a/lib/sectorbuilder/poll.go b/lib/sectorbuilder/poll.go index d2200af80..edf425f37 100644 --- a/lib/sectorbuilder/poll.go +++ b/lib/sectorbuilder/poll.go @@ -7,8 +7,6 @@ import ( // TODO: really need to get a callbacks API from the rust-sectorbuilder func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { - log.Info("starting sealed sector poller") - defer log.Info("leaving sealed sector polling routine") watching := make(map[uint64]bool) staged, err := sb.GetAllStagedSectors() @@ -33,11 +31,10 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { log.Errorf("in loop: failed to get staged sectors: %s", err) continue } - log.Info("num staged sectors: ", len(staged)) + for _, s := range staged { watching[s.SectorID] = true } - log.Info("len watching: ", len(watching)) for s := range watching { status, err := sb.SealStatus(s) @@ -46,7 +43,6 @@ func (sb *SectorBuilder) pollForSealedSectors(ctx context.Context) { continue } - log.Infof("sector %d has status %d", s, status.SealStatusCode) if status.SealStatusCode == 0 { // constant pls, zero implies the last step? delete(watching, s) sb.sschan <- status diff --git a/storage/miner.go b/storage/miner.go index d99d00620..ee90fa3b5 100644 --- a/storage/miner.go +++ b/storage/miner.go @@ -73,18 +73,15 @@ func (m *Miner) Run(ctx context.Context) error { } func (m *Miner) handlePostingSealedSectors(ctx context.Context) { - defer log.Info("leaving handle posting sealed sectors routine") for { select { case sinfo, ok := <-m.sb.SealedSectorChan(): - log.Info("got a sealed sector notification!") if !ok { // TODO: set some state variable so that this state can be // visible via some status command log.Warning("sealed sector channel closed, aborting process") return } - log.Info("about to send commit sector message: ", sinfo.SectorID, m.maddr) if err := m.commitSector(ctx, sinfo); err != nil { log.Errorf("failed to commit sector: %s", err)