lotus/chain/consensus/iface.go

86 lines
2.8 KiB
Go
Raw Normal View History

2021-09-02 16:07:23 +00:00
package consensus
import (
"context"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"go.opencensus.io/stats"
2021-09-02 16:07:23 +00:00
"github.com/filecoin-project/go-address"
2021-09-02 16:07:23 +00:00
"github.com/filecoin-project/go-state-types/abi"
2022-06-14 15:00:51 +00:00
2021-09-02 16:07:23 +00:00
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/stmgr"
2021-09-02 16:07:23 +00:00
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/metrics"
2021-09-02 16:07:23 +00:00
)
type Consensus interface {
ValidateBlock(ctx context.Context, b *types.FullBlock) (err error)
ValidateBlockHeader(ctx context.Context, b *types.BlockHeader) (rejectReason string, err error)
2021-09-02 16:07:23 +00:00
IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool
CreateBlock(ctx context.Context, w api.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error)
SignBlock(ctx context.Context, w api.Wallet, addr address.Address, next *types.BlockHeader) error
VerifyBlockSignature(ctx context.Context, h *types.BlockHeader, addr address.Address) error
}
// RewardFunc parametrizes the logic for rewards when a message is executed.
//
// Each consensus implementation can set their own reward function.
type RewardFunc func(ctx context.Context, vmi vm.Interface, em stmgr.ExecMonitor,
epoch abi.ChainEpoch, ts *types.TipSet, params []byte) error
// ValidateBlockPubsub implements the common checks performed by all consensus implementations
// when a block is received through the pubsub channel.
func ValidateBlockPubsub(ctx context.Context, cns Consensus, self bool, msg *pubsub.Message) (pubsub.ValidationResult, string) {
if self {
return validateLocalBlock(ctx, msg)
}
// track validation time
begin := build.Clock.Now()
defer func() {
log.Debugf("block validation time: %s", build.Clock.Since(begin))
}()
stats.Record(ctx, metrics.BlockReceived.M(1))
recordFailureFlagPeer := func(what string) {
// bv.Validate will flag the peer in that case
panic(what)
}
blk, what, err := decodeAndCheckBlock(msg)
if err != nil {
log.Error("got invalid block over pubsub: ", err)
recordFailureFlagPeer(what)
return pubsub.ValidationReject, what
}
// validate the block meta: the Message CID in the header must match the included messages
err = validateMsgMeta(ctx, blk)
if err != nil {
log.Warnf("error validating message metadata: %s", err)
recordFailureFlagPeer("invalid_block_meta")
return pubsub.ValidationReject, "invalid_block_meta"
}
reject, err := cns.ValidateBlockHeader(ctx, blk.Header)
if err != nil {
if reject == "" {
log.Warn("ignoring block msg: ", err)
return pubsub.ValidationIgnore, reject
}
recordFailureFlagPeer(reject)
return pubsub.ValidationReject, reject
}
// all good, accept the block
msg.ValidatorData = blk
stats.Record(ctx, metrics.BlockValidationSuccess.M(1))
return pubsub.ValidationAccept, ""
2021-09-02 16:07:23 +00:00
}