remove VDFs from tickets

This commit is contained in:
whyrusleeping 2019-10-09 13:38:59 +09:00
parent 49e8b5d334
commit 19b16077fe
11 changed files with 40 additions and 148 deletions

View File

@ -20,7 +20,6 @@ import (
"github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/chain/wallet" "github.com/filecoin-project/go-lotus/chain/wallet"
"github.com/filecoin-project/go-lotus/lib/vdf"
"github.com/filecoin-project/go-lotus/node/repo" "github.com/filecoin-project/go-lotus/node/repo"
block "github.com/ipfs/go-block-format" 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 return nil, nil, err
} }
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VDFResult) vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VRFProof)
if err != nil {
return nil, nil, err
}
out, proof, err := vdf.Run(vrfout)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
tick := &types.Ticket{ tick := &types.Ticket{
VRFProof: vrfout, VRFProof: vrfout,
VDFProof: proof,
VDFResult: out,
} }
win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm}) win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm})

View File

@ -329,9 +329,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
log.Infof("Empty Genesis root: %s", emptyroot) log.Infof("Empty Genesis root: %s", emptyroot)
genesisticket := &types.Ticket{ genesisticket := &types.Ticket{
VRFProof: []byte("vrf proof"), VRFProof: []byte("vrf proof"),
VDFResult: []byte("i am a vdf result"),
VDFProof: []byte("vdf proof"),
} }
b := &types.BlockHeader{ b := &types.BlockHeader{

View File

@ -743,7 +743,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets
t := tickets[lt-(1+lb)] t := tickets[lt-(1+lb)]
return t.VDFResult, nil return t.VRFProof, nil
} }
nv := lb - lt nv := lb - lt
@ -758,7 +758,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets
lt := int64(len(mtb.Tickets)) lt := int64(len(mtb.Tickets))
if nv < lt { if nv < lt {
t := mtb.Tickets[lt-(1+nv)] t := mtb.Tickets[lt-(1+nv)]
return t.VDFResult, nil return t.VRFProof, nil
} }
nv -= lt nv -= lt
@ -769,7 +769,7 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets
t := mtb.Tickets[0] t := mtb.Tickets[0]
rval := t.VDFResult rval := t.VRFProof
for i := int64(0); i < nv; i++ { for i := int64(0); i < nv; i++ {
h := sha256.Sum256(rval) h := sha256.Sum256(rval)
rval = h[:] rval = h[:]

View File

@ -14,7 +14,6 @@ import (
"github.com/filecoin-project/go-lotus/chain/stmgr" "github.com/filecoin-project/go-lotus/chain/stmgr"
"github.com/filecoin-project/go-lotus/chain/store" "github.com/filecoin-project/go-lotus/chain/store"
"github.com/filecoin-project/go-lotus/chain/types" "github.com/filecoin-project/go-lotus/chain/types"
"github.com/filecoin-project/go-lotus/lib/vdf"
amt "github.com/filecoin-project/go-amt-ipld" amt "github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
@ -405,15 +404,11 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre
Data: next.VRFProof, 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) 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 cur = next
} }

View File

@ -14,9 +14,7 @@ import (
) )
type Ticket struct { type Ticket struct {
VRFProof []byte VRFProof []byte
VDFResult []byte
VDFProof []byte
} }
type ElectionProof []byte type ElectionProof []byte
@ -176,5 +174,5 @@ func PowerCmp(eproof ElectionProof, mpow, totpow BigInt) bool {
} }
func (t *Ticket) Equals(ot *Ticket) bool { func (t *Ticket) Equals(ot *Ticket) bool {
return bytes.Equal(t.VDFResult, ot.VDFResult) return bytes.Equal(t.VRFProof, ot.VRFProof)
} }

View File

@ -27,9 +27,7 @@ func testBlockHeader(t testing.TB) *BlockHeader {
ElectionProof: []byte("cats won the election"), ElectionProof: []byte("cats won the election"),
Tickets: []*Ticket{ Tickets: []*Ticket{
&Ticket{ &Ticket{
VRFProof: []byte("vrf proof"), VRFProof: []byte("vrf proof"),
VDFResult: []byte("vdf result"),
VDFProof: []byte("vrf proof"),
}, },
}, },
Parents: []cid.Cid{c, c}, Parents: []cid.Cid{c, c},

View File

@ -5,7 +5,7 @@ import (
"io" "io"
"math" "math"
cid "github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
xerrors "golang.org/x/xerrors" xerrors "golang.org/x/xerrors"
) )
@ -284,7 +284,7 @@ func (t *Ticket) MarshalCBOR(w io.Writer) error {
_, err := w.Write(cbg.CborNull) _, err := w.Write(cbg.CborNull)
return err return err
} }
if _, err := w.Write([]byte{131}); err != nil { if _, err := w.Write([]byte{129}); err != nil {
return err return err
} }
@ -295,22 +295,6 @@ func (t *Ticket) MarshalCBOR(w io.Writer) error {
if _, err := w.Write(t.VRFProof); err != nil { if _, err := w.Write(t.VRFProof); err != nil {
return err 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 return nil
} }
@ -325,7 +309,7 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("cbor input should be of type array") 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") 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 { if _, err := io.ReadFull(br, t.VRFProof); err != nil {
return err 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 return nil
} }

