@@ -5,9 +5,19 @@ import (
 	"fmt"
 	"time"
 
+	"github.com/pkg/errors"
+
+	"github.com/filecoin-project/go-filecoin/clock"
 	"github.com/filecoin-project/go-filecoin/types"
 )
 
+var (
+	// ErrTooSoon is returned when a block is generated too soon after its parent.
+	ErrTooSoon = errors.New("block was generated too soon")
+	// ErrInvalidHeight is returned when a block has an invliad height.
+	ErrInvalidHeight = errors.New("block has invalid height")
+)
+
 // BlockValidator defines an interface used to validate a blocks syntax and
 // semantics.
 type BlockValidator interface {
package consensus

import (
	"context"
	"fmt"
	"time"

	"github.com/filecoin-project/go-filecoin/types"
)

// BlockValidator defines an interface used to validate a blocks syntax and
// semantics.
type BlockValidator interface {
	BlockSemanticValidator
	BlockSyntaxValidator
}

// BlockSemanticValidator defines an interface used to validate a blocks
// semantics.
type BlockSemanticValidator interface {
	ValidateSemantic(ctx context.Context, child *types.Block, parents *types.TipSet) error
}

// BlockSyntaxValidator defines an interface used to validate a blocks
// syntax.
type BlockSyntaxValidator interface {
	ValidateSyntax(ctx context.Context, blk *types.Block) error
}

// BlockValidationClock defines an interface for fetching unix epoch time.
type BlockValidationClock interface {
	EpochSeconds() uint64
}

// DefaultBlockValidationClock implements BlockValidationClock using the
// Go time package.
type DefaultBlockValidationClock struct{}

// NewDefaultBlockValidationClock returns a DefaultBlockValidationClock.
func NewDefaultBlockValidationClock() *DefaultBlockValidationClock {
	return &DefaultBlockValidationClock{}
}

// EpochSeconds returns Unix time, the number of seconds elapsed since January 1, 1970 UTC.
// The result does not depend on location.
func (ebc *DefaultBlockValidationClock) EpochSeconds() uint64 {
	return uint64(time.Now().Unix())
}

// DefaultBlockValidator implements the BlockValidator interface.
type DefaultBlockValidator struct {
	clock     BlockValidationClock
	blockTime time.Duration
}

// NewDefaultBlockValidator returns a new DefaultBlockValidator. It uses `blkTime`
// to validate blocks and uses the DefaultBlockValidationClock.
func NewDefaultBlockValidator(blkTime time.Duration) *DefaultBlockValidator {
	return &DefaultBlockValidator{
		clock:     NewDefaultBlockValidationClock(),
		blockTime: blkTime,
	}
}

// ValidateSemantic validates a block is correctly derived from its parent.
func (dv *DefaultBlockValidator) ValidateSemantic(ctx context.Context, child *types.Block, parents *types.TipSet) error {
	// TODO validate timestamp
	// #2886
	return nil
}

// ValidateSyntax validates a single block is correctly formed.
func (dv *DefaultBlockValidator) ValidateSyntax(ctx context.Context, blk *types.Block) error {
	if !blk.StateRoot.Defined() {
		return fmt.Errorf("block has nil StateRoot")
	}
	// TODO validate timestamp
	// TODO validate block signature
	// #2886
	return nil
}

// BlockTime returns the block time the DefaultBlockValidator uses to validate
/// blocks against.
func (dv *DefaultBlockValidator) BlockTime() time.Duration {
	return dv.blockTime
}

Typo in `invliad`