diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go
index 3112571759a2743eef2e619046b7af0410af6076..6827c69a1ec8cc09dc89c736ee3cf247c68a9720 100644
--- a/consensus/bor/bor.go
+++ b/consensus/bor/bor.go
@@ -8,7 +8,6 @@ import (
 	"io"
 	"math"
 	"math/big"
-	"math/rand"
 	"strings"
 	"sync"
 	"time"
@@ -39,7 +38,7 @@ const (
 	inmemorySnapshots    = 128  // Number of recent vote snapshots to keep in memory
 	inmemorySignatures   = 4096 // Number of recent block signatures to keep in memory
 
-	wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
+	wiggleTime = 1000 * time.Millisecond // Random delay (per signer) to allow concurrent signers
 )
 
 // Bor protocol constants.
@@ -116,9 +115,9 @@ var (
 	// the previous block's timestamp + the minimum block period.
 	ErrInvalidTimestamp = errors.New("invalid timestamp")
 
-	// errInvalidVotingChain is returned if an authorization list is attempted to
+	// errOutOfRangeChain is returned if an authorization list is attempted to
 	// be modified via out-of-range or non-contiguous headers.
-	errInvalidVotingChain = errors.New("invalid voting chain")
+	errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
 
 	// errUnauthorizedSigner is returned if a header is signed by a non-authorized entity.
 	errUnauthorizedSigner = errors.New("unauthorized signer")
@@ -191,21 +190,26 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
 // that a new block should have based on the previous blocks in the chain and the
 // current signer.
-func CalcDifficulty(snap *Snapshot, signer common.Address, producerPeriod uint64) *big.Int {
-	if snap.inturn(snap.Number+1, signer, producerPeriod) {
-		return new(big.Int).Set(diffInTurn)
-	}
-	return new(big.Int).Set(diffNoTurn)
+func CalcDifficulty(snap *Snapshot, signer common.Address, epoch uint64) *big.Int {
+	return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, epoch))
 }
 
 // CalcProducerDelay is the producer delay algorithm based on block time.
-func CalcProducerDelay(snap *Snapshot, producerInterval uint64, producerDelay uint64) uint64 {
-	isFirstBlock := (snap.Number + 1) % producerInterval
-	if isFirstBlock == 0 {
+func CalcProducerDelay(snap *Snapshot, signer common.Address, period uint64, epoch uint64, producerDelay uint64) uint64 {
+	// lastSigner := snap.Recents[snap.Number]
+	// proposer := snap.ValidatorSet.GetProposer()
+
+	// if block is epoch start block, proposer will be inturn signer
+	if (snap.Number+1)%epoch == 0 {
+		fmt.Println("==>", "producerDelay", producerDelay, "(snap.Number+1)%epoch", (snap.Number+1)%epoch)
 		return producerDelay
+
+		// if block is not epoch block, last block signer will be inturn
+		// } else if bytes.Compare(lastSigner.Bytes(), signer.Bytes()) != 0 {
+		// return producerDelay
 	}
 
-	return 0
+	return period
 }
 
 // BorRLP returns the rlp bytes which needs to be signed for the bor
@@ -235,7 +239,8 @@ type Bor struct {
 	signFn SignerFn       // Signer function to authorize hashes with
 	lock   sync.RWMutex   // Protects the signer fields
 
-	ethAPI *ethapi.PublicBlockChainAPI
+	ethAPI          *ethapi.PublicBlockChainAPI
+	validatorSetABI abi.ABI
 
 	// The fields below are for testing only
 	fakeDiff bool // Skip difficulty verifications
@@ -248,18 +253,21 @@ func New(config *params.BorConfig, db ethdb.Database, ethAPI *ethapi.PublicBlock
 	if conf.Epoch == 0 {
 		conf.Epoch = epochLength
 	}
+
 	// Allocate the snapshot caches and create the engine
 	recents, _ := lru.NewARC(inmemorySnapshots)
 	signatures, _ := lru.NewARC(inmemorySignatures)
-
-	return &Bor{
-		config:     &conf,
-		db:         db,
-		ethAPI:     ethAPI,
-		recents:    recents,
-		signatures: signatures,
-		proposals:  make(map[common.Address]bool),
-	}
+	validatorSetABI, _ := abi.JSON(strings.NewReader(validatorset.ValidatorsetABI))
+	c := &Bor{
+		config:          &conf,
+		db:              db,
+		ethAPI:          ethAPI,
+		recents:         recents,
+		signatures:      signatures,
+		proposals:       make(map[common.Address]bool),
+		validatorSetABI: validatorSetABI,
+	}
+	return c
 }
 
 // Author implements consensus.Engine, returning the Ethereum address recovered
@@ -381,20 +389,22 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.H
 		return ErrInvalidTimestamp
 	}
 	// Retrieve the snapshot needed to verify this header and cache it
-	snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
-	if err != nil {
-		return err
-	}
+	// snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
+	// if err != nil {
+	// 	return err
+	// }
+
 	// If the block is a checkpoint block, verify the signer list
+	// TODO verify signers
 	if number%c.config.Epoch == 0 {
-		signers := make([]byte, len(snap.Signers)*common.AddressLength)
-		for i, signer := range snap.signers() {
-			copy(signers[i*common.AddressLength:], signer[:])
-		}
-		extraSuffix := len(header.Extra) - extraSeal
-		if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) {
-			return errMismatchingCheckpointSigners
-		}
+		// signers := make([]byte, len(snap.Signers)*common.AddressLength)
+		// for i, signer := range snap.signers() {
+		// 	copy(signers[i*common.AddressLength:], signer[:])
+		// }
+		// extraSuffix := len(header.Extra) - extraSeal
+		// if !bytes.Equal(header.Extra[extraVanity:extraSuffix], signers) {
+		// 	return errMismatchingCheckpointSigners
+		// }
 	}
 	// All basic checks passed, verify the seal and return
 	return c.verifySeal(chain, header, parents)
@@ -415,7 +425,7 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H
 		}
 		// If an on-disk checkpoint snapshot can be found, use that
 		if number%voteSnapshotInterval == 0 {
-			if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
+			if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil {
 				log.Trace("Loaded voting snapshot from disk", "number", number, "hash", hash)
 				snap = s
 				break
@@ -428,15 +438,19 @@ func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.H
 			if checkpoint != nil {
 				hash := checkpoint.Hash()
 
-				// validatorSet := new(ValidatorSet)
-				// TODO populate validator set
-				c.GetCurrentValidators(number)
+				// current validators
+				validators, err := c.GetCurrentValidators(number)
+				if err != nil {
+					// Handle error
+				}
 
+				// TODO remove signer
 				signers := make([]common.Address, (len(checkpoint.Extra)-extraVanity-extraSeal)/common.AddressLength)
 				for i := 0; i < len(signers); i++ {
 					copy(signers[i][:], checkpoint.Extra[extraVanity+i*common.AddressLength:])
 				}
-				snap = newSnapshot(c.config, c.signatures, number, hash, signers)
+
+				snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI)
 				if err := snap.store(c.db); err != nil {
 					return nil, err
 				}
@@ -519,30 +533,43 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare
 	if err != nil {
 		return err
 	}
-	if _, ok := snap.Signers[signer]; !ok {
+
+	if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
 		return errUnauthorizedSigner
 	}
-	for seen, recent := range snap.Recents {
-		if recent == signer {
-			// Signer is among recents, only fail if the current block doesn't shift it out
-			if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit {
-				// return errRecentlySigned
-			}
+
+	// check if signer is correct
+	validators := snap.ValidatorSet.Validators
+	// proposer will be the last signer if block is not epoch block
+	proposer := snap.ValidatorSet.GetProposer().Address
+	if number%c.config.Epoch != 0 {
+		// proposer = snap.Recents[number-1]
+	}
+	proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
+	signerIndex, _ := snap.ValidatorSet.GetByAddress(signer)
+	limit := len(validators) - (len(validators)/2 + 1)
+
+	// temp index
+	tempIndex := signerIndex
+	if proposerIndex != tempIndex && limit > 0 {
+		if tempIndex < proposerIndex {
+			tempIndex = tempIndex + len(validators)
+		}
+
+		if tempIndex-proposerIndex > limit {
+			return errRecentlySigned
 		}
 	}
+
 	// Ensure that the difficulty corresponds to the turn-ness of the signer
 	if !c.fakeDiff {
-		inturn := snap.inturn(header.Number.Uint64(), signer, c.config.ProducerInterval)
-		if inturn && header.Difficulty.Cmp(diffInTurn) != 0 {
-			return errWrongDifficulty
-		}
-		if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 {
+		difficulty := snap.inturn(header.Number.Uint64(), signer, c.config.Epoch)
+		if header.Difficulty.Uint64() != difficulty {
 			return errWrongDifficulty
 		}
 	}
 
-	log.Info("==> New block", "number", header.Number, "hash", header.Hash().Hex(), "signer", signer.Hex())
-
+	fmt.Println("==> New block", "number", header.Number, "hash", header.Hash().Hex(), "signer", signer.Hex(), "proposer", proposer.Hex())
 	return nil
 }
 
@@ -559,29 +586,9 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
 	if err != nil {
 		return err
 	}
-	if number%c.config.Epoch != 0 {
-		c.lock.RLock()
 
-		// Gather all the proposals that make sense voting on
-		addresses := make([]common.Address, 0, len(c.proposals))
-		for address, authorize := range c.proposals {
-			if snap.validVote(address, authorize) {
-				addresses = append(addresses, address)
-			}
-		}
-		// If there's pending proposals, cast a vote on them
-		if len(addresses) > 0 {
-			header.Coinbase = addresses[rand.Intn(len(addresses))]
-			if c.proposals[header.Coinbase] {
-				copy(header.Nonce[:], nonceAuthVote)
-			} else {
-				copy(header.Nonce[:], nonceDropVote)
-			}
-		}
-		c.lock.RUnlock()
-	}
 	// Set the correct difficulty
-	header.Difficulty = CalcDifficulty(snap, c.signer, c.config.ProducerInterval)
+	header.Difficulty = CalcDifficulty(snap, c.signer, c.config.Epoch)
 
 	// Ensure the extra data has all it's components
 	if len(header.Extra) < extraVanity {
@@ -604,10 +611,12 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
 	if parent == nil {
 		return consensus.ErrUnknownAncestor
 	}
-	header.Time = parent.Time + c.config.Period + CalcProducerDelay(snap, c.config.ProducerInterval, c.config.ProducerDelay)
+
+	header.Time = parent.Time + CalcProducerDelay(snap, c.signer, c.config.Period, c.config.Epoch, c.config.ProducerDelay)
 	if header.Time < uint64(time.Now().Unix()) {
 		header.Time = uint64(time.Now().Unix())
 	}
+	fmt.Println("parent.Time", parent.Time, "header.Time", header.Time, "number", header.Number)
 	return nil
 }
 
@@ -660,43 +669,52 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
 	signer, signFn := c.signer, c.signFn
 	c.lock.RUnlock()
 
-	// Bail out if we're unauthorized to sign a block
 	snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
 	if err != nil {
 		return err
 	}
-	if _, authorized := snap.Signers[signer]; !authorized {
+
+	// Bail out if we're unauthorized to sign a block
+	if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
 		return errUnauthorizedSigner
 	}
-	// If we're amongst the recent signers, wait for the next block
-	for seen, recent := range snap.Recents {
-		count := 0
-		if recent == signer {
-			// count on how many times signer has been seen
-			count = count + 1
-
-			// Signer is among recents, only wait if the current block doesn't shift it out
-			if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit {
-				log.Info("Signed recently, must wait for others")
-				// return nil
-			}
-		}
+
+	validators := snap.ValidatorSet.Validators
+	// proposer will be the last signer if block is not epoch block
+	proposer := snap.ValidatorSet.GetProposer().Address
+	if number%c.config.Epoch != 0 {
+		// proposer = snap.Recents[number-1]
 	}
+	proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
+	signerIndex, _ := snap.ValidatorSet.GetByAddress(signer)
+	limit := len(validators) - (len(validators)/2 + 1)
+
+	// temp index
+	tempIndex := signerIndex
+	if tempIndex < proposerIndex {
+		tempIndex = tempIndex + len(validators)
+	}
+	fmt.Println("Block temp index", "number", number, "tempIndex", tempIndex, "proposerIndex", proposerIndex)
+	if limit > 0 && tempIndex-proposerIndex > limit {
+		log.Info("Signed recently, must wait for others")
+		return nil
+	}
+
 	// Sweet, the protocol permits us to sign the block, wait for our time
 	delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
-	if header.Difficulty.Cmp(diffNoTurn) == 0 {
-		// It's not our turn explicitly to sign, delay it a bit
-		wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime
-		delay += time.Duration(rand.Int63n(int64(wiggle)))
+	wiggle := time.Duration(wiggleTime) * time.Duration(tempIndex-proposerIndex)
+	delay += wiggle
+
+	fmt.Println("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
+	fmt.Println("--> Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "signer", signer.Hex(), "proposer", proposer.Hex())
 
-		log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
-	}
 	// Sign all the things!
 	sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header))
 	if err != nil {
 		return err
 	}
 	copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
+
 	// Wait until sealing is terminated or delay timeout.
 	log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
 	go func() {
@@ -724,7 +742,7 @@ func (c *Bor) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *t
 	if err != nil {
 		return nil
 	}
-	return CalcDifficulty(snap, c.signer, c.config.ProducerInterval)
+	return CalcDifficulty(snap, c.signer, c.config.Epoch)
 }
 
 // SealHash returns the hash of a block prior to it being sealed.
@@ -750,6 +768,11 @@ func (c *Bor) Close() error {
 
 // GetCurrentValidators get current validators
 func (c *Bor) GetCurrentValidators(number uint64) ([]*Validator, error) {
+	return GetValidators(number, c.config.ValidatorContract, c.ethAPI)
+}
+
+// GetValidators get current validators
+func GetValidators(number uint64, validatorContract string, ethAPI *ethapi.PublicBlockChainAPI) ([]*Validator, error) {
 	blockNr := rpc.BlockNumber(number)
 
 	// validator set ABI
@@ -765,9 +788,9 @@ func (c *Bor) GetCurrentValidators(number uint64) ([]*Validator, error) {
 
 	// call
 	msgData := (hexutil.Bytes)(data)
-	toAddress := common.HexToAddress(c.config.ValidatorContract)
+	toAddress := common.HexToAddress(validatorContract)
 	gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
-	result, err := c.ethAPI.Call(ctx, ethapi.CallArgs{
+	result, err := ethAPI.Call(ctx, ethapi.CallArgs{
 		Gas:  &gas,
 		To:   &toAddress,
 		Data: &msgData,
@@ -800,3 +823,37 @@ func (c *Bor) GetCurrentValidators(number uint64) ([]*Validator, error) {
 	}
 	return valz, nil
 }
+
+func validatorContains(a []*Validator, x *Validator) (*Validator, bool) {
+	for _, n := range a {
+		if bytes.Compare(n.Address.Bytes(), x.Address.Bytes()) == 0 {
+			return n, true
+		}
+	}
+	return nil, false
+}
+
+func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) *ValidatorSet {
+	v := oldValidatorSet
+	oldVals := v.Validators
+
+	var changes []*Validator
+	for _, ov := range oldVals {
+		if f, ok := validatorContains(newVals, ov); ok {
+			ov.VotingPower = f.VotingPower
+		} else {
+			ov.VotingPower = 0
+		}
+
+		changes = append(changes, ov)
+	}
+
+	for _, nv := range newVals {
+		if _, ok := validatorContains(changes, nv); !ok {
+			changes = append(changes, nv)
+		}
+	}
+
+	v.UpdateWithChangeSet(changes)
+	return v
+}
diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go
index a9148558c075315e6cab74364e863e186f725a06..f4201e4def77faafc2effc67262444e4b032c7cf 100644
--- a/consensus/bor/snapshot.go
+++ b/consensus/bor/snapshot.go
@@ -19,11 +19,12 @@ package bor
 import (
 	"bytes"
 	"encoding/json"
-	"sort"
+	"fmt"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/ethdb"
+	"github.com/ethereum/go-ethereum/internal/ethapi"
 	"github.com/ethereum/go-ethereum/params"
 	lru "github.com/hashicorp/golang-lru"
 )
@@ -47,14 +48,15 @@ type Tally struct {
 // Snapshot is the state of the authorization voting at a given point in time.
 type Snapshot struct {
 	config   *params.BorConfig // Consensus engine parameters to fine tune behavior
-	sigcache *lru.ARCCache     // Cache of recent block signatures to speed up ecrecover
-
-	Number  uint64                      `json:"number"`  // Block number where the snapshot was created
-	Hash    common.Hash                 `json:"hash"`    // Block hash where the snapshot was created
-	Signers map[common.Address]struct{} `json:"signers"` // Set of authorized signers at this moment
-	Recents map[uint64]common.Address   `json:"recents"` // Set of recent signers for spam protections
-	Votes   []*Vote                     `json:"votes"`   // List of votes cast in chronological order
-	Tally   map[common.Address]Tally    `json:"tally"`   // Current vote tally to avoid recalculating
+	ethAPI   *ethapi.PublicBlockChainAPI
+	sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
+
+	Number       uint64                    `json:"number"`       // Block number where the snapshot was created
+	Hash         common.Hash               `json:"hash"`         // Block hash where the snapshot was created
+	ValidatorSet *ValidatorSet             `json:"validatorSet"` // Validator set at this moment
+	Recents      map[uint64]common.Address `json:"recents"`      // Set of recent signers for spam protections
+	// Votes        []*Vote                   `json:"votes"`        // List of votes cast in chronological order
+	// Tally map[common.Address]Tally `json:"tally"` // Current vote tally to avoid recalculating
 }
 
 // signersAscending implements the sort interface to allow sorting a list of addresses
@@ -67,24 +69,23 @@ func (s signersAscending) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 // newSnapshot creates a new snapshot with the specified startup parameters. This
 // method does not initialize the set of recent signers, so only ever use if for
 // the genesis block.
-func newSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot {
+func newSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, validators []*Validator, ethAPI *ethapi.PublicBlockChainAPI) *Snapshot {
 	snap := &Snapshot{
-		config:   config,
-		sigcache: sigcache,
-		Number:   number,
-		Hash:     hash,
-		Signers:  make(map[common.Address]struct{}),
-		Recents:  make(map[uint64]common.Address),
-		Tally:    make(map[common.Address]Tally),
-	}
-	for _, signer := range signers {
-		snap.Signers[signer] = struct{}{}
+		config:       config,
+		ethAPI:       ethAPI,
+		sigcache:     sigcache,
+		Number:       number,
+		Hash:         hash,
+		ValidatorSet: NewValidatorSet(validators),
+		Recents:      make(map[uint64]common.Address),
+		// Tally:        make(map[common.Address]Tally),
 	}
+	fmt.Println("New validator set", "number", number, "proposer", snap.ValidatorSet.Proposer.Address.Hex())
 	return snap
 }
 
 // loadSnapshot loads an existing snapshot from the database.
-func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
+func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) {
 	blob, err := db.Get(append([]byte("bor-"), hash[:]...))
 	if err != nil {
 		return nil, err
@@ -95,6 +96,7 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat
 	}
 	snap.config = config
 	snap.sigcache = sigcache
+	snap.ethAPI = ethAPI
 
 	return snap, nil
 }
@@ -111,75 +113,71 @@ func (s *Snapshot) store(db ethdb.Database) error {
 // copy creates a deep copy of the snapshot, though not the individual votes.
 func (s *Snapshot) copy() *Snapshot {
 	cpy := &Snapshot{
-		config:   s.config,
-		sigcache: s.sigcache,
-		Number:   s.Number,
-		Hash:     s.Hash,
-		Signers:  make(map[common.Address]struct{}),
-		Recents:  make(map[uint64]common.Address),
-		Votes:    make([]*Vote, len(s.Votes)),
-		Tally:    make(map[common.Address]Tally),
-	}
-	for signer := range s.Signers {
-		cpy.Signers[signer] = struct{}{}
+		config:       s.config,
+		ethAPI:       s.ethAPI,
+		sigcache:     s.sigcache,
+		Number:       s.Number,
+		Hash:         s.Hash,
+		ValidatorSet: s.ValidatorSet.Copy(),
+		Recents:      make(map[uint64]common.Address),
+		// Votes:        make([]*Vote, len(s.Votes)),
+		// Tally:        make(map[common.Address]Tally),
 	}
 	for block, signer := range s.Recents {
 		cpy.Recents[block] = signer
 	}
-	for address, tally := range s.Tally {
-		cpy.Tally[address] = tally
-	}
-	copy(cpy.Votes, s.Votes)
+	// for address, tally := range s.Tally {
+	// 	cpy.Tally[address] = tally
+	// }
+	// copy(cpy.Votes, s.Votes)
 
 	return cpy
 }
 
-// validVote returns whether it makes sense to cast the specified vote in the
-// given snapshot context (e.g. don't try to add an already authorized signer).
-func (s *Snapshot) validVote(address common.Address, authorize bool) bool {
-	_, signer := s.Signers[address]
-	return (signer && !authorize) || (!signer && authorize)
-}
+// // validVote returns whether it makes sense to cast the specified vote in the
+// // given snapshot context (e.g. don't try to add an already authorized signer).
+// func (s *Snapshot) validVote(address common.Address, authorize bool) bool {
+// 	_, signer := s.Signers[address]
+// 	return (signer && !authorize) || (!signer && authorize)
+// }
 
-// cast adds a new vote into the tally.
-func (s *Snapshot) cast(address common.Address, authorize bool) bool {
-	// Ensure the vote is meaningful
-	if !s.validVote(address, authorize) {
-		return false
-	}
-	// Cast the vote into an existing or new tally
-	if old, ok := s.Tally[address]; ok {
-		old.Votes++
-		s.Tally[address] = old
-	} else {
-		s.Tally[address] = Tally{Authorize: authorize, Votes: 1}
-	}
-	return true
-}
+// // cast adds a new vote into the tally.
+// func (s *Snapshot) cast(address common.Address, authorize bool) bool {
+// 	// Ensure the vote is meaningful
+// 	if !s.validVote(address, authorize) {
+// 		return false
+// 	}
+// 	// Cast the vote into an existing or new tally
+// 	if old, ok := s.Tally[address]; ok {
+// 		old.Votes++
+// 		s.Tally[address] = old
+// 	} else {
+// 		s.Tally[address] = Tally{Authorize: authorize, Votes: 1}
+// 	}
+// 	return true
+// }
 
-// uncast removes a previously cast vote from the tally.
-func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
-	// If there's no tally, it's a dangling vote, just drop
-	tally, ok := s.Tally[address]
-	if !ok {
-		return false
-	}
-	// Ensure we only revert counted votes
-	if tally.Authorize != authorize {
-		return false
-	}
-	// Otherwise revert the vote
-	if tally.Votes > 1 {
-		tally.Votes--
-		s.Tally[address] = tally
-	} else {
-		delete(s.Tally, address)
-	}
-	return true
-}
+// // uncast removes a previously cast vote from the tally.
+// func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
+// 	// If there's no tally, it's a dangling vote, just drop
+// 	tally, ok := s.Tally[address]
+// 	if !ok {
+// 		return false
+// 	}
+// 	// Ensure we only revert counted votes
+// 	if tally.Authorize != authorize {
+// 		return false
+// 	}
+// 	// Otherwise revert the vote
+// 	if tally.Votes > 1 {
+// 		tally.Votes--
+// 		s.Tally[address] = tally
+// 	} else {
+// 		delete(s.Tally, address)
+// 	}
+// 	return true
+// }
 
-// apply creates a new authorization snapshot by applying the given headers to
-// the original one.
 func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
 	// Allow passing in no headers for cleaner code
 	if len(headers) == 0 {
@@ -188,11 +186,11 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
 	// Sanity check that the headers can be applied
 	for i := 0; i < len(headers)-1; i++ {
 		if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 {
-			return nil, errInvalidVotingChain
+			return nil, errOutOfRangeChain
 		}
 	}
 	if headers[0].Number.Uint64() != s.Number+1 {
-		return nil, errInvalidVotingChain
+		return nil, errOutOfRangeChain
 	}
 	// Iterate through the headers and create a new snapshot
 	snap := s.copy()
@@ -200,91 +198,125 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
 	for _, header := range headers {
 		// Remove any votes on checkpoint blocks
 		number := header.Number.Uint64()
-		if number%s.config.Epoch == 0 {
-			snap.Votes = nil
-			snap.Tally = make(map[common.Address]Tally)
+		if (number+1)%s.config.Epoch == 0 {
+			// snap.Votes = nil
+			// snap.Tally = make(map[common.Address]Tally)
 		}
+
 		// Delete the oldest signer from the recent list to allow it signing again
-		if limit := uint64(len(snap.Signers)/2 + 1); number >= limit {
-			delete(snap.Recents, number-limit)
+		if number >= s.config.Epoch && number-s.config.Epoch >= 0 {
+			delete(snap.Recents, number-s.config.Epoch)
 		}
+
 		// Resolve the authorization key and check against signers
 		signer, err := ecrecover(header, s.sigcache)
 		if err != nil {
 			return nil, err
 		}
-		if _, ok := snap.Signers[signer]; !ok {
+
+		if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
 			return nil, errUnauthorizedSigner
 		}
-		for _, recent := range snap.Recents {
-			if recent == signer {
-				// return nil, errRecentlySigned
-			}
-		}
-		snap.Recents[number] = signer
 
-		// Header authorized, discard any previous votes from the signer
-		for i, vote := range snap.Votes {
-			if vote.Signer == signer && vote.Address == header.Coinbase {
-				// Uncast the vote from the cached tally
-				snap.uncast(vote.Address, vote.Authorize)
+		//
+		// Check validator
+		//
 
-				// Uncast the vote from the chronological list
-				snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
-				break // only one vote allowed
+		validators := snap.ValidatorSet.Validators
+		// proposer will be the last signer if block is not epoch block
+		proposer := snap.ValidatorSet.GetProposer().Address
+		// if number%s.config.Epoch != 0 {
+		// 	proposer = snap.Recents[number-1]
+		// }
+		proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
+		signerIndex, _ := snap.ValidatorSet.GetByAddress(signer)
+		limit := len(validators) - (len(validators)/2 + 1)
+
+		// temp index
+		tempIndex := signerIndex
+		if proposerIndex != tempIndex && limit > 0 {
+			if tempIndex < proposerIndex {
+				tempIndex = tempIndex + len(validators)
+			}
+
+			if tempIndex-proposerIndex > limit {
+				return nil, errRecentlySigned
 			}
 		}
-		// Tally up the new vote from the signer
-		var authorize bool
-		switch {
-		case bytes.Equal(header.Nonce[:], nonceAuthVote):
-			authorize = true
-		case bytes.Equal(header.Nonce[:], nonceDropVote):
-			authorize = false
-		default:
-			return nil, errInvalidVote
-		}
-		if snap.cast(header.Coinbase, authorize) {
-			snap.Votes = append(snap.Votes, &Vote{
-				Signer:    signer,
-				Block:     number,
-				Address:   header.Coinbase,
-				Authorize: authorize,
-			})
+
+		// add recents
+		snap.Recents[number] = signer
+		fmt.Println("Recent signer", "number", number, "signer", signer.Hex())
+		// change proposer on epoch
+		if number > 0 && (number+1)%s.config.Epoch == 0 {
+			newVals, _ := GetValidators(number, snap.config.ValidatorContract, snap.ethAPI)
+			v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals)
+			v.IncrementProposerPriority(1)
+			snap.ValidatorSet = v
+			fmt.Println("New validator set", "number", number, "proposer", v.Proposer.Address.Hex())
 		}
+		// // Header authorized, discard any previous votes from the signer
+		// for i, vote := range snap.Votes {
+		// 	if vote.Signer == signer && vote.Address == header.Coinbase {
+		// 		// Uncast the vote from the cached tally
+		// 		snap.uncast(vote.Address, vote.Authorize)
+
+		// 		// Uncast the vote from the chronological list
+		// 		snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
+		// 		break // only one vote allowed
+		// 	}
+		// }
+		// Tally up the new vote from the signer
+		// var authorize bool
+		// switch {
+		// case bytes.Equal(header.Nonce[:], nonceAuthVote):
+		// 	authorize = true
+		// case bytes.Equal(header.Nonce[:], nonceDropVote):
+		// 	authorize = false
+		// default:
+		// 	return nil, errInvalidVote
+		// }
+		// if snap.cast(header.Coinbase, authorize) {
+		// 	snap.Votes = append(snap.Votes, &Vote{
+		// 		Signer:    signer,
+		// 		Block:     number,
+		// 		Address:   header.Coinbase,
+		// 		Authorize: authorize,
+		// 	})
+		// }
 		// If the vote passed, update the list of signers
-		if tally := snap.Tally[header.Coinbase]; tally.Votes > len(snap.Signers)/2 {
-			if tally.Authorize {
-				snap.Signers[header.Coinbase] = struct{}{}
-			} else {
-				delete(snap.Signers, header.Coinbase)
-
-				// Signer list shrunk, delete any leftover recent caches
-				if limit := uint64(len(snap.Signers)/2 + 1); number >= limit {
-					delete(snap.Recents, number-limit)
-				}
-				// Discard any previous votes the deauthorized signer cast
-				for i := 0; i < len(snap.Votes); i++ {
-					if snap.Votes[i].Signer == header.Coinbase {
-						// Uncast the vote from the cached tally
-						snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize)
-
-						// Uncast the vote from the chronological list
-						snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
-
-						i--
-					}
-				}
-			}
-			// Discard any previous votes around the just changed account
-			for i := 0; i < len(snap.Votes); i++ {
-				if snap.Votes[i].Address == header.Coinbase {
-					snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
-					i--
-				}
-			}
-			delete(snap.Tally, header.Coinbase)
-		}
+		// if tally := snap.Tally[header.Coinbase]; tally.Votes > len(snap.Signers)/2 {
+		// 	if tally.Authorize {
+		// 		snap.Signers[header.Coinbase] = struct{}{}
+		// 	} else {
+		// 		delete(snap.Signers, header.Coinbase)
+
+		// 		// Signer list shrunk, delete any leftover recent caches
+		// 		if limit := uint64(len(snap.Signers)/2 + 1); number >= limit {
+		// 			delete(snap.Recents, number-limit)
+		// 		}
+		// 		// Discard any previous votes the deauthorized signer cast
+		// 		for i := 0; i < len(snap.Votes); i++ {
+		// 			if snap.Votes[i].Signer == header.Coinbase {
+		// 				// Uncast the vote from the cached tally
+		// 				snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize)
+
+		// 				// Uncast the vote from the chronological list
+		// 				snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
+
+		// 				i--
+		// 			}
+		// 		}
+		// 	}
+		// 	// Discard any previous votes around the just changed account
+		// 	for i := 0; i < len(snap.Votes); i++ {
+		// 		if snap.Votes[i].Address == header.Coinbase {
+		// 			snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
+		// 			i--
+		// 		}
+		// 	}
+		// 	delete(snap.Tally, header.Coinbase)
+		// }
 	}
 	snap.Number += uint64(len(headers))
 	snap.Hash = headers[len(headers)-1].Hash()
@@ -294,19 +326,54 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
 
 // signers retrieves the list of authorized signers in ascending order.
 func (s *Snapshot) signers() []common.Address {
-	sigs := make([]common.Address, 0, len(s.Signers))
-	for sig := range s.Signers {
-		sigs = append(sigs, sig)
+	sigs := make([]common.Address, 0, len(s.ValidatorSet.Validators))
+	for _, sig := range s.ValidatorSet.Validators {
+		sigs = append(sigs, sig.Address)
 	}
-	sort.Sort(signersAscending(sigs))
 	return sigs
 }
 
 // inturn returns if a signer at a given block height is in-turn or not.
-func (s *Snapshot) inturn(number uint64, signer common.Address, producerPeriod uint64) bool {
-	signers, offset := s.signers(), 0
-	for offset < len(signers) && signers[offset] != signer {
-		offset++
+func (s *Snapshot) inturn(number uint64, signer common.Address, epoch uint64) uint64 {
+	// if signer is empty
+	if bytes.Compare(signer.Bytes(), common.Address{}.Bytes()) == 0 {
+		return 1
+	}
+
+	validators := s.ValidatorSet.Validators
+	proposer := s.ValidatorSet.GetProposer().Address
+	totalValidators := len(validators)
+
+	// proposer will be the last signer if block is not epoch block
+	// proposer := snap.ValidatorSet.GetProposer().Address
+	// if number%epoch != 0 {
+	// 	proposer = snap.Recents[number-1]
+	// }
+	proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
+	signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
+
+	// temp index
+	tempIndex := signerIndex
+	if tempIndex < proposerIndex {
+		tempIndex = tempIndex + totalValidators
 	}
-	return ((number / producerPeriod) % uint64(len(signers))) == uint64(offset)
+
+	return uint64(totalValidators - (tempIndex - proposerIndex))
+
+	// signers, offset := s.signers(), 0
+	// for offset < len(signers) && signers[offset] != signer {
+	// 	offset++
+	// }
+	// return ((number / producerPeriod) % uint64(len(signers))) == uint64(offset)
+
+	// // if block is epoch start block, proposer will be inturn signer
+	// if s.Number%epoch == 0 {
+	// 	if bytes.Compare(proposer.Address.Bytes(), signer.Bytes()) == 0 {
+	// 		return true
+	// 	}
+	// 	// if block is not epoch block, last block signer will be inturn
+	// } else if bytes.Compare(lastSigner.Bytes(), signer.Bytes()) == 0 {
+	// 	return false
+	// }
+	// return false
 }
diff --git a/core/blockchain.go b/core/blockchain.go
index 2355f0ea315fd97d07dd1fa3da2521afa452c026..47fb5c705184b390aa2ba1fb0671bfe7611a8158 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -228,7 +228,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
 	// The first thing the node will do is reconstruct the verification data for
 	// the head block (ethash cache or clique voting snapshot). Might as well do
 	// it in advance.
-	bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true)
+	// bc.engine.VerifyHeader(bc, bc.CurrentHeader(), true)
 
 	if frozen, err := bc.db.Ancients(); err == nil && frozen > 0 {
 		var (
diff --git a/eth/backend.go b/eth/backend.go
index 698f519bc77602aac0639d326375a46e1e3e24a3..e4d01c169bc7d79f150f06db8b200e924c2d7c6f 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -183,7 +183,10 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
 			TrieTimeLimit:       config.TrieTimeout,
 		}
 	)
+
 	eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve)
+	eth.engine.VerifyHeader(eth.blockchain, eth.blockchain.CurrentHeader(), true) // TODO think on it
+
 	if err != nil {
 		return nil, err
 	}