diff --git a/api/api.go b/api/api.go index 159769bf6..91555f7cc 100644 --- a/api/api.go +++ b/api/api.go @@ -4,8 +4,8 @@ import ( "context" "github.com/filecoin-project/go-lotus/chain" + "github.com/filecoin-project/go-lotus/chain/address" - "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" ) @@ -20,8 +20,9 @@ type Version struct { type API interface { // chain - ChainHead(context.Context) ([]cid.Cid, error) + ChainHead(context.Context) (*chain.TipSet, error) // TODO: check serialization ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error // TODO: check serialization + ChainGetRandomness(context.Context, *chain.TipSet) ([]byte, error) // messages @@ -30,6 +31,7 @@ type API interface { // // status // // mpool // // // ls / show / rm + MpoolPending(context.Context, *chain.TipSet) ([]*chain.SignedMessage, error) // dag @@ -52,6 +54,8 @@ type API interface { // // power // // set-price // // set-perrid + MinerStart(context.Context, address.Address) error + MinerCreateBlock(context.Context, address.Address, *chain.TipSet, []chain.Ticket, chain.ElectionProof, []*chain.SignedMessage) (*chain.BlockMsg, error) // // UX ? diff --git a/api/struct.go b/api/struct.go index 89c57c5af..4a8e8662c 100644 --- a/api/struct.go +++ b/api/struct.go @@ -4,8 +4,8 @@ import ( "context" "github.com/filecoin-project/go-lotus/chain" + "github.com/filecoin-project/go-lotus/chain/address" - "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/peer" ) @@ -15,8 +15,14 @@ type Struct struct { ID func(context.Context) (peer.ID, error) Version func(context.Context) (Version, error) - ChainSubmitBlock func(ctx context.Context, blk *chain.BlockMsg) error - ChainHead func(context.Context) ([]cid.Cid, error) + ChainSubmitBlock func(ctx context.Context, blk *chain.BlockMsg) error + ChainHead func(context.Context) (*chain.TipSet, error) + ChainGetRandomness func(context.Context, *chain.TipSet) ([]byte, error) + + MpoolPending func(context.Context, *chain.TipSet) ([]*chain.SignedMessage, error) + + MinerStart func(context.Context, address.Address) error + MinerCreateBlock func(context.Context, address.Address, *chain.TipSet, []chain.Ticket, chain.ElectionProof, []*chain.SignedMessage) (*chain.BlockMsg, error) NetPeers func(context.Context) ([]peer.AddrInfo, error) NetConnect func(context.Context, peer.AddrInfo) error @@ -24,6 +30,18 @@ type Struct struct { } } +func (c *Struct) MpoolPending(ctx context.Context, ts *chain.TipSet) ([]*chain.SignedMessage, error) { + return c.Internal.MpoolPending(ctx, ts) +} + +func (c *Struct) MinerStart(ctx context.Context, addr address.Address) error { + return c.Internal.MinerStart(ctx, addr) +} + +func (c *Struct) MinerCreateBlock(ctx context.Context, addr address.Address, base *chain.TipSet, tickets []chain.Ticket, eproof chain.ElectionProof, msgs []*chain.SignedMessage) (*chain.BlockMsg, error) { + return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs) +} + func (c *Struct) NetPeers(ctx context.Context) ([]peer.AddrInfo, error) { return c.Internal.NetPeers(ctx) } @@ -40,10 +58,14 @@ func (c *Struct) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) erro return c.Internal.ChainSubmitBlock(ctx, blk) } -func (c *Struct) ChainHead(ctx context.Context) ([]cid.Cid, error) { +func (c *Struct) ChainHead(ctx context.Context) (*chain.TipSet, error) { return c.Internal.ChainHead(ctx) } +func (c *Struct) ChainGetRandomness(ctx context.Context, pts *chain.TipSet) ([]byte, error) { + return c.Internal.ChainGetRandomness(ctx, pts) +} + // ID implements API.ID func (c *Struct) ID(ctx context.Context) (peer.ID, error) { return c.Internal.ID(ctx) diff --git a/chain/chain.go b/chain/chain.go index 86956ddc6..5c1a4f7ef 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -226,7 +226,7 @@ func (cs *ChainStore) maybeTakeHeavierTipSet(ts *TipSet) error { return err } cs.headChange(revert, apply) - log.Errorf("New heaviest tipset! %s", ts.Cids()) + log.Infof("New heaviest tipset! %s", ts.Cids()) cs.heaviest = ts } return nil diff --git a/chain/mining.go b/chain/mining.go index 06a9d1050..fa8d5c567 100644 --- a/chain/mining.go +++ b/chain/mining.go @@ -3,7 +3,6 @@ package chain import ( "context" "fmt" - "time" cid "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" @@ -14,154 +13,40 @@ import ( bls "github.com/filecoin-project/go-lotus/lib/bls-signatures" ) -type Miner struct { - cs *ChainStore - newBlockCB func(*FullBlock) - - maddr address.Address - mpool *MessagePool - - Delay time.Duration - - candidate *MiningBase -} - -func NewMiner(cs *ChainStore, maddr address.Address, mpool *MessagePool, newBlockCB func(*FullBlock)) *Miner { - return &Miner{ - cs: cs, - newBlockCB: newBlockCB, - maddr: maddr, - mpool: mpool, - Delay: time.Second * 2, - } -} - -type MiningBase struct { - ts *TipSet - tickets []Ticket -} - -func (m *Miner) Mine(ctx context.Context) { - log.Error("mining...") - defer log.Error("left mining...") - for { - base := m.GetBestMiningCandidate() - - b, err := m.mineOne(ctx, base) - if err != nil { - log.Error(err) - continue - } - - if b != nil { - m.submitNewBlock(b) - } - } -} - -func (m *Miner) GetBestMiningCandidate() *MiningBase { - best := m.cs.GetHeaviestTipSet() - if m.candidate == nil { - if best == nil { - panic("no best candidate!") - } - return &MiningBase{ - ts: best, - } - } - - if m.cs.Weight(best) > m.cs.Weight(m.candidate.ts) { - return &MiningBase{ - ts: best, - } - } - - return m.candidate -} - -func (m *Miner) submitNullTicket(base *MiningBase, ticket Ticket) { - panic("nyi") -} - -func (m *Miner) isWinnerNextRound(base *MiningBase) (bool, ElectionProof, error) { - return true, []byte("election prooooof"), nil -} - -func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (Ticket, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-time.After(m.Delay): - } - - return []byte("this is a ticket"), nil -} - -func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*FullBlock, error) { - log.Info("mine one") - ticket, err := m.scratchTicket(ctx, base) - if err != nil { - return nil, errors.Wrap(err, "scratching ticket failed") - } - - win, proof, err := m.isWinnerNextRound(base) - if err != nil { - return nil, errors.Wrap(err, "failed to check if we win next round") - } - - if !win { - m.submitNullTicket(base, ticket) - return nil, nil - } - - b, err := m.createBlock(base, ticket, proof) - if err != nil { - return nil, errors.Wrap(err, "failed to create block") - } - fmt.Println("created new block:", b.Cid()) - - return b, nil -} - -func (m *Miner) submitNewBlock(b *FullBlock) { - if err := m.cs.AddBlock(b.Header); err != nil { - log.Error("failed to add new block to chainstore: ", err) - } - m.newBlockCB(b) -} - func miningRewardForBlock(base *TipSet) BigInt { return NewInt(10000) } -func (m *Miner) createBlock(base *MiningBase, ticket Ticket, proof ElectionProof) (*FullBlock, error) { - st, err := m.cs.TipSetState(base.ts.Cids()) +func MinerCreateBlock(cs *ChainStore, miner address.Address, parents *TipSet, tickets []Ticket, proof ElectionProof, msgs []*SignedMessage) (*FullBlock, error) { + st, err := cs.TipSetState(parents.Cids()) if err != nil { return nil, errors.Wrap(err, "failed to load tipset state") } - height := base.ts.Height() + uint64(len(base.tickets)) + 1 + height := parents.Height() + uint64(len(tickets)) - vm, err := NewVM(st, height, m.maddr, m.cs) + vm, err := NewVM(st, height, miner, cs) + if err != nil { + return nil, err + } // apply miner reward - if err := vm.TransferFunds(NetworkAddress, m.maddr, miningRewardForBlock(base.ts)); err != nil { + if err := vm.TransferFunds(NetworkAddress, miner, miningRewardForBlock(parents)); err != nil { return nil, err } next := &BlockHeader{ - Miner: m.maddr, - Parents: base.ts.Cids(), - Tickets: append(base.tickets, ticket), + Miner: miner, + Parents: parents.Cids(), + Tickets: tickets, Height: height, } - pending := m.mpool.Pending() - fmt.Printf("adding %d messages to block...", len(pending)) + fmt.Printf("adding %d messages to block...", len(msgs)) var msgCids []cid.Cid var blsSigs []Signature var receipts []interface{} - for _, msg := range pending { + for _, msg := range msgs { if msg.Signature.TypeCode() == 2 { blsSigs = append(blsSigs, msg.Signature) @@ -169,7 +54,7 @@ func (m *Miner) createBlock(base *MiningBase, ticket Ticket, proof ElectionProof if err != nil { return nil, err } - if err := m.cs.bs.Put(blk); err != nil { + if err := cs.bs.Put(blk); err != nil { return nil, err } @@ -185,7 +70,7 @@ func (m *Miner) createBlock(base *MiningBase, ticket Ticket, proof ElectionProof receipts = append(receipts, rec) } - cst := hamt.CSTFromBstore(m.cs.bs) + cst := hamt.CSTFromBstore(cs.bs) msgroot, err := sharray.Build(context.TODO(), 4, toIfArr(msgCids), cst) if err != nil { return nil, err @@ -210,12 +95,12 @@ func (m *Miner) createBlock(base *MiningBase, ticket Ticket, proof ElectionProof next.BLSAggregate = aggSig next.StateRoot = stateRoot - pweight := m.cs.Weight(base.ts) + pweight := cs.Weight(parents) next.ParentWeight = NewInt(pweight) fullBlock := &FullBlock{ Header: next, - Messages: pending, + Messages: msgs, } return fullBlock, nil diff --git a/chain/sync.go b/chain/sync.go index ca0aafa60..c76651b66 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -37,13 +37,15 @@ type Syncer struct { // handle to the block sync service Bsync *BlockSync + self peer.ID + // peer heads // Note: clear cache on disconnects peerHeads map[peer.ID]*TipSet peerHeadsLk sync.Mutex } -func NewSyncer(cs *ChainStore, bsync *BlockSync) (*Syncer, error) { +func NewSyncer(cs *ChainStore, bsync *BlockSync, self peer.ID) (*Syncer, error) { gen, err := cs.GetGenesis() if err != nil { return nil, err @@ -61,6 +63,7 @@ func NewSyncer(cs *ChainStore, bsync *BlockSync) (*Syncer, error) { peerHeads: make(map[peer.ID]*TipSet), head: cs.GetHeaviestTipSet(), store: cs, + self: self, }, nil } @@ -120,6 +123,21 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *FullTipSet) { if fts == nil { panic("bad") } + if from == syncer.self { + // TODO: this is kindof a hack... + log.Infof("got block from ourselves") + syncer.syncLock.Lock() + defer syncer.syncLock.Unlock() + + if syncer.syncMode == Bootstrap { + syncer.syncMode = CaughtUp + } + if err := syncer.SyncCaughtUp(fts); err != nil { + log.Errorf("failed to sync our own block: %s", err) + } + + return + } syncer.peerHeadsLk.Lock() syncer.peerHeads[from] = fts.TipSet() syncer.peerHeadsLk.Unlock() @@ -180,7 +198,25 @@ func (syncer *Syncer) SyncBootstrap() { blockSet := []*TipSet{selectedHead} cur := selectedHead.Cids() - for /* would be cool to have a terminating condition maybe */ { + + // If, for some reason, we have a suffix of the chain locally, handle that here + for blockSet[len(blockSet)-1].Height() > 0 { + log.Errorf("syncing local: ", cur) + ts, err := syncer.store.LoadTipSet(cur) + if err != nil { + if err == bstore.ErrNotFound { + log.Error("not found: ", cur) + break + } + log.Errorf("loading local tipset: %s", err) + return + } + + blockSet = append(blockSet, ts) + cur = ts.Parents() + } + + for blockSet[len(blockSet)-1].Height() > 0 { // NB: GetBlocks validates that the blocks are in-fact the ones we // requested, and that they are correctly linked to eachother. It does // not validate any state transitions @@ -194,9 +230,6 @@ func (syncer *Syncer) SyncBootstrap() { for _, b := range blks { blockSet = append(blockSet, b) } - if blks[len(blks)-1].Height() == 0 { - break - } cur = blks[len(blks)-1].Parents() } diff --git a/chain/types.go b/chain/types.go index f5d9cfb5c..a7b44a8a4 100644 --- a/chain/types.go +++ b/chain/types.go @@ -3,6 +3,7 @@ package chain import ( "bytes" "encoding/binary" + "encoding/json" "fmt" "math/big" @@ -229,6 +230,25 @@ func (bi *BigInt) Nil() bool { return bi.Int == nil } +func (bi *BigInt) MarshalJSON() ([]byte, error) { + return json.Marshal(bi.String()) +} + +func (bi *BigInt) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + i, ok := big.NewInt(0).SetString(s, 10) + if !ok { + return fmt.Errorf("failed to parse bigint string") + } + + bi.Int = i + return nil +} + type Actor struct { Code cid.Cid Head cid.Cid @@ -402,6 +422,34 @@ type TipSet struct { height uint64 } +// why didnt i just export the fields? Because the struct has methods with the +// same names already +type expTipSet struct { + Cids []cid.Cid + Blocks []*BlockHeader + Height uint64 +} + +func (ts *TipSet) MarshalJSON() ([]byte, error) { + return json.Marshal(expTipSet{ + Cids: ts.cids, + Blocks: ts.blks, + Height: ts.height, + }) +} + +func (ts *TipSet) UnmarshalJSON(b []byte) error { + var ets expTipSet + if err := json.Unmarshal(b, &ets); err != nil { + return err + } + + ts.cids = ets.Cids + ts.blks = ets.Blocks + ts.height = ets.Height + return nil +} + func NewTipSet(blks []*BlockHeader) (*TipSet, error) { var ts TipSet ts.cids = []cid.Cid{blks[0].Cid()} diff --git a/cli/chain.go b/cli/chain.go index 22a788f3b..ce1fed1a6 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -29,7 +29,7 @@ var chainHeadCmd = &cli.Command{ return err } - for _, c := range head { + for _, c := range head.Cids() { fmt.Println(c) } return nil diff --git a/cli/cmd.go b/cli/cmd.go index e6eb40d4b..414312e67 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -62,4 +62,6 @@ var Commands = []*cli.Command{ chainCmd, netCmd, versionCmd, + mpoolCmd, + minerCmd, } diff --git a/cli/miner.go b/cli/miner.go new file mode 100644 index 000000000..5b9afecbd --- /dev/null +++ b/cli/miner.go @@ -0,0 +1,41 @@ +package cli + +import ( + "fmt" + + "github.com/pkg/errors" + "gopkg.in/urfave/cli.v2" + + "github.com/filecoin-project/go-lotus/chain/address" +) + +var minerCmd = &cli.Command{ + Name: "miner", + Usage: "Manage mining", + Subcommands: []*cli.Command{ + minerStart, + }, +} + +var minerStart = &cli.Command{ + Name: "start", + Usage: "start mining", + Action: func(cctx *cli.Context) error { + api := getApi(cctx) + ctx := reqContext(cctx) + + // TODO: this address needs to be the address of an actual miner + maddr, err := address.NewIDAddress(523423423) + if err != nil { + return errors.Wrap(err, "failed to create miner address") + } + + if err := api.MinerStart(ctx, maddr); err != nil { + return err + } + + fmt.Println("started mining") + + return nil + }, +} diff --git a/cli/mpool.go b/cli/mpool.go new file mode 100644 index 000000000..10b51807d --- /dev/null +++ b/cli/mpool.go @@ -0,0 +1,35 @@ +package cli + +import ( + "fmt" + + "gopkg.in/urfave/cli.v2" +) + +var mpoolCmd = &cli.Command{ + Name: "mpool", + Usage: "Manage message pool", + Subcommands: []*cli.Command{ + mpoolPending, + }, +} + +var mpoolPending = &cli.Command{ + Name: "pending", + Usage: "Get pending messages", + Action: func(cctx *cli.Context) error { + api := getApi(cctx) + ctx := reqContext(cctx) + + msgs, err := api.MpoolPending(ctx, nil) + if err != nil { + return err + } + + for _, msg := range msgs { + fmt.Println(msg) + } + + return nil + }, +} diff --git a/cmd/lotus/main.go b/cmd/lotus/main.go index 06086f20d..abda9b021 100644 --- a/cmd/lotus/main.go +++ b/cmd/lotus/main.go @@ -4,6 +4,7 @@ import ( "log" "os" + logging "github.com/ipfs/go-log" "gopkg.in/urfave/cli.v2" "github.com/filecoin-project/go-lotus/build" @@ -12,6 +13,7 @@ import ( ) func main() { + logging.SetLogLevel("*", "INFO") local := []*cli.Command{ daemon.Cmd, } diff --git a/miner/miner.go b/miner/miner.go index 5aaf3dfed..a69cae230 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -8,36 +8,46 @@ import ( "github.com/pkg/errors" chain "github.com/filecoin-project/go-lotus/chain" + "github.com/filecoin-project/go-lotus/chain/address" ) var log = logging.Logger("miner") type api interface { - SubmitNewBlock(blk *chain.BlockMsg) error + ChainSubmitBlock(context.Context, *chain.BlockMsg) error // returns a set of messages that havent been included in the chain as of // the given tipset - PendingMessages(base *chain.TipSet) ([]*chain.SignedMessage, error) + MpoolPending(ctx context.Context, base *chain.TipSet) ([]*chain.SignedMessage, error) // Returns the best tipset for the miner to mine on top of. // TODO: Not sure this feels right (including the messages api). Miners // will likely want to have more control over exactly which blocks get // mined on, and which messages are included. - GetBestTipset() (*chain.TipSet, error) + ChainHead(context.Context) (*chain.TipSet, error) // returns the lookback randomness from the chain used for the election - GetChainRandomness(ts *chain.TipSet) ([]byte, error) + ChainGetRandomness(context.Context, *chain.TipSet) ([]byte, error) // create a block // it seems realllllly annoying to do all the actions necessary to build a // block through the API. so, we just add the block creation to the API // now, all the 'miner' does is check if they win, and call create block - CreateBlock(base *chain.TipSet, tickets []chain.Ticket, eproof chain.ElectionProof, msgs []*chain.SignedMessage) (*chain.BlockMsg, error) + MinerCreateBlock(context.Context, address.Address, *chain.TipSet, []chain.Ticket, chain.ElectionProof, []*chain.SignedMessage) (*chain.BlockMsg, error) +} + +func NewMiner(api api, addr address.Address) *Miner { + return &Miner{ + api: api, + Delay: time.Second * 4, + } } type Miner struct { api api + address address.Address + // time between blocks, network parameter Delay time.Duration @@ -59,7 +69,7 @@ func (m *Miner) Mine(ctx context.Context) { } if b != nil { - if err := m.api.SubmitNewBlock(b); err != nil { + if err := m.api.ChainSubmitBlock(ctx, b); err != nil { log.Errorf("failed to submit newly mined block: %s", err) } } @@ -72,7 +82,7 @@ type MiningBase struct { } func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) { - bts, err := m.api.GetBestTipset() + bts, err := m.api.ChainHead(context.TODO()) if err != nil { return nil, err } @@ -93,7 +103,7 @@ func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) { } func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*chain.BlockMsg, error) { - log.Info("mine one") + log.Info("attempting to mine a block on:", base.ts.Cids()) ticket, err := m.scratchTicket(ctx, base) if err != nil { return nil, errors.Wrap(err, "scratching ticket failed") @@ -113,7 +123,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*chain.BlockMsg, if err != nil { return nil, errors.Wrap(err, "failed to create block") } - log.Infof("created new block: %s", b.Cid()) + log.Infof("mined new block: %s", b.Cid()) return b, nil } @@ -124,7 +134,7 @@ func (m *Miner) submitNullTicket(base *MiningBase, ticket chain.Ticket) { } func (m *Miner) isWinnerNextRound(base *MiningBase) (bool, chain.ElectionProof, error) { - r, err := m.api.GetChainRandomness(base.ts) + r, err := m.api.ChainGetRandomness(context.TODO(), base.ts) if err != nil { return false, nil, err } @@ -146,13 +156,15 @@ func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (chain.Tick func (m *Miner) createBlock(base *MiningBase, ticket chain.Ticket, proof chain.ElectionProof) (*chain.BlockMsg, error) { - pending, err := m.api.PendingMessages(base.ts) + pending, err := m.api.MpoolPending(context.TODO(), base.ts) if err != nil { return nil, errors.Wrapf(err, "failed to get pending messages") } + msgs := m.selectMessages(pending) + // why even return this? that api call could just submit it for us - return m.api.CreateBlock(base.ts, append(base.tickets, ticket), proof, pending) + return m.api.MinerCreateBlock(context.TODO(), m.address, base.ts, append(base.tickets, ticket), proof, msgs) } func (m *Miner) selectMessages(msgs []*chain.SignedMessage) []*chain.SignedMessage { diff --git a/node/api.go b/node/api.go index 1efdfd3af..7736c5d2a 100644 --- a/node/api.go +++ b/node/api.go @@ -6,8 +6,9 @@ import ( "github.com/filecoin-project/go-lotus/api" "github.com/filecoin-project/go-lotus/build" "github.com/filecoin-project/go-lotus/chain" + "github.com/filecoin-project/go-lotus/chain/address" + "github.com/filecoin-project/go-lotus/miner" - "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" pubsub "github.com/libp2p/go-libp2p-pubsub" @@ -18,9 +19,14 @@ type API struct { Host host.Host Chain *chain.ChainStore PubSub *pubsub.PubSub + Mpool *chain.MessagePool } func (a *API) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error { + if err := a.Chain.AddBlock(blk.Header); err != nil { + return err + } + b, err := blk.Serialize() if err != nil { return err @@ -30,8 +36,13 @@ func (a *API) ChainSubmitBlock(ctx context.Context, blk *chain.BlockMsg) error { return a.PubSub.Publish("/fil/blocks", b) } -func (a *API) ChainHead(context.Context) ([]cid.Cid, error) { - return a.Chain.GetHeaviestTipSet().Cids(), nil +func (a *API) ChainHead(context.Context) (*chain.TipSet, error) { + return a.Chain.GetHeaviestTipSet(), nil +} + +func (a *API) ChainGetRandomness(ctx context.Context, pts *chain.TipSet) ([]byte, error) { + // TODO: this needs to look back in the chain for the right random beacon value + return []byte("foo bar random"), nil } func (a *API) ID(context.Context) (peer.ID, error) { @@ -44,6 +55,36 @@ func (a *API) Version(context.Context) (api.Version, error) { }, nil } +func (a *API) MpoolPending(ctx context.Context, ts *chain.TipSet) ([]*chain.SignedMessage, error) { + // TODO: need to make sure we don't return messages that were already included in the referenced chain + // also need to accept ts == nil just fine, assume nil == chain.Head() + return a.Mpool.Pending(), nil +} + +func (a *API) MinerStart(ctx context.Context, addr address.Address) error { + // hrm... + m := miner.NewMiner(a, addr) + + go m.Mine(context.TODO()) + + return nil +} + +func (a *API) MinerCreateBlock(ctx context.Context, addr address.Address, parents *chain.TipSet, tickets []chain.Ticket, proof chain.ElectionProof, msgs []*chain.SignedMessage) (*chain.BlockMsg, error) { + fblk, err := chain.MinerCreateBlock(a.Chain, addr, parents, tickets, proof, msgs) + if err != nil { + return nil, err + } + + var out chain.BlockMsg + out.Header = fblk.Header + for _, msg := range fblk.Messages { + out.Messages = append(out.Messages, msg.Cid()) + } + + return &out, nil +} + func (a *API) NetPeers(context.Context) ([]peer.AddrInfo, error) { conns := a.Host.Network().Conns() out := make([]peer.AddrInfo, len(conns)) diff --git a/node/builder.go b/node/builder.go index 0ba8e246c..089758f96 100644 --- a/node/builder.go +++ b/node/builder.go @@ -58,7 +58,7 @@ const ( StartListeningKey // filecoin - SetGenisisKey + SetGenesisKey RunHelloKey RunBlockSyncKey @@ -174,7 +174,7 @@ func Online() Option { Override(new(*chain.MessagePool), chain.NewMessagePool), Override(new(modules.Genesis), testing.MakeGenesis), - Override(SetGenisisKey, modules.SetGenesis), + Override(SetGenesisKey, modules.SetGenesis), Override(new(*hello.Service), hello.NewHelloService), Override(new(*chain.BlockSyncService), chain.NewBlockSyncService),