diff --git a/api/api.go b/api/api.go index 9dbc77bf7..2520f1f01 100644 --- a/api/api.go +++ b/api/api.go @@ -66,7 +66,7 @@ type FullNode interface { // miner MinerStart(context.Context, address.Address) error - MinerCreateBlock(context.Context, address.Address, *types.TipSet, []types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) + MinerCreateBlock(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) // // UX ? diff --git a/api/struct.go b/api/struct.go index 75cb45f68..2058c7286 100644 --- a/api/struct.go +++ b/api/struct.go @@ -54,8 +54,8 @@ type FullNodeStruct struct { MpoolPending func(context.Context, *types.TipSet) ([]*types.SignedMessage, error) `perm:"read"` MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"` - MinerStart func(context.Context, address.Address) error `perm:"admin"` - MinerCreateBlock func(context.Context, address.Address, *types.TipSet, []types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) `perm:"write"` + MinerStart func(context.Context, address.Address) error `perm:"admin"` + MinerCreateBlock func(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) `perm:"write"` WalletNew func(context.Context, string) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` @@ -163,7 +163,7 @@ func (c *FullNodeStruct) MinerStart(ctx context.Context, addr address.Address) e return c.Internal.MinerStart(ctx, addr) } -func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, tickets []types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) { +func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, tickets []*types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) { return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 24c724976..c4cbc4291 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -41,6 +41,7 @@ type ChainGen struct { w *wallet.Wallet miner address.Address + mworker address.Address receivers []address.Address banker address.Address bankerNonce uint64 @@ -93,7 +94,7 @@ func NewGenerator() (*ChainGen, error) { return nil, err } - miner, err := w.GenerateKey(types.KTBLS) + worker, err := w.GenerateKey(types.KTBLS) if err != nil { return nil, err } @@ -112,10 +113,15 @@ func NewGenerator() (*ChainGen, error) { } } + minercfg := &GenMinerCfg{ + Worker: worker, + Owner: worker, + } + genb, err := MakeGenesisBlock(bs, map[address.Address]types.BigInt{ - miner: types.NewInt(5), + worker: types.NewInt(50000), banker: types.NewInt(90000000), - }) + }, minercfg) if err != nil { return nil, err } @@ -135,7 +141,8 @@ func NewGenerator() (*ChainGen, error) { genesis: genb.Genesis, w: w, - miner: miner, + miner: minercfg.MinerAddr, + mworker: worker, banker: banker, receivers: receievers, @@ -166,8 +173,13 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) { return out.Bytes(), nil } -func (cg *ChainGen) nextBlockProof() (address.Address, types.ElectionProof, []types.Ticket, error) { - return cg.miner, []byte("cat in a box"), []types.Ticket{types.Ticket("im a ticket, promise")}, nil +func (cg *ChainGen) nextBlockProof() (address.Address, types.ElectionProof, []*types.Ticket, error) { + tick := &types.Ticket{ + VRFProof: []byte("im a ticket, promise"), + VDFProof: []byte("vdf proof"), + VDFResult: []byte("verifiable and delayed"), + } + return cg.miner, []byte("cat in a box"), []*types.Ticket{tick}, nil } func (cg *ChainGen) NextBlock() (*types.FullBlock, []*types.SignedMessage, error) { diff --git a/chain/gen/mining.go b/chain/gen/mining.go index 9872bff32..cc7ee5e9b 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -16,7 +16,7 @@ import ( "github.com/filecoin-project/go-lotus/chain/vm" ) -func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*types.FullBlock, error) { +func MinerCreateBlock(ctx context.Context, cs *store.ChainStore, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*types.FullBlock, error) { st, err := cs.TipSetState(parents.Cids()) if err != nil { return nil, errors.Wrap(err, "failed to load tipset state") diff --git a/chain/gen/utils.go b/chain/gen/utils.go index f7603e9ae..65c77b1fd 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -7,11 +7,16 @@ import ( actors "github.com/filecoin-project/go-lotus/chain/actors" "github.com/filecoin-project/go-lotus/chain/address" "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" + "golang.org/x/xerrors" "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" hamt "github.com/ipfs/go-hamt-ipld" bstore "github.com/ipfs/go-ipfs-blockstore" + peer "github.com/libp2p/go-libp2p-peer" sharray "github.com/whyrusleeping/sharray" ) @@ -133,8 +138,107 @@ func SetupStorageMarketActor(bs bstore.Blockstore) (*types.Actor, error) { }, nil } -func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.BigInt) (*GenesisBootstrap, error) { - fmt.Println("at end of make Genesis block") +type GenMinerCfg struct { + Owner address.Address + Worker address.Address + + // not quite generating real sectors yet, but this will be necessary + //SectorDir string + + // The address of the created miner, this is set by the genesis setup + MinerAddr address.Address + + PeerID peer.ID +} + +func mustEnc(i interface{}) []byte { + enc, err := actors.SerializeParams(i) + if err != nil { + panic(err) + } + return enc +} + +func SetupStorageMiners(ctx context.Context, cs *store.ChainStore, sroot cid.Cid, gmcfg *GenMinerCfg) (cid.Cid, error) { + vm, err := vm.NewVM(sroot, 0, actors.NetworkAddress, cs) + if err != nil { + return cid.Undef, err + } + + params := mustEnc(actors.CreateStorageMinerParams{ + Owner: gmcfg.Owner, + Worker: gmcfg.Worker, + SectorSize: types.NewInt(1024), + PeerID: gmcfg.PeerID, + }) + + rval, err := doExec(ctx, vm, actors.StorageMarketAddress, gmcfg.Owner, actors.SMAMethods.CreateStorageMiner, params) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to create genesis miner: %w", err) + } + + maddr, err := address.NewFromBytes(rval) + if err != nil { + return cid.Undef, err + } + + gmcfg.MinerAddr = maddr + + params = mustEnc(actors.UpdateStorageParams{Delta: types.NewInt(5000)}) + + _, err = doExec(ctx, vm, actors.StorageMarketAddress, maddr, actors.SMAMethods.UpdateStorage, params) + + // UGLY HACKY MODIFICATION OF MINER POWER + st := vm.StateTree() + mact, err := st.GetActor(maddr) + if err != nil { + return cid.Undef, err + } + + cst := hamt.CSTFromBstore(cs.Blockstore()) + var mstate actors.StorageMinerActorState + if err := cst.Get(ctx, mact.Head, &mstate); err != nil { + return cid.Undef, err + } + mstate.Power = types.NewInt(5000) + + nstate, err := cst.Put(ctx, mstate) + if err != nil { + return cid.Undef, err + } + + mact.Head = nstate + if err := st.SetActor(maddr, mact); err != nil { + return cid.Undef, err + } + // End of super haxx + + return vm.Flush(ctx) +} + +func doExec(ctx context.Context, vm *vm.VM, to, from address.Address, method uint64, params []byte) ([]byte, error) { + ret, err := vm.ApplyMessage(context.TODO(), &types.Message{ + To: to, + From: from, + Method: method, + Params: params, + GasLimit: types.NewInt(1000000), + GasPrice: types.NewInt(0), + Value: types.NewInt(0), + }) + if err != nil { + return nil, err + } + + if ret.ExitCode != 0 { + return nil, fmt.Errorf("failed to call method: %s", ret.ActorErr) + } + + return ret.Return, nil +} + +func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.BigInt, gmcfg *GenMinerCfg) (*GenesisBootstrap, error) { + ctx := context.Background() state, err := MakeInitialStateTree(bs, balances) if err != nil { @@ -146,6 +250,13 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B return nil, err } + // temp chainstore + cs := store.NewChainStore(bs, datastore.NewMapDatastore()) + stateroot, err = SetupStorageMiners(ctx, cs, stateroot, gmcfg) + if err != nil { + return nil, err + } + cst := hamt.CSTFromBstore(bs) emptyroot, err := sharray.Build(context.TODO(), 4, []interface{}{}, cst) @@ -162,9 +273,15 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B fmt.Println("Empty Genesis root: ", emptyroot) + genesisticket := &types.Ticket{ + VRFProof: []byte("vrf proof"), + VDFResult: []byte("i am a vdf result"), + VDFProof: []byte("vdf proof"), + } + b := &types.BlockHeader{ Miner: actors.InitActorAddress, - Tickets: []types.Ticket{}, + Tickets: []*types.Ticket{genesisticket}, ElectionProof: []byte("the Genesis block"), Parents: []cid.Cid{}, Height: 0, diff --git a/chain/types/bigint.go b/chain/types/bigint.go index 062ea44eb..12d0d89ca 100644 --- a/chain/types/bigint.go +++ b/chain/types/bigint.go @@ -54,6 +54,10 @@ func BigMul(a, b BigInt) BigInt { return BigInt{big.NewInt(0).Mul(a.Int, b.Int)} } +func BigDiv(a, b BigInt) BigInt { + return BigInt{big.NewInt(0).Div(a.Int, b.Int)} +} + func BigAdd(a, b BigInt) BigInt { return BigInt{big.NewInt(0).Add(a.Int, b.Int)} } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index d4a2e126d..c491d3c0c 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + block "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" @@ -15,14 +17,22 @@ func init() { TransformMarshal(atlas.MakeMarshalTransformFunc( func(blk BlockHeader) ([]interface{}, error) { if blk.Tickets == nil { - blk.Tickets = []Ticket{} + blk.Tickets = []*Ticket{} } if blk.Parents == nil { blk.Parents = []cid.Cid{} } + + var tickarrs [][][]byte // oh boy + for _, t := range blk.Tickets { + tickarrs = append(tickarrs, [][]byte{ + t.VRFProof, t.VDFResult, t.VDFProof, + }) + } + return []interface{}{ blk.Miner.Bytes(), - blk.Tickets, + tickarrs, blk.ElectionProof, blk.Parents, blk.ParentWeight, @@ -39,10 +49,23 @@ func init() { return BlockHeader{}, err } - tickets := []Ticket{} + tickets := []*Ticket{} ticketarr, _ := arr[1].([]interface{}) for _, t := range ticketarr { - tickets = append(tickets, Ticket(t.([]byte))) + ticklist, ok := t.([]interface{}) + if !ok { + return BlockHeader{}, fmt.Errorf("tickets were incorrectly formatted (type = %T)", t) + } + + if len(ticklist) != 3 { + return BlockHeader{}, fmt.Errorf("ticket should be a three item array of Byte arrays (got len = %d)", len(ticklist)) + } + + tickets = append(tickets, &Ticket{ + VRFProof: ticklist[0].([]byte), + VDFResult: ticklist[1].([]byte), + VDFProof: ticklist[2].([]byte), + }) } electionProof, _ := arr[2].([]byte) @@ -72,15 +95,21 @@ func init() { })). Complete()) cbor.RegisterCborType(MsgMeta{}) + cbor.RegisterCborType(Ticket{}) +} + +type Ticket struct { + VRFProof []byte + VDFResult []byte + VDFProof []byte } -type Ticket []byte type ElectionProof []byte type BlockHeader struct { Miner address.Address - Tickets []Ticket + Tickets []*Ticket ElectionProof []byte diff --git a/chain/vm/vm.go b/chain/vm/vm.go index c50dee634..55072b727 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -441,6 +441,10 @@ func Copy(ctx context.Context, from, to ipld.DAGService, root cid.Cid) error { return nil } +func (vm *VM) StateTree() types.StateTree { + return vm.cstate +} + func (vm *VM) TransferFunds(from, to address.Address, amt types.BigInt) error { if from == to { return nil diff --git a/go.mod b/go.mod index f4bfafc5d..b25822cf9 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/libp2p/go-libp2p-discovery v0.1.0 github.com/libp2p/go-libp2p-kad-dht v0.1.1 github.com/libp2p/go-libp2p-mplex v0.2.1 + github.com/libp2p/go-libp2p-peer v0.2.0 github.com/libp2p/go-libp2p-peerstore v0.1.2-0.20190621130618-cfa9bb890c1a github.com/libp2p/go-libp2p-pnet v0.1.0 github.com/libp2p/go-libp2p-pubsub v0.1.0 diff --git a/go.sum b/go.sum index 3fadb7b2a..781b10683 100644 --- a/go.sum +++ b/go.sum @@ -305,6 +305,7 @@ github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFx github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ= github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo= +github.com/libp2p/go-libp2p-peer v0.2.0 h1:EQ8kMjaCUwt/Y5uLgjT8iY2qg0mGUT0N1zUjer50DsY= github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20= github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= diff --git a/miner/miner.go b/miner/miner.go index 9e9e426f3..ff926c97b 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -1,14 +1,20 @@ package miner import ( + "bytes" "context" + "crypto/sha256" + "fmt" + "math/big" "time" logging "github.com/ipfs/go-log" "github.com/pkg/errors" "go.opencensus.io/trace" + "golang.org/x/xerrors" chain "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/types" ) @@ -16,6 +22,8 @@ import ( var log = logging.Logger("miner") type api interface { + ChainCall(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) + ChainSubmitBlock(context.Context, *chain.BlockMsg) error // returns a set of messages that havent been included in the chain as of @@ -35,7 +43,9 @@ type api interface { // 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 - MinerCreateBlock(context.Context, address.Address, *types.TipSet, []types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) + MinerCreateBlock(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage) (*chain.BlockMsg, error) + + WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) } func NewMiner(api api, addr address.Address) *Miner { @@ -83,7 +93,7 @@ func (m *Miner) Mine(ctx context.Context) { type MiningBase struct { ts *types.TipSet - tickets []types.Ticket + tickets []*types.Ticket } func (m *Miner) GetBestMiningCandidate() (*MiningBase, error) { @@ -114,7 +124,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*chain.BlockMsg, return nil, errors.Wrap(err, "scratching ticket failed") } - win, proof, err := m.isWinnerNextRound(base) + win, proof, err := m.isWinnerNextRound(ctx, base) if err != nil { return nil, errors.Wrap(err, "failed to check if we win next round") } @@ -133,33 +143,180 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (*chain.BlockMsg, return b, nil } -func (m *Miner) submitNullTicket(base *MiningBase, ticket types.Ticket) { +func (m *Miner) submitNullTicket(base *MiningBase, ticket *types.Ticket) { base.tickets = append(base.tickets, ticket) m.lastWork = base } -func (m *Miner) isWinnerNextRound(base *MiningBase) (bool, types.ElectionProof, error) { +func (m *Miner) computeVRF(ctx context.Context, input []byte) ([]byte, error) { + w, err := m.getMinerWorker(ctx, m.address, nil) + if err != nil { + return nil, err + } + + sig, err := m.api.WalletSign(ctx, w, input) + if err != nil { + return nil, err + } + + if sig.Type != types.KTBLS { + return nil, fmt.Errorf("miner worker address was not a BLS key") + } + + return sig.Data, nil +} + +func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { + ret, err := m.api.ChainCall(ctx, &types.Message{ + From: addr, + To: addr, + Method: actors.MAMethods.GetWorkerAddr, + }, ts) + if err != nil { + return address.Undef, xerrors.Errorf("failed to get miner worker addr: %w", err) + } + + if ret.ExitCode != 0 { + return address.Undef, xerrors.Errorf("failed to get miner worker addr (exit code %d)", ret.ExitCode) + } + + w, err := address.NewFromBytes(ret.Return) + if err != nil { + return address.Undef, xerrors.Errorf("GetWorkerAddr returned malformed address: %w", err) + } + + return w, nil +} + +func (m *Miner) isWinnerNextRound(ctx context.Context, base *MiningBase) (bool, types.ElectionProof, error) { r, err := m.api.ChainGetRandomness(context.TODO(), base.ts) if err != nil { return false, nil, err } - _ = r // TODO: use this to properly compute the election proof + vrfout, err := m.computeVRF(ctx, r) + if err != nil { + return false, nil, xerrors.Errorf("failed to compute VRF: %w", err) + } - return true, []byte("election prooooof"), nil + mpow, totpow, err := m.getPowerForTipset(ctx, m.address, base.ts) + if err != nil { + return false, nil, xerrors.Errorf("failed to check power: %w", err) + } + + return powerCmp(vrfout, mpow, totpow), vrfout, nil } -func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (types.Ticket, error) { +func powerCmp(vrfout []byte, mpow, totpow types.BigInt) bool { + + /* + Need to check that + h(vrfout) / 2^256 < minerPower / totalPower + */ + + h := sha256.Sum256(vrfout) + + // 2^256 + rden := types.BigInt{big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil)} + + top := types.BigMul(rden, mpow) + out := types.BigDiv(top, totpow) + + return types.BigCmp(types.BigFromBytes(h[:]), out) < 0 +} + +func (m *Miner) getPowerForTipset(ctx context.Context, maddr address.Address, ts *types.TipSet) (types.BigInt, types.BigInt, error) { + var err error + enc, err := actors.SerializeParams(&actors.PowerLookupParams{maddr}) + if err != nil { + return types.EmptyInt, types.EmptyInt, err + } + + ret, err := m.api.ChainCall(ctx, &types.Message{ + From: maddr, + To: actors.StorageMarketAddress, + Method: actors.SMAMethods.PowerLookup, + Params: enc, + }, ts) + if err != nil { + return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain: %w", err) + } + if ret.ExitCode != 0 { + return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get miner power from chain (exit code %d)", ret.ExitCode) + } + + mpow := types.BigFromBytes(ret.Return) + + ret, err = m.api.ChainCall(ctx, &types.Message{ + From: maddr, + To: actors.StorageMarketAddress, + Method: actors.SMAMethods.GetTotalStorage, + }, ts) + if err != nil { + return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain: %w", err) + } + if ret.ExitCode != 0 { + return types.EmptyInt, types.EmptyInt, xerrors.Errorf("failed to get total power from chain (exit code %d)", ret.ExitCode) + } + + tpow := types.BigFromBytes(ret.Return) + + return mpow, tpow, nil +} + +func (m *Miner) runVDF(ctx context.Context, input []byte) ([]byte, []byte, error) { select { case <-ctx.Done(): - return nil, ctx.Err() + return nil, nil, ctx.Err() case <-time.After(m.Delay): } - return []byte("this is a ticket"), nil + h := sha256.Sum256(input) + // TODO: THIS IS A FAKE VDF. THE SPEC IS UNCLEAR ON WHAT TO REALLY DO HERE + return h[:], []byte("proof"), nil } -func (m *Miner) createBlock(base *MiningBase, ticket types.Ticket, proof types.ElectionProof) (*chain.BlockMsg, error) { +func minTicket(ts *types.TipSet) *types.Ticket { + if len(ts.Blocks()) == 0 { + panic("tipset has no blocks!") + } + var minTicket *types.Ticket + for _, b := range ts.Blocks() { + lastTicket := b.Tickets[len(b.Tickets)-1] + if minTicket == nil || bytes.Compare(lastTicket.VDFResult, minTicket.VDFResult) < 0 { + minTicket = lastTicket + } + } + + return minTicket +} + +func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (*types.Ticket, error) { + var lastTicket *types.Ticket + if len(base.tickets) > 0 { + lastTicket = base.tickets[len(base.tickets)-1] + } else { + lastTicket = minTicket(base.ts) + } + + vrfOut, err := m.computeVRF(ctx, lastTicket.VDFResult) + if err != nil { + return nil, err + } + + res, proof, err := m.runVDF(ctx, vrfOut) + if err != nil { + return nil, err + } + + return &types.Ticket{ + VRFProof: vrfOut, + VDFResult: res, + VDFProof: proof, + }, nil +} + +func (m *Miner) createBlock(base *MiningBase, ticket *types.Ticket, proof types.ElectionProof) (*chain.BlockMsg, error) { pending, err := m.api.MpoolPending(context.TODO(), base.ts) if err != nil { diff --git a/node/impl/full.go b/node/impl/full.go index a9f235023..5fbd452c6 100644 --- a/node/impl/full.go +++ b/node/impl/full.go @@ -291,7 +291,7 @@ func (a *FullNodeAPI) MinerStart(ctx context.Context, addr address.Address) erro return nil } -func (a *FullNodeAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) { +func (a *FullNodeAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage) (*chain.BlockMsg, error) { fblk, err := gen.MinerCreateBlock(ctx, a.Chain, addr, parents, tickets, proof, msgs) if err != nil { return nil, err diff --git a/node/modules/testing/genesis.go b/node/modules/testing/genesis.go index 64a7db71c..79c52eb1b 100644 --- a/node/modules/testing/genesis.go +++ b/node/modules/testing/genesis.go @@ -27,7 +27,20 @@ func MakeGenesisMem(out io.Writer) func(bs dtypes.ChainBlockstore, w *wallet.Wal 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 - b, err := gen.MakeGenesisBlock(bs, nil) + w, err := w.GenerateKey(types.KTBLS) + if err != nil { + return nil, err + } + + gmc := &gen.GenMinerCfg{ + Owner: w, + Worker: w, + } + alloc := map[address.Address]types.BigInt{ + w: types.NewInt(100000), + } + + b, err := gen.MakeGenesisBlock(bs, alloc, gmc) if err != nil { return nil, err } @@ -48,16 +61,21 @@ func MakeGenesis(outFile string) func(bs dtypes.ChainBlockstore, w *wallet.Walle 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") - minerAddr, err := w.GenerateKey(types.KTSecp256k1) + minerAddr, err := w.GenerateKey(types.KTBLS) if err != nil { return nil, err } + gmc := &gen.GenMinerCfg{ + Owner: minerAddr, + Worker: minerAddr, + } + addrs := map[address.Address]types.BigInt{ minerAddr: types.NewInt(50000000), } - b, err := gen.MakeGenesisBlock(bs, addrs) + b, err := gen.MakeGenesisBlock(bs, addrs, gmc) if err != nil { return nil, err }