Refactor mining logic to match specs ticket chain
This commit is contained in:
parent
d680dab52e
commit
f8eabd3db4
@ -23,7 +23,7 @@ type FullNode interface {
|
||||
// First message is guaranteed to be of len == 1, and type == 'current'
|
||||
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
|
||||
ChainGetBlock(context.Context, cid.Cid) (*types.BlockHeader, error)
|
||||
ChainGetTipSet(context.Context, types.TipSetKey) (*types.TipSet, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*BlockMessages, error)
|
||||
@ -52,7 +52,7 @@ type FullNode interface {
|
||||
MinerRegister(context.Context, address.Address) error
|
||||
MinerUnregister(context.Context, address.Address) error
|
||||
MinerAddresses(context.Context) ([]address.Address, error)
|
||||
MinerCreateBlock(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error)
|
||||
MinerCreateBlock(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error)
|
||||
|
||||
// // UX ?
|
||||
|
||||
|
@ -37,19 +37,19 @@ type FullNodeStruct struct {
|
||||
CommonStruct
|
||||
|
||||
Internal struct {
|
||||
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
|
||||
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetRandomness func(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error) `perm:"read"`
|
||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
|
||||
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
|
||||
ChainNotify func(context.Context) (<-chan []*store.HeadChange, error) `perm:"read"`
|
||||
ChainHead func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetRandomness func(context.Context, types.TipSetKey, int64) ([]byte, error) `perm:"read"`
|
||||
ChainGetBlock func(context.Context, cid.Cid) (*types.BlockHeader, error) `perm:"read"`
|
||||
ChainGetTipSet func(context.Context, types.TipSetKey) (*types.TipSet, error) `perm:"read"`
|
||||
ChainGetBlockMessages func(context.Context, cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||
ChainGetParentReceipts func(context.Context, cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"`
|
||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]Message, error) `perm:"read"`
|
||||
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
|
||||
|
||||
SyncState func(context.Context) (*SyncState, error) `perm:"read"`
|
||||
SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"`
|
||||
@ -58,10 +58,10 @@ type FullNodeStruct struct {
|
||||
MpoolPush func(context.Context, *types.SignedMessage) error `perm:"write"`
|
||||
MpoolPushMessage func(context.Context, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
||||
|
||||
MinerRegister func(context.Context, address.Address) error `perm:"admin"`
|
||||
MinerUnregister func(context.Context, address.Address) error `perm:"admin"`
|
||||
MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, []*types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
MinerRegister func(context.Context, address.Address) error `perm:"admin"`
|
||||
MinerUnregister func(context.Context, address.Address) error `perm:"admin"`
|
||||
MinerAddresses func(context.Context) ([]address.Address, error) `perm:"write"`
|
||||
MinerCreateBlock func(context.Context, address.Address, *types.TipSet, *types.Ticket, types.ElectionProof, []*types.SignedMessage, uint64, uint64) (*types.BlockMsg, error) `perm:"write"`
|
||||
|
||||
WalletNew func(context.Context, string) (address.Address, error) `perm:"write"`
|
||||
WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"`
|
||||
@ -237,16 +237,16 @@ func (c *FullNodeStruct) MinerAddresses(ctx context.Context) ([]address.Address,
|
||||
return c.Internal.MinerAddresses(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, tickets []*types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, tickets, eproof, msgs, ts)
|
||||
func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base *types.TipSet, ticket *types.Ticket, eproof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
||||
return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainHead(ctx context.Context) (*types.TipSet, error) {
|
||||
return c.Internal.ChainHead(ctx)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) {
|
||||
return c.Internal.ChainGetRandomness(ctx, pts, ticks, lb)
|
||||
func (c *FullNodeStruct) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) {
|
||||
return c.Internal.ChainGetRandomness(ctx, pts, round)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h uint64, ts *types.TipSet) (*types.TipSet, error) {
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
xerrors "golang.org/x/xerrors"
|
||||
)
|
||||
|
@ -52,7 +52,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
Height: h,
|
||||
Miner: a,
|
||||
|
||||
Tickets: []*types.Ticket{{[]byte{byte(h % 2)}}},
|
||||
Ticket: &types.Ticket{[]byte{byte(h % 2)}},
|
||||
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: msgcid,
|
||||
@ -65,7 +65,7 @@ func makeTs(t *testing.T, h uint64, msgcid cid.Cid) *types.TipSet {
|
||||
Height: h,
|
||||
Miner: b,
|
||||
|
||||
Tickets: []*types.Ticket{{[]byte{byte((h + 1) % 2)}}},
|
||||
Ticket: &types.Ticket{[]byte{byte((h + 1) % 2)}},
|
||||
|
||||
ParentStateRoot: dummyCid,
|
||||
Messages: msgcid,
|
||||
|
@ -3,6 +3,8 @@ package gen
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
@ -46,7 +48,7 @@ type ChainGen struct {
|
||||
genesis *types.BlockHeader
|
||||
CurTipset *store.FullTipSet
|
||||
|
||||
Timestamper func(*types.TipSet, int) uint64
|
||||
Timestamper func(*types.TipSet, uint64) uint64
|
||||
|
||||
w *wallet.Wallet
|
||||
|
||||
@ -195,14 +197,9 @@ func (cg *ChainGen) GenesisCar() ([]byte, error) {
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, ticks []*types.Ticket) (types.ElectionProof, *types.Ticket, error) {
|
||||
func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m address.Address, round int64) (types.ElectionProof, *types.Ticket, error) {
|
||||
|
||||
var lastTicket *types.Ticket
|
||||
if len(ticks) == 0 {
|
||||
lastTicket = pts.MinTicket()
|
||||
} else {
|
||||
lastTicket = ticks[len(ticks)-1]
|
||||
}
|
||||
lastTicket := pts.MinTicket()
|
||||
|
||||
st := pts.ParentState()
|
||||
|
||||
@ -211,7 +208,8 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
return nil, nil, xerrors.Errorf("get miner worker: %w", err)
|
||||
}
|
||||
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, lastTicket.VRFProof)
|
||||
vrfBase := TicketHash(lastTicket, uint64(round))
|
||||
vrfout, err := ComputeVRF(ctx, cg.w.Sign, worker, vrfBase)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("compute VRF: %w", err)
|
||||
}
|
||||
@ -220,7 +218,7 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add
|
||||
VRFProof: vrfout,
|
||||
}
|
||||
|
||||
win, eproof, err := IsRoundWinner(ctx, pts, append(ticks, tick), m, &mca{w: cg.w, sm: cg.sm})
|
||||
win, eproof, err := IsRoundWinner(ctx, pts, round, m, &mca{w: cg.w, sm: cg.sm})
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("checking round winner failed: %w", err)
|
||||
}
|
||||
@ -248,23 +246,21 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
||||
|
||||
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
|
||||
var blks []*types.FullBlock
|
||||
ticketSets := make([][]*types.Ticket, len(miners))
|
||||
|
||||
msgs, err := cg.getRandomMessages()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get random messages: %w", err)
|
||||
}
|
||||
|
||||
for len(blks) == 0 {
|
||||
for i, m := range miners {
|
||||
proof, t, err := cg.nextBlockProof(context.TODO(), base, m, ticketSets[i])
|
||||
for round := int64(base.Height() + 1); len(blks) == 0; round++ {
|
||||
for _, m := range miners {
|
||||
proof, t, err := cg.nextBlockProof(context.TODO(), base, m, round)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("next block proof: %w", err)
|
||||
}
|
||||
|
||||
ticketSets[i] = append(ticketSets[i], t)
|
||||
if proof != nil {
|
||||
fblk, err := cg.makeBlock(base, m, proof, ticketSets[i], msgs)
|
||||
fblk, err := cg.makeBlock(base, m, proof, t, uint64(round), msgs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
@ -286,16 +282,16 @@ func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Ad
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, tickets []*types.Ticket, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
func (cg *ChainGen) makeBlock(parents *types.TipSet, m address.Address, eproof types.ElectionProof, ticket *types.Ticket, height uint64, msgs []*types.SignedMessage) (*types.FullBlock, error) {
|
||||
|
||||
var ts uint64
|
||||
if cg.Timestamper != nil {
|
||||
ts = cg.Timestamper(parents, len(tickets))
|
||||
ts = cg.Timestamper(parents, height-parents.Height())
|
||||
} else {
|
||||
ts = parents.MinTimestamp() + (uint64(len(tickets)) * build.BlockDelay)
|
||||
ts = parents.MinTimestamp() + ((height - parents.Height()) * build.BlockDelay)
|
||||
}
|
||||
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, tickets, eproof, msgs, ts)
|
||||
fblk, err := MinerCreateBlock(context.TODO(), cg.sm, cg.w, m, parents, ticket, eproof, msgs, height, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -354,7 +350,7 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) {
|
||||
}
|
||||
|
||||
type MiningCheckAPI interface {
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
|
||||
|
||||
StateMinerPower(context.Context, address.Address, *types.TipSet) (api.MinerPower, error)
|
||||
|
||||
@ -368,8 +364,8 @@ type mca struct {
|
||||
sm *stmgr.StateManager
|
||||
}
|
||||
|
||||
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, ticks []*types.Ticket, lb int) ([]byte, error) {
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), ticks, int64(lb))
|
||||
func (mca mca) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, lb int64) ([]byte, error) {
|
||||
return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), int64(lb))
|
||||
}
|
||||
|
||||
func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, ts *types.TipSet) (api.MinerPower, error) {
|
||||
@ -392,8 +388,8 @@ func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*ty
|
||||
return mca.w.Sign(ctx, a, v)
|
||||
}
|
||||
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, ticks []*types.Ticket, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) {
|
||||
r, err := a.ChainGetRandomness(ctx, ts.Key(), ticks, build.EcRandomnessLookback)
|
||||
func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, a MiningCheckAPI) (bool, types.ElectionProof, error) {
|
||||
r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback)
|
||||
if err != nil {
|
||||
return false, nil, xerrors.Errorf("chain get randomness: %w", err)
|
||||
}
|
||||
@ -430,3 +426,12 @@ func ComputeVRF(ctx context.Context, sign SignFunc, w address.Address, input []b
|
||||
|
||||
return sig.Data, nil
|
||||
}
|
||||
|
||||
func TicketHash(t *types.Ticket, round uint64) []byte {
|
||||
h := sha256.New()
|
||||
h.Write(t.VRFProof)
|
||||
var roundbuf [8]byte
|
||||
binary.LittleEndian.PutUint64(roundbuf[:], round)
|
||||
h.Write(roundbuf[:])
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
@ -12,18 +12,12 @@ func testGeneration(t testing.TB, n int, msgs int) {
|
||||
|
||||
g.msgsPerBlock = msgs
|
||||
|
||||
var height int
|
||||
for i := 0; i < n; i++ {
|
||||
mts, err := g.NextTipSet()
|
||||
if err != nil {
|
||||
t.Fatalf("error at H:%d, %s", i, err)
|
||||
}
|
||||
|
||||
ts := mts.TipSet.TipSet()
|
||||
if ts.Height() != uint64(height+len(ts.Blocks()[0].Tickets)) {
|
||||
t.Fatal("wrong height", ts.Height(), i, len(ts.Blocks()[0].Tickets), len(ts.Blocks()))
|
||||
}
|
||||
height += len(ts.Blocks()[0].Tickets)
|
||||
_ = mts
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,14 +18,12 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
)
|
||||
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, timestamp uint64) (*types.FullBlock, error) {
|
||||
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, miner address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, 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)
|
||||
}
|
||||
|
||||
height := parents.Height() + uint64(len(tickets))
|
||||
|
||||
worker, err := stmgr.GetMinerWorkerRaw(ctx, sm, st, miner)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
|
||||
@ -34,7 +32,7 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
|
||||
next := &types.BlockHeader{
|
||||
Miner: miner,
|
||||
Parents: parents.Cids(),
|
||||
Tickets: tickets,
|
||||
Ticket: ticket,
|
||||
Height: height,
|
||||
Timestamp: timestamp,
|
||||
ElectionProof: proof,
|
||||
|
@ -384,7 +384,7 @@ func MakeGenesisBlock(bs bstore.Blockstore, balances map[address.Address]types.B
|
||||
|
||||
b := &types.BlockHeader{
|
||||
Miner: actors.InitAddress,
|
||||
Tickets: []*types.Ticket{genesisticket},
|
||||
Ticket: genesisticket,
|
||||
ElectionProof: []byte("the Genesis block"),
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
|
@ -68,7 +68,7 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
||||
|
||||
state := ts.ParentState()
|
||||
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height(), nil)
|
||||
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
||||
|
||||
return sm.CallRaw(ctx, msg, state, r, ts.Height())
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
cids[i] = v.Cid()
|
||||
}
|
||||
|
||||
r := store.NewChainRand(sm.cs, cids, blks[0].Height, nil)
|
||||
r := store.NewChainRand(sm.cs, cids, blks[0].Height)
|
||||
|
||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore())
|
||||
if err != nil {
|
||||
|
@ -3,8 +3,8 @@ package store
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -12,7 +12,6 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"go.opencensus.io/trace"
|
||||
"go.uber.org/zap"
|
||||
|
||||
amt "github.com/filecoin-project/go-amt-ipld"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -771,24 +770,21 @@ func (cs *ChainStore) TryFillTipSet(ts *types.TipSet) (*FullTipSet, error) {
|
||||
return NewFullTipSet(out), nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets []*types.Ticket, lb int64) ([]byte, error) {
|
||||
func ticketHash(t *types.Ticket, round int64) []byte {
|
||||
h := sha256.New()
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], uint64(round))
|
||||
|
||||
h.Write(t.VRFProof)
|
||||
h.Write(buf[:])
|
||||
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, round int64) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "store.GetRandomness")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("lb", lb))
|
||||
|
||||
if lb < 0 {
|
||||
return nil, fmt.Errorf("negative lookback parameters are not valid (got %d)", lb)
|
||||
}
|
||||
lt := int64(len(tickets))
|
||||
if lb < lt {
|
||||
log.Desugar().Warn("self sampling randomness. this should be extremely rare, if you see this often it may be a bug", zap.Stack("stacktrace"))
|
||||
|
||||
t := tickets[lt-(1+lb)]
|
||||
|
||||
return t.VRFProof, nil
|
||||
}
|
||||
|
||||
nv := lb - lt
|
||||
span.AddAttributes(trace.Int64Attribute("round", round))
|
||||
|
||||
for {
|
||||
nts, err := cs.LoadTipSet(blks)
|
||||
@ -797,26 +793,21 @@ func (cs *ChainStore) GetRandomness(ctx context.Context, blks []cid.Cid, tickets
|
||||
}
|
||||
|
||||
mtb := nts.MinTicketBlock()
|
||||
lt := int64(len(mtb.Tickets))
|
||||
if nv < lt {
|
||||
t := mtb.Tickets[lt-(1+nv)]
|
||||
return t.VRFProof, nil
|
||||
}
|
||||
|
||||
nv -= lt
|
||||
if int64(nts.Height()) <= round {
|
||||
return ticketHash(nts.MinTicketBlock().Ticket, round), nil
|
||||
}
|
||||
|
||||
// special case for lookback behind genesis block
|
||||
// TODO(spec): this is not in the spec, need to sync that
|
||||
if mtb.Height == 0 {
|
||||
|
||||
t := mtb.Tickets[0]
|
||||
// round is negative
|
||||
thash := ticketHash(mtb.Ticket, round*-1)
|
||||
|
||||
rval := t.VRFProof
|
||||
for i := int64(0); i < nv; i++ {
|
||||
h := sha256.Sum256(rval)
|
||||
rval = h[:]
|
||||
}
|
||||
return rval, nil
|
||||
// for negative lookbacks, just use the hash of the positive tickethash value
|
||||
h := sha256.Sum256(thash)
|
||||
return h[:], nil
|
||||
}
|
||||
|
||||
blks = mtb.Parents
|
||||
@ -837,36 +828,33 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h uint64, ts *types
|
||||
}
|
||||
|
||||
for {
|
||||
mtb := ts.MinTicketBlock()
|
||||
if h >= ts.Height()-uint64(len(mtb.Tickets)) {
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
pts, err := cs.LoadTipSet(ts.Parents())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if h > pts.Height() {
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
ts = pts
|
||||
}
|
||||
}
|
||||
|
||||
type chainRand struct {
|
||||
cs *ChainStore
|
||||
blks []cid.Cid
|
||||
bh uint64
|
||||
tickets []*types.Ticket
|
||||
cs *ChainStore
|
||||
blks []cid.Cid
|
||||
bh uint64
|
||||
}
|
||||
|
||||
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64, tickets []*types.Ticket) vm.Rand {
|
||||
func NewChainRand(cs *ChainStore, blks []cid.Cid, bheight uint64) vm.Rand {
|
||||
return &chainRand{
|
||||
cs: cs,
|
||||
blks: blks,
|
||||
bh: bheight,
|
||||
tickets: tickets,
|
||||
cs: cs,
|
||||
blks: blks,
|
||||
bh: bheight,
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, h int64) ([]byte, error) {
|
||||
lb := (int64(cr.bh) + int64(len(cr.tickets))) - h
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, cr.tickets, lb)
|
||||
func (cr *chainRand) GetRandomness(ctx context.Context, round int64) ([]byte, error) {
|
||||
return cr.cs.GetRandomness(ctx, cr.blks, round)
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"golang.org/x/xerrors"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var zero = types.NewInt(0)
|
||||
@ -57,7 +58,7 @@ func (cs *ChainStore) Weight(ctx context.Context, ts *types.TipSet) (types.BigIn
|
||||
func (cs *ChainStore) call(ctx context.Context, msg *types.Message, ts *types.TipSet) (*types.MessageReceipt, error) {
|
||||
bstate := ts.ParentState()
|
||||
|
||||
r := NewChainRand(cs, ts.Cids(), ts.Height(), nil)
|
||||
r := NewChainRand(cs, ts.Cids(), ts.Height())
|
||||
|
||||
vmi, err := vm.NewVM(bstate, ts.Height(), r, actors.NetworkAddress, cs.bs)
|
||||
if err != nil {
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/address"
|
||||
"github.com/filecoin-project/lotus/chain/blocksync"
|
||||
"github.com/filecoin-project/lotus/chain/gen"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
@ -466,30 +467,22 @@ func (syncer *Syncer) minerIsValid(ctx context.Context, maddr address.Address, b
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Address, tickets []*types.Ticket, base *types.TipSet) error {
|
||||
func (syncer *Syncer) validateTicket(ctx context.Context, mworker address.Address, ticket *types.Ticket, base *types.TipSet, round uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "validateTickets")
|
||||
defer span.End()
|
||||
span.AddAttributes(trace.Int64Attribute("tickets", int64(len(tickets))))
|
||||
|
||||
if len(tickets) == 0 {
|
||||
return xerrors.Errorf("block had no tickets")
|
||||
sig := &types.Signature{
|
||||
Type: types.KTBLS,
|
||||
Data: ticket.VRFProof,
|
||||
}
|
||||
|
||||
cur := base.MinTicket()
|
||||
for i := 0; i < len(tickets); i++ {
|
||||
next := tickets[i]
|
||||
vrfBase := gen.TicketHash(base.MinTicket(), round)
|
||||
|
||||
sig := &types.Signature{
|
||||
Type: types.KTBLS,
|
||||
Data: next.VRFProof,
|
||||
}
|
||||
log.Infof("about to verify ticket: %x %d", base.MinTicket().VRFProof, round)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
cur = next
|
||||
// TODO: ticket signatures should also include miner address
|
||||
if err := sig.Verify(mworker, vrfBase); err != nil {
|
||||
return xerrors.Errorf("invalid ticket, VRFProof invalid: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -514,9 +507,9 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
return xerrors.Errorf("block was from the future")
|
||||
}
|
||||
|
||||
if h.Timestamp < baseTs.MinTimestamp()+uint64(build.BlockDelay*len(h.Tickets)) {
|
||||
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), len(h.Tickets))
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * tkts.len:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, len(h.Tickets))
|
||||
if h.Timestamp < baseTs.MinTimestamp()+(build.BlockDelay*(h.Height-baseTs.Height())) {
|
||||
log.Warn("timestamp funtimes: ", h.Timestamp, baseTs.MinTimestamp(), h.Height, baseTs.Height())
|
||||
return xerrors.Errorf("block was generated too soon (h.ts:%d < base.mints:%d + BLOCK_DELAY:%d * deltaH:%d)", h.Timestamp, baseTs.MinTimestamp(), build.BlockDelay, h.Height-baseTs.Height())
|
||||
}
|
||||
|
||||
winnerCheck := async.Err(func() error {
|
||||
@ -583,14 +576,14 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
|
||||
})
|
||||
|
||||
tktsCheck := async.Err(func() error {
|
||||
if err := syncer.validateTickets(ctx, waddr, h.Tickets, baseTs); err != nil {
|
||||
if err := syncer.validateTicket(ctx, waddr, h.Ticket, baseTs, h.Height); err != nil {
|
||||
return xerrors.Errorf("validating block tickets failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
eproofCheck := async.Err(func() error {
|
||||
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), h.Tickets, build.EcRandomnessLookback)
|
||||
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), int64(h.Height-build.EcRandomnessLookback))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ func TestSyncBadTimestamp(t *testing.T) {
|
||||
tu.waitUntilSync(0, client)
|
||||
|
||||
base := tu.g.CurTipset
|
||||
tu.g.Timestamper = func(pts *types.TipSet, tl int) uint64 {
|
||||
tu.g.Timestamper = func(pts *types.TipSet, tl uint64) uint64 {
|
||||
return pts.MinTimestamp() + (build.BlockDelay / 2)
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ type ElectionProof []byte
|
||||
type BlockHeader struct {
|
||||
Miner address.Address
|
||||
|
||||
Tickets []*Ticket
|
||||
Ticket *Ticket
|
||||
|
||||
ElectionProof []byte
|
||||
|
||||
@ -91,7 +91,7 @@ func (blk *BlockHeader) Serialize() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (blk *BlockHeader) LastTicket() *Ticket {
|
||||
return blk.Tickets[len(blk.Tickets)-1]
|
||||
return blk.Ticket
|
||||
}
|
||||
|
||||
func (blk *BlockHeader) SigningBytes() ([]byte, error) {
|
||||
|
@ -25,10 +25,8 @@ func testBlockHeader(t testing.TB) *BlockHeader {
|
||||
return &BlockHeader{
|
||||
Miner: addr,
|
||||
ElectionProof: []byte("cats won the election"),
|
||||
Tickets: []*Ticket{
|
||||
&Ticket{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
},
|
||||
Ticket: &Ticket{
|
||||
VRFProof: []byte("vrf proof0000000vrf proof0000000"),
|
||||
},
|
||||
Parents: []cid.Cid{c, c},
|
||||
ParentMessageReceipts: c,
|
||||
|
@ -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"
|
||||
)
|
||||
@ -28,15 +28,10 @@ func (t *BlockHeader) MarshalCBOR(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.t.Tickets ([]*types.Ticket) (slice)
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Tickets)))); err != nil {
|
||||
// t.t.Ticket (types.Ticket) (struct)
|
||||
if err := t.Ticket.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Tickets {
|
||||
if err := v.MarshalCBOR(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.t.ElectionProof ([]uint8) (slice)
|
||||
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.ElectionProof)))); err != nil {
|
||||
@ -125,32 +120,27 @@ func (t *BlockHeader) UnmarshalCBOR(r io.Reader) error {
|
||||
}
|
||||
|
||||
}
|
||||
// t.t.Tickets ([]*types.Ticket) (slice)
|
||||
// t.t.Ticket (types.Ticket) (struct)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if extra > 8192 {
|
||||
return fmt.Errorf("t.Tickets: array too large (%d)", extra)
|
||||
}
|
||||
{
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
if extra > 0 {
|
||||
t.Tickets = make([]*Ticket, extra)
|
||||
}
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v Ticket
|
||||
if err := v.UnmarshalCBOR(br); err != nil {
|
||||
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.Ticket = new(Ticket)
|
||||
if err := t.Ticket.UnmarshalCBOR(br); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
t.Tickets[i] = &v
|
||||
}
|
||||
|
||||
// t.t.ElectionProof ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cbg.CborReadHeader(br)
|
||||
|
@ -165,8 +165,7 @@ func (t *Ticket) Less(o *Ticket) bool {
|
||||
}
|
||||
|
||||
func (ts *TipSet) MinTicket() *Ticket {
|
||||
b := ts.MinTicketBlock()
|
||||
return b.Tickets[len(b.Tickets)-1]
|
||||
return ts.MinTicketBlock().Ticket
|
||||
}
|
||||
|
||||
func (ts *TipSet) MinTimestamp() uint64 {
|
||||
|
@ -161,8 +161,8 @@ eventLoop:
|
||||
log.Errorf("failed to get best mining candidate: %s", err)
|
||||
continue
|
||||
}
|
||||
if base.ts.Equals(lastBase.ts) && len(lastBase.tickets) == len(base.tickets) {
|
||||
log.Errorf("BestMiningCandidate from the previous round: %s (tkts:%d)", lastBase.ts.Cids(), len(lastBase.tickets))
|
||||
if base.ts.Equals(lastBase.ts) && lastBase.nullRounds == base.nullRounds {
|
||||
log.Errorf("BestMiningCandidate from the previous round: %s (nulls:%d)", lastBase.ts.Cids(), lastBase.nullRounds)
|
||||
time.Sleep(build.BlockDelay * time.Second)
|
||||
continue
|
||||
}
|
||||
@ -205,15 +205,15 @@ eventLoop:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*len(base.tickets))), 0)
|
||||
nextRound := time.Unix(int64(base.ts.MinTimestamp()+uint64(build.BlockDelay*base.nullRounds)), 0)
|
||||
time.Sleep(time.Until(nextRound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type MiningBase struct {
|
||||
ts *types.TipSet
|
||||
tickets []*types.Ticket
|
||||
ts *types.TipSet
|
||||
nullRounds uint64
|
||||
}
|
||||
|
||||
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
|
||||
@ -253,13 +253,13 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return nil, errors.Wrap(err, "scratching ticket failed")
|
||||
}
|
||||
|
||||
win, proof, err := gen.IsRoundWinner(ctx, base.ts, append(base.tickets, ticket), addr, &m.api)
|
||||
win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, &m.api)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to check if we win next round")
|
||||
}
|
||||
|
||||
if !win {
|
||||
m.submitNullTicket(base, ticket)
|
||||
base.nullRounds++
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -272,11 +272,6 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (m *Miner) submitNullTicket(base *MiningBase, ticket *types.Ticket) {
|
||||
base.tickets = append(base.tickets, ticket)
|
||||
m.lastWork = base
|
||||
}
|
||||
|
||||
func (m *Miner) computeVRF(ctx context.Context, addr address.Address, input []byte) ([]byte, error) {
|
||||
w, err := m.getMinerWorker(ctx, addr, nil)
|
||||
if err != nil {
|
||||
@ -309,14 +304,11 @@ func (m *Miner) getMinerWorker(ctx context.Context, addr address.Address, ts *ty
|
||||
}
|
||||
|
||||
func (m *Miner) scratchTicket(ctx context.Context, addr address.Address, base *MiningBase) (*types.Ticket, error) {
|
||||
var lastTicket *types.Ticket
|
||||
if len(base.tickets) > 0 {
|
||||
lastTicket = base.tickets[len(base.tickets)-1]
|
||||
} else {
|
||||
lastTicket = base.ts.MinTicket()
|
||||
}
|
||||
round := base.ts.Height() + base.nullRounds
|
||||
|
||||
vrfOut, err := m.computeVRF(ctx, addr, lastTicket.VRFProof)
|
||||
vrfBase := gen.TicketHash(base.ts.MinTicket(), round)
|
||||
|
||||
vrfOut, err := m.computeVRF(ctx, addr, vrfBase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -338,10 +330,12 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type
|
||||
return nil, xerrors.Errorf("message filtering failed: %w", err)
|
||||
}
|
||||
|
||||
uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(len(base.tickets)+1))
|
||||
uts := base.ts.MinTimestamp() + uint64(build.BlockDelay*(base.nullRounds+1))
|
||||
|
||||
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, append(base.tickets, ticket), proof, msgs, uint64(uts))
|
||||
return m.api.MinerCreateBlock(context.TODO(), addr, base.ts, ticket, proof, msgs, nheight, uint64(uts))
|
||||
}
|
||||
|
||||
type actorLookup func(context.Context, address.Address, *types.TipSet) (*types.Actor, error)
|
||||
|
@ -28,8 +28,8 @@ func (a *ChainAPI) ChainHead(context.Context) (*types.TipSet, error) {
|
||||
return a.Chain.GetHeaviestTipSet(), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, tickets []*types.Ticket, lb int) ([]byte, error) {
|
||||
return a.Chain.GetRandomness(ctx, pts.Cids(), tickets, int64(lb))
|
||||
func (a *ChainAPI) ChainGetRandomness(ctx context.Context, pts types.TipSetKey, round int64) ([]byte, error) {
|
||||
return a.Chain.GetRandomness(ctx, pts.Cids(), round)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainGetBlock(ctx context.Context, msg cid.Cid) (*types.BlockHeader, error) {
|
||||
|
@ -177,8 +177,8 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, ts *typ
|
||||
}
|
||||
|
||||
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, tickets []*types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, ts uint64) (*types.BlockMsg, error) {
|
||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, tickets, proof, msgs, ts)
|
||||
func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parents *types.TipSet, ticket *types.Ticket, proof types.ElectionProof, msgs []*types.SignedMessage, height, ts uint64) (*types.BlockMsg, error) {
|
||||
fblk, err := gen.MinerCreateBlock(ctx, a.StateManager, a.Wallet, addr, parents, ticket, proof, msgs, height, ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ func SealTicketGen(api api.FullNode) storage.TicketFn {
|
||||
return nil, xerrors.Errorf("getting head ts for SealTicket failed: %w", err)
|
||||
}
|
||||
|
||||
r, err := api.ChainGetRandomness(ctx, ts.Key(), nil, build.SealRandomnessLookback)
|
||||
r, err := api.ChainGetRandomness(ctx, ts.Key(), int64(ts.Height())-build.SealRandomnessLookback)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting randomness for SealTicket failed: %w", err)
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ type storageMinerApi interface {
|
||||
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainNotify(context.Context) (<-chan []*store.HeadChange, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, []*types.Ticket, int) ([]byte, error)
|
||||
ChainGetRandomness(context.Context, types.TipSetKey, int64) ([]byte, error)
|
||||
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error)
|
||||
ChainGetBlockMessages(context.Context, cid.Cid) (*api.BlockMessages, error)
|
||||
|
||||
|
@ -154,9 +154,8 @@ func (p *post) preparePost(ctx context.Context) error {
|
||||
|
||||
p.sset = sset
|
||||
|
||||
// Compute how many blocks back we have to look from the given tipset for the PoSt challenge
|
||||
challengeLookback := int((int64(p.ts.Height()) - int64(p.ppe)) + int64(build.PoStChallangeTime) + int64(build.PoStRandomnessLookback))
|
||||
r, err := p.m.api.ChainGetRandomness(ctx, p.ts.Key(), nil, challengeLookback)
|
||||
challengeRound := int64(p.ppe) - int64(build.PoStChallangeTime+build.PoStRandomnessLookback)
|
||||
r, err := p.m.api.ChainGetRandomness(ctx, p.ts.Key(), challengeRound)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get chain randomness for post (ts=%d; ppe=%d): %w", p.ts.Height(), p.ppe, err)
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ func (m *Miner) preCommitted(ctx context.Context, sector SectorInfo) (func(*Sect
|
||||
log.Infof("precommit for sector %d made it on chain, will start proof computation at height %d", sector.SectorID, randHeight)
|
||||
|
||||
err = m.events.ChainAt(func(ctx context.Context, ts *types.TipSet, curH uint64) error {
|
||||
rand, err := m.api.ChainGetRandomness(ctx, ts.Key(), nil, int(ts.Height()-randHeight))
|
||||
rand, err := m.api.ChainGetRandomness(ctx, ts.Key(), int64(randHeight))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get randomness for computing seal proof: %w", err)
|
||||
}
|
||||
|
@ -134,12 +134,8 @@ func loadTipsets(ctx context.Context, api api.FullNode, curr *types.TipSet, lowe
|
||||
log.Printf("Walking back { height:%d }", curr.Height())
|
||||
tipsets = append(tipsets, curr)
|
||||
|
||||
ph := ParentTipsetHeight(curr)
|
||||
if ph == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
prev, err := api.ChainGetTipSetByHeight(ctx, ph, curr)
|
||||
tsk := types.NewTipSetKey(curr.Parents()...)
|
||||
prev, err := api.ChainGetTipSet(ctx, tsk)
|
||||
if err != nil {
|
||||
return tipsets, err
|
||||
}
|
||||
@ -154,11 +150,6 @@ func loadTipsets(ctx context.Context, api api.FullNode, curr *types.TipSet, lowe
|
||||
return tipsets, nil
|
||||
}
|
||||
|
||||
func ParentTipsetHeight(tipset *types.TipSet) uint64 {
|
||||
mtb := tipset.MinTicketBlock()
|
||||
return tipset.Height() - uint64(len(mtb.Tickets)) - 1
|
||||
}
|
||||
|
||||
func GetFullNodeAPI(repo string) (api.FullNode, jsonrpc.ClientCloser, error) {
|
||||
addr, headers, err := getAPI(repo)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user