diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 5cee19efb..fe5d6221d 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -20,7 +20,6 @@ import ( "github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/wallet" - "github.com/filecoin-project/go-lotus/lib/vdf" "github.com/filecoin-project/go-lotus/node/repo" block "github.com/ipfs/go-block-format" @@ -213,20 +212,13 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add return nil, nil, err } - vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VDFResult) - if err != nil { - return nil, nil, err - } - - out, proof, err := vdf.Run(vrfout) + vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VRFProof) if err != nil { return nil, nil, err } tick := &types.Ticket{ - VRFProof: vrfout, - VDFProof: proof, - VDFResult: out, + VRFProof: vrfout, } win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm}) diff --git a/chain/gen/utils.go b/chain/gen/utils.go index af42e4c2e..f6784962e 100644 --- a/chain/gen/utils.go +++ b/chain/gen/utils.go @@ -329,9 +329,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B log.Infof("Empty Genesis root: %s", emptyroot) genesisticket := &types.Ticket{ - VRFProof: []byte("vrf proof"), - VDFResult: []byte("i am a vdf result"), - VDFProof: []byte("vdf proof"), + VRFProof: []byte("vrf proof"), } b := &types.BlockHeader{ diff --git a/chain/store/store.go b/chain/store/store.go index 33c139913..bbda0d145 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -743,7 +743,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets t := tickets[lt-(1+lb)] - return t.VDFResult, nil + return t.VRFProof, nil } nv := lb - lt @@ -758,7 +758,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets lt := int64(len(mtb.Tickets)) if nv < lt { t := mtb.Tickets[lt-(1+nv)] - return t.VDFResult, nil + return t.VRFProof, nil } nv -= lt @@ -769,7 +769,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets t := mtb.Tickets[0] - rval := t.VDFResult + rval := t.VRFProof for i := int64(0); i < nv; i++ { h := sha256.Sum256(rval) rval = h[:] diff --git a/chain/sync.go b/chain/sync.go index cd288d7ee..054c46c59 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -14,7 +14,6 @@ import ( "github.com/filecoin-project/go-lotus/chain/stmgr" "github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/types" - "github.com/filecoin-project/go-lotus/lib/vdf" amt "github.com/filecoin-project/go-amt-ipld" "github.com/ipfs/go-cid" @@ -405,15 +404,11 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre Data: next.VRFProof, } - if err := sig.Verify(mworker, cur.VDFResult); err != nil { + // TODO: ticket signatures should also include miner address + if err := sig.Verify(mworker, cur.VRFProof); err != nil { return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err) } - // now verify the VDF - if err := vdf.Verify(next.VRFProof, next.VDFResult, next.VDFProof); err != nil { - return xerrors.Errorf("ticket %d had invalid VDF: %w", err) - } - cur = next } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 55b09f870..f1003ed07 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -14,9 +14,7 @@ import ( ) type Ticket struct { - VRFProof []byte - VDFResult []byte - VDFProof []byte + VRFProof []byte } type ElectionProof []byte @@ -176,5 +174,5 @@ func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool { } func (t *Ticket) Equals(ot *Ticket) bool { - return bytes.Equal(t.VDFResult, ot.VDFResult) + return bytes.Equal(t.VRFProof, ot.VRFProof) } diff --git a/chain/types/blockheader_test.go b/chain/types/blockheader_test.go index fadac1698..6af560423 100644 --- a/chain/types/blockheader_test.go +++ b/chain/types/blockheader_test.go @@ -27,9 +27,7 @@ func testBlockHeader(t testing.TB) *BlockHeader { ElectionProof: []byte("cats won the election"), Tickets: []*Ticket{ &Ticket{ - VRFProof: []byte("vrf proof"), - VDFResult: []byte("vdf result"), - VDFProof: []byte("vrf proof"), + VRFProof: []byte("vrf proof"), }, }, Parents: []cid.Cid{c, c}, diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index 5841abf03..bad374f1b 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -5,7 +5,7 @@ import ( "io" "math" - cid "github.com/ipfs/go-cid" + "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" ) @@ -284,7 +284,7 @@ func (t *Ticket) MarshalCBOR(w io.Writer) error { _, err := w.Write(cbg.CborNull) return err } - if _, err := w.Write([]byte{131}); err != nil { + if _, err := w.Write([]byte{129}); err != nil { return err } @@ -295,22 +295,6 @@ func (t *Ticket) MarshalCBOR(w io.Writer) error { if _, err := w.Write(t.VRFProof); err != nil { return err } - - // t.t.VDFResult ([]uint8) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VDFResult)))); err != nil { - return err - } - if _, err := w.Write(t.VDFResult); err != nil { - return err - } - - // t.t.VDFProof ([]uint8) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VDFProof)))); err != nil { - return err - } - if _, err := w.Write(t.VDFProof); err != nil { - return err - } return nil } @@ -325,7 +309,7 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input should be of type array") } - if extra != 3 { + if extra != 1 { return fmt.Errorf("cbor input had wrong number of fields") } @@ -346,40 +330,6 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error { if _, err := io.ReadFull(br, t.VRFProof); err != nil { return err } - // t.t.VDFResult ([]uint8) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.VDFResult: array too large (%d)", extra) - } - - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.VDFResult = make([]byte, extra) - if _, err := io.ReadFull(br, t.VDFResult); err != nil { - return err - } - // t.t.VDFProof ([]uint8) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.VDFProof: array too large (%d)", extra) - } - - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.VDFProof = make([]byte, extra) - if _, err := io.ReadFull(br, t.VDFProof); err != nil { - return err - } return nil } diff --git a/chain/types/tipset.go b/chain/types/tipset.go index 2197b2d3f..979f59290 100644 --- a/chain/types/tipset.go +++ b/chain/types/tipset.go @@ -125,7 +125,7 @@ func (ts *TipSet) Equals(ots *TipSet) bool { } func (t *Ticket) Less(o *Ticket) bool { - return bytes.Compare(t.VDFResult, o.VDFResult) < 0 + return bytes.Compare(t.VRFProof, o.VRFProof) < 0 } func (ts *TipSet) MinTicket() *Ticket { diff --git a/lib/vdf/vdf.go b/lib/vdf/vdf.go deleted file mode 100644 index 98590be8e..000000000 --- a/lib/vdf/vdf.go +++ /dev/null @@ -1,28 +0,0 @@ -package vdf - -import ( - "bytes" - "crypto/sha256" - "fmt" -) - -func Run(input []byte) ([]byte, []byte, error) { - 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 Verify(input []byte, out []byte, proof []byte) error { - // this is a fake VDF - h := sha256.Sum256(input) - - if !bytes.Equal(h[:], out) { - return fmt.Errorf("vdf output incorrect") - } - - if !bytes.Equal(proof, []byte("proof")) { - return fmt.Errorf("vdf proof failed to validate") - } - - return nil -} diff --git a/miner/miner.go b/miner/miner.go index df47f3f14..84c779a70 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -10,7 +10,6 @@ import ( "github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/types" - "github.com/filecoin-project/go-lotus/lib/vdf" "github.com/filecoin-project/go-lotus/node/impl/full" logging "github.com/ipfs/go-log" @@ -22,7 +21,7 @@ import ( var log = logging.Logger("miner") -type vdfFunc func(ctx context.Context, input []byte) ([]byte, []byte, error) +type waitFunc func(ctx context.Context) error type api struct { fx.In @@ -36,9 +35,11 @@ type api struct { func NewMiner(api api) *Miner { return &Miner{ api: api, - - // time between blocks, network parameter - runVDF: delayVDF(build.BlockDelay * time.Second), + waitFunc: func(ctx context.Context) error { + // Wait around for half the block time in case other parents come in + time.Sleep(build.BlockDelay * time.Second / 2) + return nil + }, } } @@ -50,7 +51,7 @@ type Miner struct { stop chan struct{} stopping chan struct{} - runVDF vdfFunc + waitFunc waitFunc lastWork *MiningBase } @@ -144,6 +145,10 @@ func (m *Miner) mine(ctx context.Context) { return default: } + if err := m.waitFunc(ctx); err != nil { + log.Error(err) + return + } base, err := m.GetBestMiningCandidate() if err != nil { @@ -159,6 +164,11 @@ func (m *Miner) mine(ctx context.Context) { continue } + btime := time.Unix(int64(b.Header.Timestamp), 0) + if time.Now().Before(btime) { + time.Sleep(time.Until(btime)) + } + if b != nil { if err := m.api.ChainSubmitBlock(ctx, b); err != nil { log.Errorf("failed to submit newly mined block: %s", err) @@ -255,18 +265,6 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty return w, nil } -func delayVDF(delay time.Duration) func(ctx context.Context, input []byte) ([]byte, []byte, error) { - return func(ctx context.Context, input []byte) ([]byte, []byte, error) { - select { - case <-ctx.Done(): - return nil, nil, ctx.Err() - case <-time.After(delay): - } - - return vdf.Run(input) - } -} - func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (*types.Ticket, error) { var lastTicket *types.Ticket if len(base.tickets) > 0 { @@ -275,20 +273,13 @@ func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (*types.Tic lastTicket = base.ts.MinTicket() } - vrfOut, err := m.computeVRF(ctx, lastTicket.VDFResult) - if err != nil { - return nil, err - } - - res, proof, err := m.runVDF(ctx, vrfOut) + vrfOut, err := m.computeVRF(ctx, lastTicket.VRFProof) if err != nil { return nil, err } return &types.Ticket{ - VRFProof: vrfOut, - VDFResult: res, - VDFProof: proof, + VRFProof: vrfOut, }, nil } @@ -304,7 +295,7 @@ func (m *Miner) createBlock(base *MiningBase, ticket *types.Ticket, proof types. return nil, xerrors.Errorf("message filtering failed: %w", err) } - uts := time.Now().Unix() // TODO: put smallest valid timestamp + uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(len(base.tickets)+1)) // why even return this? that api call could just submit it for us return m.api.MinerCreateBlock(context.TODO(), m.addresses[0], base.ts, append(base.tickets, ticket), proof, msgs, uint64(uts)) diff --git a/miner/testminer.go b/miner/testminer.go index 241f9ffa8..6adf02266 100644 --- a/miner/testminer.go +++ b/miner/testminer.go @@ -2,27 +2,25 @@ package miner import ( "context" - - "github.com/filecoin-project/go-lotus/lib/vdf" ) func NewTestMiner(nextCh <-chan struct{}) func(api api) *Miner { return func(api api) *Miner { return &Miner{ - api: api, - runVDF: chanVDF(nextCh), + api: api, + waitFunc: chanWaiter(nextCh), } } } -func chanVDF(next <-chan struct{}) func(ctx context.Context, input []byte) ([]byte, []byte, error) { - return func(ctx context.Context, input []byte) ([]byte, []byte, error) { +func chanWaiter(next <-chan struct{}) func(ctx context.Context) error { + return func(ctx context.Context) error { select { case <-ctx.Done(): - return nil, nil, ctx.Err() + return ctx.Err() case <-next: } - return vdf.Run(input) + return nil } }