Reintroduce correct ticket randomness alongside ElectionProof
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
9a17beba9e
commit
ce4978d8c3
@ -73,7 +73,7 @@ type FullNode interface {
|
||||
// miner
|
||||
|
||||
MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*MiningBaseInfo, error)
|
||||
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
|
||||
MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.ElectionProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
|
||||
|
||||
// // UX ?
|
||||
|
||||
|
@ -88,8 +88,8 @@ type FullNodeStruct struct {
|
||||
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
||||
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"`
|
||||
|
||||
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"`
|
||||
MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.ElectionProof, []types.BeaconEntry, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
@ -330,7 +330,7 @@ func (c *FullNodeStruct) MinerGetBaseInfo(ctx context.Context, maddr address.Add
|
||||
return c.Internal.MinerGetBaseInfo(ctx, maddr, tsk)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.ElectionProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, bvals, msgs, height, ts)
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ const MaxSealLookback = SealRandomnessLookbackLimit + 2000 // TODO: Get from spe
|
||||
// Mining
|
||||
|
||||
// Epochs
|
||||
const EcRandomnessLookback = Finality
|
||||
const TicketRandomnessLookback = 1
|
||||
|
||||
// /////
|
||||
// Devnet settings
|
||||
|
@ -277,17 +277,16 @@ func CarWalkFunc(nd format.Node) (out []*format.Link, err error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.Ticket, error) {
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round abi.ChainEpoch) ([]types.BeaconEntry, *types.ElectionProof, *types.Ticket, error) {
|
||||
mc := &mca{w: cg.w, sm: cg.sm}
|
||||
|
||||
prev, err := cg.cs.GetLatestBeaconEntry(pts)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("getLatestBeaconEntry: %w", err)
|
||||
return nil, nil, nil, xerrors.Errorf("getLatestBeaconEntry: %w", err)
|
||||
}
|
||||
|
||||
entries, err := beacon.BeaconEntriesForBlock(ctx, cg.beacon, abi.ChainEpoch(round), *prev)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
|
||||
return nil, nil, nil, xerrors.Errorf("get beacon entries for block: %w", err)
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
panic("no drand")
|
||||
@ -298,39 +297,37 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
rbase = entries[len(entries)-1]
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
||||
eproof, err := IsRoundWinner(ctx, pts, round, m, rbase, mc)
|
||||
if err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
|
||||
ticketRand, err := store.DrawRandomness(rbase.Data, 17, round, buf.Bytes())
|
||||
buf := new(bytes.Buffer)
|
||||
if err := m.MarshalCBOR(buf); err != nil {
|
||||
return nil, nil, nil, xerrors.Errorf("failed to cbor marshal address: %w", err)
|
||||
}
|
||||
|
||||
ticketRand, err := cg.cs.GetRandomness(ctx, pts.Cids(), crypto.DomainSeparationTag_TicketProduction,
|
||||
round-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
st := pts.ParentState()
|
||||
|
||||
worker, err := stmgr.GetMinerWorkerRaw(ctx, cg.sm, st, m)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
return nil, nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, ticketRand)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
|
||||
tick := &types.Ticket{
|
||||
VRFProof: vrfout,
|
||||
return nil, nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
|
||||
// TODO winning post return?
|
||||
_, err = IsRoundWinner(ctx, pts, round, m, rbase, mc)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
|
||||
return entries, tick, nil
|
||||
return entries, eproof, &types.Ticket{VRFProof: vrfout}, nil
|
||||
}
|
||||
|
||||
type MinedTipSet struct {
|
||||
@ -358,7 +355,7 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
|
||||
for round := base.Height() + 1; len(blks) == 0; round++ {
|
||||
for _, m := range miners {
|
||||
bvals, t, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
||||
bvals, et, ticket, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("next block proof: %w", err)
|
||||
}
|
||||
@ -366,9 +363,10 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
panic("no drand")
|
||||
}
|
||||
|
||||
if t != nil {
|
||||
if et != nil {
|
||||
// TODO: winning post proof
|
||||
fblk, err := cg.makeBlock(base, m, nil, t, bvals, abi.ChainEpoch(round), msgs)
|
||||
_ = ticket
|
||||
fblk, err := cg.makeBlock(base, m, ticket, et, bvals, abi.ChainEpoch(round), msgs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
@ -390,7 +388,9 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *types.EPostProof, ticket *types.Ticket, bvals []types.BeaconEntry, height abi.ChainEpoch, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, vrfticket *types.Ticket,
|
||||
eticket *types.ElectionProof, bvals []types.BeaconEntry, height abi.ChainEpoch,
|
||||
msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
|
||||
var ts uint64
|
||||
if cg.Timestamper != nil {
|
||||
@ -399,7 +399,7 @@ func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof *
|
||||
ts = parents.MinTimestamp() + uint64((height-parents.Height())*build.BlockDelay)
|
||||
}
|
||||
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, bvals, msgs, height, ts)
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, vrfticket, eticket, bvals, msgs, height, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -531,37 +531,37 @@ type ProofInput struct {
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round abi.ChainEpoch,
|
||||
miner address.Address, brand types.BeaconEntry, a MiningCheckAPI) (bool, error) {
|
||||
miner address.Address, brand types.BeaconEntry, a MiningCheckAPI) (*types.ElectionProof, error) {
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := miner.MarshalCBOR(buf); err != nil {
|
||||
return false, xerrors.Errorf("failed to cbor marshal address: %w")
|
||||
return nil, xerrors.Errorf("failed to cbor marshal address: %w")
|
||||
}
|
||||
|
||||
electionRand, err := store.DrawRandomness(brand.Data, 17, round, buf.Bytes())
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to draw randomness: %w", err)
|
||||
return nil, xerrors.Errorf("failed to draw randomness: %w", err)
|
||||
}
|
||||
|
||||
mbi, err := a.MinerGetBaseInfo(ctx, miner, ts.Key())
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to get mining base info: %w", err)
|
||||
return nil, xerrors.Errorf("failed to get mining base info: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.Worker, electionRand)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
return nil, xerrors.Errorf("failed to compute VRF: %w", err)
|
||||
}
|
||||
|
||||
// TODO: wire in real power
|
||||
myPower := types.BigMul(types.NewInt(uint64(len(mbi.Sectors))), types.NewInt(uint64(mbi.SectorSize)))
|
||||
if !types.IsTicketWinner(vrfout, myPower, mbi.NetworkPower) {
|
||||
return false, nil
|
||||
if !types.IsTicketWinner(vrfout, mbi.MinerPower, mbi.NetworkPower) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return &types.ElectionProof{VRFProof: vrfout}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) {
|
||||
proof, err := epp.ComputeProof(ctx, pi.sectors, pi.hvrf, pi.winners)
|
||||
if err != nil {
|
||||
@ -584,6 +584,7 @@ func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (
|
||||
|
||||
return &ept, nil
|
||||
}
|
||||
*/
|
||||
|
||||
type SignFunc func(context.Context, address.Address, []byte) (*crypto.Signature, error)
|
||||
|
||||
|
@ -252,11 +252,8 @@ func MakeGenesisBlock(ctx context.Context, bs bstore.Blockstore, sys runtime.Sys
|
||||
}
|
||||
|
||||
b := &types.BlockHeader{
|
||||
Miner: builtin.SystemActorAddr,
|
||||
Ticket: genesisticket,
|
||||
EPostProof: types.EPostProof{
|
||||
PostRand: []byte("i guess this is kinda random"),
|
||||
},
|
||||
Miner: builtin.SystemActorAddr,
|
||||
Ticket: genesisticket,
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
ParentWeight: types.NewInt(0),
|
||||
|
@ -21,8 +21,10 @@ import (
|
||||
)
|
||||
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address,
|
||||
parents *types.TipSet, ticket *types.Ticket, proof *types.EPostProof, bvals []types.BeaconEntry,
|
||||
msgs []*types.SignedMessage, height abi.ChainEpoch, timestamp uint64) (*types.FullBlock, error) {
|
||||
parents *types.TipSet, vrfticket *types.Ticket, eproof *types.ElectionProof,
|
||||
bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch,
|
||||
timestamp uint64) (*types.FullBlock, error) {
|
||||
|
||||
st, recpts, err := sm.TipSetState(ctx, parents)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load tipset state: %w", err)
|
||||
@ -36,7 +38,9 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
next := &types.BlockHeader{
|
||||
Miner: miner,
|
||||
Parents: parents.Cids(),
|
||||
Ticket: ticket,
|
||||
Ticket: vrfticket,
|
||||
ElectionProof: eproof,
|
||||
|
||||
BeaconEntries: bvals,
|
||||
Height: height,
|
||||
Timestamp: timestamp,
|
||||
|
@ -314,7 +314,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
Miner: b.Miner,
|
||||
BlsMessages: make([]types.ChainMsg, 0, len(bms)),
|
||||
SecpkMessages: make([]types.ChainMsg, 0, len(sms)),
|
||||
TicketCount: int64(len(b.EPostProof.Proofs)),
|
||||
TicketCount: 1, //int64(len(b.EPostProof.Proofs)), // TODO fix this
|
||||
}
|
||||
|
||||
for _, m := range bms {
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/trace"
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
|
||||
@ -893,7 +894,7 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
}
|
||||
|
||||
func DrawRandomness(rbase []byte, pers crypto.DomainSeparationTag, round abi.ChainEpoch, entropy []byte) ([]byte, error) {
|
||||
// log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar().Warnw("DrawRandomness", "base", rbase, "dsep", pers, "round", round, "entropy", entropy)
|
||||
log.Desugar().WithOptions(zap.AddCallerSkip(2)).Sugar().Warnw("DrawRandomness", "base", rbase, "dsep", pers, "round", round, "entropy", entropy)
|
||||
h := blake2b.New256()
|
||||
if err := binary.Write(h, binary.BigEndian, int64(pers)); err != nil {
|
||||
return nil, xerrors.Errorf("deriving randomness: %w", err)
|
||||
@ -913,11 +914,9 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, pers cr
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("round", int64(round)))
|
||||
|
||||
/*
|
||||
defer func() {
|
||||
log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
}()
|
||||
*/
|
||||
//defer func() {
|
||||
//log.Infof("getRand %v %d %d %x -> %x", blks, pers, round, entropy, out)
|
||||
//}()
|
||||
for {
|
||||
nts, err := cs.LoadTipSet(types.NewTipSetKey(blks...))
|
||||
if err != nil {
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/libp2p/go-libp2p-core/connmgr"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/minio/blake2b-simd"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"github.com/whyrusleeping/pubsub"
|
||||
"go.opencensus.io/stats"
|
||||
@ -28,7 +27,6 @@ import (
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
"github.com/filecoin-project/go-address"
|
||||
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
@ -45,7 +43,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
||||
)
|
||||
|
||||
var log = logging.Logger("chain")
|
||||
@ -538,30 +535,6 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d; diff %d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height(), diff)
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
|
||||
}
|
||||
|
||||
if slashed {
|
||||
return xerrors.Errorf("received block was from slashed or invalid miner")
|
||||
}
|
||||
|
||||
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed getting power: %w", err)
|
||||
}
|
||||
|
||||
if !types.IsTicketWinner(h.Ticket.VRFProof, mpow, tpow) {
|
||||
return xerrors.Errorf("miner created a block but was not a winner")
|
||||
}
|
||||
|
||||
// TODO: validate winning post proof
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
msgsCheck := async.Err(func() error {
|
||||
if err := syncer.checkBlockMessages(ctx, b, baseTs); err != nil {
|
||||
return xerrors.Errorf("block had invalid messages: %w", err)
|
||||
@ -606,6 +579,50 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("GetMinerWorkerRaw failed: %w", err)
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
rBeacon := *prevBeacon
|
||||
if len(h.BeaconEntries) != 0 {
|
||||
rBeacon = h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := h.Miner.MarshalCBOR(buf); err != nil {
|
||||
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
|
||||
}
|
||||
|
||||
//TODO: DST from spec actors when it is there
|
||||
vrfBase, err := store.DrawRandomness(rBeacon.Data, 17, h.Height, buf.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not draw randomness: %w", err)
|
||||
}
|
||||
|
||||
err = gen.VerifyVRF(ctx, waddr, vrfBase, h.ElectionProof.VRFProof)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("validating block election proof failed: %w", err)
|
||||
}
|
||||
|
||||
slashed, err := stmgr.GetMinerSlashed(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check if block miner was slashed: %w", err)
|
||||
}
|
||||
|
||||
if slashed {
|
||||
return xerrors.Errorf("received block was from slashed or invalid miner")
|
||||
}
|
||||
|
||||
mpow, tpow, err := stmgr.GetPower(ctx, syncer.sm, baseTs, h.Miner)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed getting power: %w", err)
|
||||
}
|
||||
|
||||
if !types.IsTicketWinner(h.ElectionProof.VRFProof, mpow, tpow) {
|
||||
return xerrors.Errorf("miner created a block but was not a winner")
|
||||
}
|
||||
|
||||
// TODO: validate winning post proof
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
blockSigCheck := async.Err(func() error {
|
||||
if err := sigs.CheckBlockSignature(h, ctx, waddr); err != nil {
|
||||
return xerrors.Errorf("check block signature failed: %w", err)
|
||||
@ -622,18 +639,13 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
})
|
||||
|
||||
tktsCheck := async.Err(func() error {
|
||||
baseBeacon := prevBeacon
|
||||
if len(h.BeaconEntries) > 0 {
|
||||
baseBeacon = &h.BeaconEntries[len(h.BeaconEntries)-1]
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if err := h.Miner.MarshalCBOR(buf); err != nil {
|
||||
return xerrors.Errorf("failed to marshal miner address to cbor: %w", err)
|
||||
}
|
||||
|
||||
// TODO: use real DST from specs actors when it lands
|
||||
vrfBase, err := store.DrawRandomness(baseBeacon.Data, 17, h.Height, buf.Bytes())
|
||||
vrfBase, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(),
|
||||
crypto.DomainSeparationTag_TicketProduction, h.Height-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to compute vrf base for ticket: %w", err)
|
||||
}
|
||||
@ -689,6 +701,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return merr
|
||||
}
|
||||
|
||||
/*
|
||||
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, waddr address.Address) error {
|
||||
curTs, err := types.NewTipSet([]*types.BlockHeader{h})
|
||||
if err != nil {
|
||||
@ -790,6 +803,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
|
||||
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
|
||||
{
|
||||
|
@ -22,16 +22,8 @@ type Ticket struct {
|
||||
VRFProof []byte
|
||||
}
|
||||
|
||||
type EPostTicket struct {
|
||||
Partial []byte
|
||||
SectorID abi.SectorNumber
|
||||
ChallengeIndex uint64
|
||||
}
|
||||
|
||||
type EPostProof struct {
|
||||
Proofs []abi.PoStProof
|
||||
PostRand []byte
|
||||
Candidates []EPostTicket
|
||||
type ElectionProof struct {
|
||||
VRFProof []byte
|
||||
}
|
||||
|
||||
type BeaconEntry struct {
|
||||
@ -44,7 +36,7 @@ type BlockHeader struct {
|
||||
|
||||
Ticket *Ticket // 1
|
||||
|
||||
EPostProof EPostProof // 2
|
||||
ElectionProof *ElectionProof
|
||||
|
||||
BeaconEntries []BeaconEntry
|
||||
|
||||
@ -173,7 +165,7 @@ var blocksPerEpoch = NewInt(build.BlocksPerEpoch)
|
||||
|
||||
const sha256bits = 256
|
||||
|
||||
func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||
func IsTicketWinner(vrfTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||
/*
|
||||
Need to check that
|
||||
(h(vrfout) + 1) / (max(h) + 1) <= e * myPower / totalPower
|
||||
@ -185,7 +177,7 @@ func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||
|
||||
*/
|
||||
|
||||
h := sha256.Sum256(partialTicket)
|
||||
h := sha256.Sum256(vrfTicket)
|
||||
|
||||
lhs := BigFromBytes(h[:]).Int
|
||||
lhs = lhs.Mul(lhs, totpow.Int)
|
||||
@ -199,14 +191,6 @@ func IsTicketWinner(partialTicket []byte, mypow BigInt, totpow BigInt) bool {
|
||||
return lhs.Cmp(rhs) < 0
|
||||
}
|
||||
|
||||
func ElectionPostChallengeCount(sectors uint64, faults uint64) uint64 {
|
||||
if sectors-faults == 0 {
|
||||
return 0
|
||||
}
|
||||
// ceil(sectors / SectorChallengeRatioDiv)
|
||||
return (sectors-faults-1)/build.SectorChallengeRatioDiv + 1
|
||||
}
|
||||
|
||||
func (t *Ticket) Equals(ot *Ticket) bool {
|
||||
return bytes.Equal(t.VRFProof, ot.VRFProof)
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.EPostProof (types.EPostProof) (struct)
|
||||
if err := t.EPostProof.MarshalCBOR(w); err != nil {
|
||||
// t.ElectionProof (types.ElectionProof) (struct)
|
||||
if err := t.ElectionProof.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -172,12 +172,24 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
}
|
||||
// t.EPostProof (types.EPostProof) (struct)
|
||||
// t.ElectionProof (types.ElectionProof) (struct)
|
||||
|
||||
{
|
||||
|
||||
if err := t.EPostProof.UnmarshalCBOR(br); err != nil {
|
||||
return xerrors.Errorf("unmarshaling t.EPostProof: %w", err)
|
||||
pb, err := br.PeekByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pb == cbg.CborNull[0] {
|
||||
var nbuf [1]byte
|
||||
if _, err := br.Read(nbuf[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
t.ElectionProof = new(ElectionProof)
|
||||
if err := t.ElectionProof.UnmarshalCBOR(br); err != nil {
|
||||
return xerrors.Errorf("unmarshaling t.ElectionProof pointer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -435,58 +447,30 @@ func (t *Ticket) UnmarshalCBOR(r io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostProof) MarshalCBOR(w io.Writer) error {
|
||||
func (t *ElectionProof) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, 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
|
||||
}
|
||||
|
||||
// t.Proofs ([]abi.PoStProof) (slice)
|
||||
if len(t.Proofs) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Proofs was too long")
|
||||
// t.VRFProof ([]uint8) (slice)
|
||||
if len(t.VRFProof) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.VRFProof was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Proofs)))); err != nil {
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.VRFProof)))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Proofs {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.PostRand ([]uint8) (slice)
|
||||
if len(t.PostRand) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.PostRand was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PostRand)))); err != nil {
|
||||
if _, err := w.Write(t.VRFProof); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(t.PostRand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Candidates ([]types.EPostTicket) (slice)
|
||||
if len(t.Candidates) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Candidates was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Candidates {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
|
||||
func (t *ElectionProof) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
@ -497,38 +481,11 @@ func (t *EPostProof) 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")
|
||||
}
|
||||
|
||||
// t.Proofs ([]abi.PoStProof) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Proofs: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Proofs = make([]abi.PoStProof, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v abi.PoStProof
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Proofs[i] = v
|
||||
}
|
||||
|
||||
// t.PostRand ([]uint8) (slice)
|
||||
// t.VRFProof ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
@ -536,141 +493,15 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.PostRand: byte array too large (%d)", extra)
|
||||
return fmt.Errorf("t.VRFProof: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
t.PostRand = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.PostRand); err != nil {
|
||||
t.VRFProof = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.VRFProof); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.Candidates ([]types.EPostTicket) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Candidates = make([]EPostTicket, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v EPostTicket
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Candidates[i] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostTicket) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write([]byte{131}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Partial ([]uint8) (slice)
|
||||
if len(t.Partial) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Partial was too long")
|
||||
}
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Partial)))); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(t.Partial); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.SectorID))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.ChallengeIndex (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.ChallengeIndex))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EPostTicket) UnmarshalCBOR(r io.Reader) error {
|
||||
br := cbg.GetPeeker(r)
|
||||
|
||||
maj, extra, err := cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Partial ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Partial: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
t.Partial = make([]byte, extra)
|
||||
if _, err := io.ReadFull(br, t.Partial); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.SectorID (abi.SectorNumber) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.SectorID = abi.SectorNumber(extra)
|
||||
|
||||
}
|
||||
// t.ChallengeIndex (uint64) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.ChallengeIndex = uint64(extra)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1506,7 +1337,7 @@ func (t *BeaconEntry) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Index (uint64) (uint64)
|
||||
// t.Round (uint64) (uint64)
|
||||
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Round))); err != nil {
|
||||
return err
|
||||
@ -1541,7 +1372,7 @@ func (t *BeaconEntry) UnmarshalCBOR(r io.Reader) error {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Index (uint64) (uint64)
|
||||
// t.Round (uint64) (uint64)
|
||||
|
||||
{
|
||||
|
||||
|
@ -60,8 +60,8 @@ func MkBlock(parents *types.TipSet, weightInc uint64, ticketNonce uint64) *types
|
||||
|
||||
return &types.BlockHeader{
|
||||
Miner: addr,
|
||||
EPostProof: types.EPostProof{
|
||||
Proofs: []abi.PoStProof{{ProofBytes: []byte("election post proof proof")}},
|
||||
ElectionProof: &types.ElectionProof{
|
||||
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
||||
},
|
||||
Ticket: &types.Ticket{
|
||||
VRFProof: []byte(fmt.Sprintf("====%d=====", ticketNonce)),
|
||||
|
13
gen/main.go
13
gen/main.go
@ -11,15 +11,13 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/node/hello"
|
||||
"github.com/filecoin-project/lotus/paychmgr"
|
||||
sealing "github.com/filecoin-project/storage-fsm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := gen.WriteTupleEncodersToFile("./chain/types/cbor_gen.go", "types",
|
||||
types.BlockHeader{},
|
||||
types.Ticket{},
|
||||
types.EPostProof{},
|
||||
types.EPostTicket{},
|
||||
types.ElectionProof{},
|
||||
types.Message{},
|
||||
types.SignedMessage{},
|
||||
types.MsgMeta{},
|
||||
@ -74,13 +72,4 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = gen.WriteMapEncodersToFile("./storage/sealing/cbor_gen.go", "sealing",
|
||||
sealing.Piece{},
|
||||
sealing.SectorInfo{},
|
||||
sealing.Log{},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ import (
|
||||
|
||||
address "github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/beacon"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
@ -355,7 +355,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, xerrors.Errorf("failed to check if we win next round: %w", err)
|
||||
}
|
||||
|
||||
if !winner {
|
||||
if winner == nil {
|
||||
base.nullRounds++
|
||||
return nil, nil
|
||||
}
|
||||
@ -367,7 +367,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
}
|
||||
|
||||
// TODO: winning post proof
|
||||
b, err := m.createBlock(base, addr, ticket, nil, bvals, pending)
|
||||
b, err := m.createBlock(base, addr, ticket, winner, bvals, pending)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create block: %w", err)
|
||||
}
|
||||
@ -391,7 +391,8 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
|
||||
if err := addr.MarshalCBOR(buf); err != nil {
|
||||
return nil, xerrors.Errorf("failed to marshal address to cbor: %w", err)
|
||||
}
|
||||
input, err := store.DrawRandomness(brand.Data, 17, (base.ts.Height() + base.nullRounds + 1), buf.Bytes())
|
||||
input, err := m.api.ChainGetRandomness(ctx, base.ts.Key(), crypto.DomainSeparationTag_TicketProduction,
|
||||
base.ts.Height()+base.nullRounds+1-build.TicketRandomnessLookback, buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -407,7 +408,7 @@ func (m *Miner) computeTicket(ctx context.Context, addr address.Address, brand *
|
||||
}
|
||||
|
||||
func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket,
|
||||
proof *types.EPostProof, bvals []types.BeaconEntry, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
||||
eproof *types.ElectionProof, bvals []types.BeaconEntry, pending []*types.SignedMessage) (*types.BlockMsg, error) {
|
||||
msgs, err := SelectMessages(context.TODO(), m.api.StateGetActor, base.ts, pending)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
||||
@ -423,7 +424,7 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
|
||||
nheight := base.ts.Height() + base.nullRounds + 1
|
||||
|
||||
// why even return this? that api call could just submit it for us
|
||||
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, proof, bvals, msgs, nheight, uint64(uts))
|
||||
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts.Key(), ticket, eproof, bvals, msgs, nheight, uint64(uts))
|
||||
}
|
||||
|
||||
type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error)
|
||||
|
@ -269,7 +269,7 @@ func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address,
|
||||
return stmgr.MinerGetBaseInfo(ctx, a.StateManager, tsk, maddr)
|
||||
}
|
||||
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.ElectionProof, bvals []types.BeaconEntry, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) {
|
||||
parents, err := a.Chain.GetTipSetFromKey(parentsTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("loading tipset %s: %w", parentsTSK, err)
|
||||
|
Loading…
Reference in New Issue
Block a user