add godocs to miner objects.
This commit is contained in:
parent
8f78066d4f
commit
87efc9d536
@ -37,7 +37,13 @@ const (
|
||||
evtTypeBlockMined = iota
|
||||
)
|
||||
|
||||
// returns a callback reporting whether we mined a blocks in this round
|
||||
// waitFunc is expected to pace block mining at the configured network rate.
|
||||
//
|
||||
// baseTime is the timestamp of the mining base, i.e. the timestamp
|
||||
// of the tipset we're planning to construct upon.
|
||||
//
|
||||
// Upon each mining loop iteration, the returned callback is called reporting
|
||||
// whether we mined a block in this round or not.
|
||||
type waitFunc func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error)
|
||||
|
||||
func randTimeOffset(width time.Duration) time.Duration {
|
||||
@ -48,6 +54,8 @@ func randTimeOffset(width time.Duration) time.Duration {
|
||||
return val - (width / 2)
|
||||
}
|
||||
|
||||
// NewMiner instantiates a miner with a concrete WinningPoStProver and a miner
|
||||
// address (which can be different from the worker's address).
|
||||
func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address, sf *slashfilter.SlashFilter, j journal.Journal) *Miner {
|
||||
arc, err := lru.NewARC(10000)
|
||||
if err != nil {
|
||||
@ -59,7 +67,16 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
|
||||
epp: epp,
|
||||
address: addr,
|
||||
waitFunc: func(ctx context.Context, baseTime uint64) (func(bool, abi.ChainEpoch, error), abi.ChainEpoch, error) {
|
||||
// Wait around for half the block time in case other parents come in
|
||||
// wait around for half the block time in case other parents come in
|
||||
//
|
||||
// if we're mining a block in the past via catch-up/rush mining,
|
||||
// such as when recovering from a network halt, this sleep will be
|
||||
// for a negative duration, and therefore **will return
|
||||
// immediately**.
|
||||
//
|
||||
// the result is that we WILL NOT wait, therefore fast-forwarding
|
||||
// and thus healing the chain by backfilling it with null rounds
|
||||
// rapidly.
|
||||
deadline := baseTime + build.PropagationDelaySecs
|
||||
baseT := time.Unix(int64(deadline), 0)
|
||||
|
||||
@ -79,6 +96,9 @@ func NewMiner(api api.FullNode, epp gen.WinningPoStProver, addr address.Address,
|
||||
}
|
||||
}
|
||||
|
||||
// Miner encapsulates the mining processes of the system.
|
||||
//
|
||||
// Refer to the godocs on mineOne and mine methods for more detail.
|
||||
type Miner struct {
|
||||
api api.FullNode
|
||||
|
||||
@ -91,15 +111,20 @@ type Miner struct {
|
||||
|
||||
waitFunc waitFunc
|
||||
|
||||
// lastWork holds the last MiningBase we built upon.
|
||||
lastWork *MiningBase
|
||||
|
||||
sf *slashfilter.SlashFilter
|
||||
// minedBlockHeights is a safeguard that caches the last heights we mined.
|
||||
// It is consulted before publishing a newly mined block, for a sanity check
|
||||
// intended to avoid slashings in case of a bug.
|
||||
minedBlockHeights *lru.ARCCache
|
||||
|
||||
evtTypes [1]journal.EventType
|
||||
journal journal.Journal
|
||||
}
|
||||
|
||||
// Address returns the address of the miner.
|
||||
func (m *Miner) Address() address.Address {
|
||||
m.lk.Lock()
|
||||
defer m.lk.Unlock()
|
||||
@ -107,7 +132,9 @@ func (m *Miner) Address() address.Address {
|
||||
return m.address
|
||||
}
|
||||
|
||||
func (m *Miner) Start(ctx context.Context) error {
|
||||
// Start starts the mining operation. It spawns a goroutine and returns
|
||||
// immediately. Start is not idempotent.
|
||||
func (m *Miner) Start(_ context.Context) error {
|
||||
m.lk.Lock()
|
||||
defer m.lk.Unlock()
|
||||
if m.stop != nil {
|
||||
@ -118,6 +145,8 @@ func (m *Miner) Start(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops the mining operation. It is not idempotent, and multiple adjacent
|
||||
// calls to Stop will fail.
|
||||
func (m *Miner) Stop(ctx context.Context) error {
|
||||
m.lk.Lock()
|
||||
|
||||
@ -145,6 +174,28 @@ func (m *Miner) niceSleep(d time.Duration) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// mine runs the mining loop. It performs the following:
|
||||
//
|
||||
// 1. Queries our current best currently-known mining candidate (tipset to
|
||||
// build upon).
|
||||
// 2. Waits until the propagation delay of the network has elapsed (currently
|
||||
// 6 seconds). The waiting is done relative to the timestamp of the best
|
||||
// candidate, which means that if it's way in the past, we won't wait at
|
||||
// all (e.g. in catch-up or rush mining).
|
||||
// 3. After the wait, we query our best mining candidate. This will be the one
|
||||
// we'll work with.
|
||||
// 4. Sanity check that we _actually_ have a new mining base to mine on. If
|
||||
// not, wait one epoch + propagation delay, and go back to the top.
|
||||
// 5. We attempt to mine a block, by calling mineOne (refer to godocs). This
|
||||
// method will either return a block if we were eligible to mine, or nil
|
||||
// if we weren't.
|
||||
// 6a. If we mined a block, we update our state and push it out to the network
|
||||
// via gossipsub.
|
||||
// 6b. If we didn't mine a block, we consider this to be a nil round on top of
|
||||
// the mining base we selected. If other miner or miners on the network
|
||||
// were eligible to mine, we will receive their blocks via gossipsub and
|
||||
// we will select that tipset on the next iteration of the loop, thus
|
||||
// discarding our null round.
|
||||
func (m *Miner) mine(ctx context.Context) {
|
||||
ctx, span := trace.StartSpan(ctx, "/mine")
|
||||
defer span.End()
|
||||
@ -305,11 +356,19 @@ minerLoop:
|
||||
}
|
||||
}
|
||||
|
||||
// MiningBase is the tipset on top of which we plan to construct our next block.
|
||||
// Refer to godocs on GetBestMiningCandidate.
|
||||
type MiningBase struct {
|
||||
TipSet *types.TipSet
|
||||
NullRounds abi.ChainEpoch
|
||||
}
|
||||
|
||||
// GetBestMiningCandidate implements the fork choice rule from a miner's
|
||||
// perspective.
|
||||
//
|
||||
// It obtains the current chain head (HEAD), and compares it to the last tipset
|
||||
// we selected as our mining base (LAST). If HEAD's weight is larger than
|
||||
// LAST's weight, it selects HEAD to build on. Else, it selects LAST.
|
||||
func (m *Miner) GetBestMiningCandidate(ctx context.Context) (*MiningBase, error) {
|
||||
m.lk.Lock()
|
||||
defer m.lk.Unlock()
|
||||
|
Loading…
Reference in New Issue
Block a user