func (b *Blockchain) GetConfig() *config.Config {
	return b.config
}
GetConfig returns the config used by this blockchain
package beacon
import (
	"errors"
	"sync"
	"time"
	"github.com/sirupsen/logrus"
	"github.com/phoreproject/synapse/beacon/config"
	"github.com/phoreproject/synapse/beacon/db"
	"github.com/phoreproject/synapse/bls"
	"github.com/phoreproject/synapse/primitives"
	"github.com/phoreproject/synapse/primitives/proofs"
	"github.com/phoreproject/synapse/utils"
	"github.com/prysmaticlabs/go-ssz"
	"github.com/phoreproject/synapse/chainhash"
)
var zeroHash = chainhash.Hash{}
type Blockchain struct {
	View         *BlockchainView
	DB           db.Database
	config       *config.Config
	stateManager *StateManager
	notifees    []BlockchainNotifee
	notifeeLock sync.Mutex
}
func (b *Blockchain) getLatestAttestationTarget(validator uint32) (*BlockNode, error) {
	att, err := b.DB.GetLatestAttestation(validator)
	if err != nil {
		return nil, err
	}
	bl, err := b.DB.GetBlockForHash(att.Data.BeaconBlockHash)
	if err != nil {
		return nil, err
	}
	h, _ := ssz.HashTreeRoot(bl)
	node := b.View.Index.GetBlockNodeByHash(h)
	if node == nil {
		return nil, errors.New("couldn't find block attested to by validator in index")
	}
	return node, nil
}
func NewBlockchainWithInitialValidators(db db.Database, config *config.Config, validators []primitives.InitialValidatorEntry, skipValidation bool, genesisTime uint64) (*Blockchain, error) {
	b := &Blockchain{
		DB:     db,
		config: config,
		View:   NewBlockchainView(),
	}
	sm, err := NewStateManager(config, genesisTime, b, db)
	if err != nil {
		return nil, err
	}
	b.stateManager = sm
	initialState, err := primitives.InitializeState(config, validators, genesisTime, skipValidation)
	if err != nil {
		return nil, err
	}
	stateRoot, err := ssz.HashTreeRoot(initialState)
	if err != nil {
		return nil, err
	}
	block0 := primitives.Block{
		BlockHeader: primitives.BlockHeader{
			SlotNumber:     0,
			StateRoot:      stateRoot,
			ParentRoot:     zeroHash,
			RandaoReveal:   bls.EmptySignature.Serialize(),
			Signature:      bls.EmptySignature.Serialize(),
			ValidatorIndex: 0,
		},
		BlockBody: primitives.BlockBody{
			ProposerSlashings: []primitives.ProposerSlashing{},
			CasperSlashings:   []primitives.CasperSlashing{},
			Attestations:      []primitives.Attestation{},
			Deposits:          []primitives.Deposit{},
			Exits:             []primitives.Exit{},
		},
	}
	blockHash, err := ssz.HashTreeRoot(block0)
	if err != nil {
		return nil, err
	}
	logrus.WithField("genesisHash", chainhash.Hash(blockHash)).Info("initializing blockchain with genesis block")
	err = b.DB.SetBlock(block0)
	if err != nil {
		return nil, err
	}
	node, err := b.View.Index.AddBlockNodeToIndex(&block0, blockHash, stateRoot, proofs.GetValidatorHash(initialState))
	if err != nil {
		return nil, err
	}
	_, err = b.DB.GetBlockNode(blockHash)
	if err != nil {
		if err := b.initializeDatabase(node, *initialState); err != nil {
			return nil, err
		}
	} else {
		if err := b.loadBlockchainFromDisk(blockHash); err != nil {
			return nil, err
		}
	}
	return b, nil
}
func (b *Blockchain) GetUpdatedState(upTo uint64) (*primitives.State, error) {
	tip := b.View.Chain.Tip()
	view := NewChainView(tip)
	_, tipState, err := b.stateManager.GetStateForHashAtSlot(tip.Hash, upTo, &view, b.config)
	if err != nil {
		return nil, err
	}
	tipStateCopy := tipState.Copy()
	return &tipStateCopy, nil
}
func (b *Blockchain) GetNextSlotTime() time.Time {
	return time.Unix(int64((b.View.Chain.Tip().Slot+1)*uint64(b.config.SlotDuration)+b.stateManager.GetGenesisTime()), 0)
}
func (b *Blockchain) Height() uint64 {
	h := b.View.Chain.Height()
	if h < 0 {
		return 0
	}
	return uint64(h)
}
func (b *Blockchain) GetBlockByHash(h chainhash.Hash) (*primitives.Block, error) {
	block, err := b.DB.GetBlockForHash(h)
	if err != nil {
		return nil, err
	}
	return block, nil
}