View File

@ -125,7 +125,7 @@ func (ts *TipSet) Equals(ots *TipSet) bool {
} }
func (t *Ticket) Less(o *Ticket) 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 { func (ts *TipSet) MinTicket() *Ticket {

View File

@ -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
}

View File

@ -10,7 +10,6 @@ import (
"github.com/filecoin-project/go-lotus/chain/address" "github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/gen" "github.com/filecoin-project/go-lotus/chain/gen"
"github.com/filecoin-project/go-lotus/chain/types" "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" "github.com/filecoin-project/go-lotus/node/impl/full"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
@ -22,7 +21,7 @@ import (
var log = logging.Logger("miner") 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 { type api struct {
fx.In fx.In
@ -36,9 +35,11 @@ type api struct {
func NewMiner(api api) *Miner { func NewMiner(api api) *Miner {
return &Miner{ return &Miner{
api: api, api: api,
waitFunc: func(ctx context.Context) error {
// time between blocks, network parameter // Wait around for half the block time in case other parents come in
runVDF: delayVDF(build.BlockDelay * time.Second), time.Sleep(build.BlockDelay * time.Second / 2)
return nil
},
} }
} }
@ -50,7 +51,7 @@ type Miner struct {
stop chan struct{} stop chan struct{}
stopping chan struct{} stopping chan struct{}
runVDF vdfFunc waitFunc waitFunc
lastWork *MiningBase lastWork *MiningBase
} }
@ -144,6 +145,10 @@ func (m *Miner) mine(ctx context.Context) {
return return
default: default:
} }
if err := m.waitFunc(ctx); err != nil {
log.Error(err)
return
}
base, err := m.GetBestMiningCandidate() base, err := m.GetBestMiningCandidate()
if err != nil { if err != nil {
@ -159,6 +164,11 @@ func (m *Miner) mine(ctx context.Context) {
continue continue
} }
btime := time.Unix(int64(b.Header.Timestamp), 0)
if time.Now().Before(btime) {
time.Sleep(time.Until(btime))
}
if b != nil { if b != nil {
if err := m.api.ChainSubmitBlock(ctx, b); err != nil { if err := m.api.ChainSubmitBlock(ctx, b); err != nil {
log.Errorf("failed to submit newly mined block: %s", err) 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 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) { func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (*types.Ticket, error) {
var lastTicket *types.Ticket var lastTicket *types.Ticket
if len(base.tickets) > 0 { if len(base.tickets) > 0 {
@ -275,20 +273,13 @@ func (m *Miner) scratchTicket(ctx context.Context, base *MiningBase) (*types.Tic
lastTicket = base.ts.MinTicket() lastTicket = base.ts.MinTicket()
} }
vrfOut, err := m.computeVRF(ctx, lastTicket.VDFResult) vrfOut, err := m.computeVRF(ctx, lastTicket.VRFProof)
if err != nil {
return nil, err
}
res, proof, err := m.runVDF(ctx, vrfOut)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &types.Ticket{ return &types.Ticket{
VRFProof: vrfOut, VRFProof: vrfOut,
VDFResult: res,
VDFProof: proof,
}, nil }, 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) 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 // 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)) return m.api.MinerCreateBlock(context.TODO(), m.addresses[0], base.ts, append(base.tickets, ticket), proof, msgs, uint64(uts))

View File

@ -2,27 +2,25 @@ package miner
import ( import (
"context" "context"
"github.com/filecoin-project/go-lotus/lib/vdf"
) )
func NewTestMiner(nextCh <-chan struct{}) func(api api) *Miner { func NewTestMiner(nextCh <-chan struct{}) func(api api) *Miner {
return func(api api) *Miner { return func(api api) *Miner {
return &Miner{ return &Miner{
api: api, api: api,
runVDF: chanVDF(nextCh), waitFunc: chanWaiter(nextCh),
} }
} }
} }
func chanVDF(next <-chan struct{}) func(ctx context.Context, input []byte) ([]byte, []byte, error) { func chanWaiter(next <-chan struct{}) func(ctx context.Context) error {
return func(ctx context.Context, input []byte) ([]byte, []byte, error) { return func(ctx context.Context) error {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, nil, ctx.Err() return ctx.Err()
case <-next: case <-next:
} }
return vdf.Run(input) return nil
} }
} }