github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/poa/clique.go (about)

     1  package poa
     2  
     3  import (
     4  	//"bytes"
     5  	"crypto"
     6  	"errors"
     7  	"fmt"
     8  	"math/big"
     9  	//"math/rand"
    10  	"sync"
    11  	"time"
    12  
    13  	lru "github.com/hashicorp/golang-lru"
    14  	"github.com/sixexorg/magnetic-ring/account"
    15  	"github.com/sixexorg/magnetic-ring/common"
    16  	"github.com/sixexorg/magnetic-ring/config"
    17  	"github.com/sixexorg/magnetic-ring/core/orgchain/types"
    18  	mycrypte "github.com/sixexorg/magnetic-ring/crypto"
    19  	"github.com/sixexorg/magnetic-ring/log"
    20  	"github.com/sixexorg/magnetic-ring/orgcontainer"
    21  	"github.com/sixexorg/magnetic-ring/rlp"
    22  	"github.com/sixexorg/magnetic-ring/store/orgchain/storages"
    23  	"github.com/sixexorg/magnetic-ring/store/storelaw"
    24  	_ "golang.org/x/crypto/sha3"
    25  )
    26  
    27  const (
    28  	inmemorySnapshots  = 128  // Number of recent vote snapshots to keep in memory
    29  	inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
    30  
    31  	wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
    32  )
    33  
    34  var (
    35  	epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes
    36  	diffInTurn  = big.NewInt(2) // Block difficulty for in-turn signatures
    37  	diffNoTurn  = big.NewInt(1) // Block difficulty for out-of-turn signatures
    38  )
    39  
    40  var (
    41  	errUnknownBlock                 = errors.New("unknown block")
    42  	errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero")
    43  	errInvalidVote                  = errors.New("vote nonce not 0x00..0 or 0xff..f")
    44  	errInvalidCheckpointVote        = errors.New("vote nonce in checkpoint block non-zero")
    45  	errMissingVanity                = errors.New("extra-data 32 byte vanity prefix missing")
    46  	errMissingSignature             = errors.New("extra-data 65 byte suffix signature missing")
    47  	errExtraSigners                 = errors.New("non-checkpoint block contains extra signer list")
    48  	errInvalidCheckpointSigners     = errors.New("invalid signer list on checkpoint block")
    49  	errInvalidMixDigest             = errors.New("non-zero mix digest")
    50  	errInvalidUncleHash             = errors.New("non empty uncle hash")
    51  	errInvalidDifficulty            = errors.New("invalid difficulty")
    52  	ErrInvalidTimestamp             = errors.New("invalid timestamp")
    53  	errInvalidVotingChain           = errors.New("invalid voting chain")
    54  	errUnauthorized                 = errors.New("unauthorized")
    55  	errWaitTransactions             = errors.New("waiting for transactions")
    56  )
    57  
    58  func sigHash(header *types.Header) (hash common.Hash) {
    59  	sha3256 := crypto.SHA3_256.New()
    60  	rlp.Encode(sha3256, []interface{}{
    61  		header.PrevBlockHash,
    62  		header.Coinbase,
    63  		header.BlockRoot,
    64  		header.TxRoot,
    65  		header.ReceiptsRoot,
    66  		header.Difficulty,
    67  		header.Height,
    68  		uint64(header.Timestamp),
    69  		header.Extra, // Yes, this will panic if extra is too short
    70  	})
    71  	sha3256.Sum(hash[:0])
    72  	return hash
    73  }
    74  
    75  func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
    76  	hash := header.Hash()
    77  	if address, known := sigcache.Get(hash); known {
    78  		return address.(common.Address), nil
    79  	}
    80  	signature := header.Extra
    81  
    82  	pubkey, _ := mycrypte.UnmarshalPubkey([]byte(header.Coinbase[:]))
    83  	if fg, err := pubkey.Verify(hash[:], signature); !fg && err != nil {
    84  		return common.Address{}, err
    85  	}
    86  
    87  	sigcache.Add(hash, header.Coinbase)
    88  	return header.Coinbase, nil
    89  }
    90  
    91  type Clique struct {
    92  	config *config.CliqueConfig
    93  	ledger *storages.LedgerStoreImp
    94  
    95  	recents    *lru.ARCCache
    96  	signatures *lru.ARCCache
    97  
    98  	account account.Account
    99  	signer  common.Address
   100  	//txpool      *common2.SubTxPool
   101  	orgContent *orgcontainer.Container
   102  	lock       sync.RWMutex
   103  }
   104  
   105  func New(config *config.CliqueConfig, account account.Account, orgCtx *orgcontainer.Container, ledger *storages.LedgerStoreImp) *Clique {
   106  	conf := *config
   107  	if conf.Epoch == 0 {
   108  		conf.Epoch = epochLength
   109  	}
   110  	recents, _ := lru.NewARC(inmemorySnapshots)
   111  	signatures, _ := lru.NewARC(inmemorySignatures)
   112  
   113  	return &Clique{
   114  		config:     &conf,
   115  		account:    account,
   116  		recents:    recents,
   117  		signatures: signatures,
   118  		//txpool:     txpool,
   119  		orgContent: orgCtx,
   120  		ledger:     ledger,
   121  	}
   122  }
   123  
   124  func (c *Clique) Author(header *types.Header) (common.Address, error) {
   125  	return ecrecover(header, c.signatures)
   126  }
   127  
   128  func (c *Clique) VerifyHeader(header *types.Header, seal bool) error {
   129  	return c.verifyHeader(header)
   130  }
   131  
   132  func (c *Clique) verifyHeader(header *types.Header) error {
   133  	number := header.Height
   134  
   135  	if header.Timestamp > uint64(time.Now().Unix()) {
   136  		return ErrFutureBlock
   137  	}
   138  
   139  	checkpoint := (number % c.config.Epoch) == 0
   140  	if checkpoint && header.Coinbase != (common.Address{}) {
   141  		return errInvalidCheckpointBeneficiary
   142  	}
   143  
   144  	if number > 0 {
   145  		if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) {
   146  			return errInvalidDifficulty
   147  		}
   148  	}
   149  
   150  	return c.verifySeal(header)
   151  }
   152  
   153  func (c *Clique) snapshot(number uint64, hash common.Hash) (*Snapshot, error) {
   154  	var (
   155  		headers []*types.Header
   156  		snap    *Snapshot
   157  	)
   158  	for snap == nil {
   159  		// If an in-memory snapshot was found, use that
   160  		if s, ok := c.recents.Get(hash); ok {
   161  			snap = s.(*Snapshot)
   162  			break
   163  		}
   164  
   165  		if number == 1 {
   166  			genesis, _ := c.ledger.GetBlockByHeight(1)
   167  			//if err := c.VerifyHeader(genesis.Header, false); err != nil {
   168  			//	return nil, err
   169  			//}
   170  			var signers []common.Address
   171  			signers = append(signers, c.account.Address())
   172  			snap = newSnapshot(c.config, c.signatures, 1, genesis.Hash(), signers)
   173  			log.Trace("Stored genesis voting snapshot to disk")
   174  			break
   175  		}
   176  
   177  		var header *types.Header
   178  		blk, _ := c.ledger.GetBlockByHeight(number)
   179  		//fmt.Println("øøøøøøøøøøøøøø", blk.Header.Coinbase.ToString(), blk.Header.Height)
   180  		header = blk.Header
   181  		if header == nil {
   182  			return nil, ErrUnknownAncestor
   183  		}
   184  		headers = append(headers, header)
   185  		number, hash = number-1, header.PrevBlockHash
   186  	}
   187  
   188  	snap, err := snap.apply(headers)
   189  	if err != nil {
   190  		return nil, err
   191  	}
   192  	c.recents.Add(snap.Hash, snap)
   193  
   194  	return snap, err
   195  }
   196  
   197  func (c *Clique) VerifySeal(header *types.Header) error {
   198  	return c.verifySeal(header)
   199  }
   200  
   201  func (c *Clique) verifySeal(header *types.Header) error {
   202  	// Verifying the genesis block is not supported
   203  	number := header.Height
   204  	if number == 0 {
   205  		return errUnknownBlock
   206  	}
   207  	// Retrieve the snapshot needed to verify this header and cache it
   208  	snap, err := c.snapshot(number-1, header.PrevBlockHash)
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	// Resolve the authorization key and check against signers
   214  	//signer, err := ecrecover(header, c.signatures)
   215  	//if err != nil {
   216  	//	return err
   217  	//}
   218  	signer := header.Coinbase
   219  	if _, ok := snap.Signers[signer]; !ok {
   220  		return errUnauthorized
   221  	}
   222  	for seen, recent := range snap.Recents {
   223  		if recent == signer {
   224  			// Signer is among recents, only fail if the current block doesn't shift it out
   225  			if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit {
   226  				return errUnauthorized
   227  			}
   228  		}
   229  	}
   230  	// Ensure that the difficulty corresponds to the turn-ness of the signer
   231  	inturn := snap.inturn(header.Height, signer)
   232  	if inturn && header.Difficulty.Cmp(diffInTurn) != 0 {
   233  		return errInvalidDifficulty
   234  	}
   235  	if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 {
   236  		return errInvalidDifficulty
   237  	}
   238  	return nil
   239  }
   240  
   241  func (c *Clique) Prepare(header *types.Header) error {
   242  	//header.Coinbase = common.Address{}
   243  	number := header.Height
   244  
   245  	// Assemble the voting snapshot to check which votes make sense
   246  	snap, err := c.snapshot(number-1, header.PrevBlockHash)
   247  	if err != nil {
   248  		return err
   249  	}
   250  	// Set the correct difficulty
   251  	header.Difficulty = diffNoTurn
   252  	if snap.inturn(header.Height, c.signer) {
   253  		header.Difficulty = diffInTurn
   254  	}
   255  	//parent, _ := c.ledger.GetBlockByHeight(number - 1)
   256  	//if parent == nil {
   257  	//	return ErrUnknownAncestor
   258  	//}
   259  	//header.Timestamp = uint64(time.Unix(int64(header.Timestamp), 0).Add(time.Millisecond *500).Unix())
   260  	//timeNow := uint64(time.Now().Unix())
   261  	//if header.Timestamp < timeNow {
   262  	//	header.Timestamp = timeNow
   263  	//}
   264  	//if time.Now().After(t1) {
   265  	//	header.Timestamp = uint64(time.Now().Unix())
   266  	//}
   267  	//fmt.Println("++++++++++++++++++++++++++++++++++++",// t.Format("15:04:05.000"), "t1:", t1.Format("15:04:05.000"),
   268  	//	"height:", header.Height, "timestamp:", time.Unix(0, int64(header.Timestamp)).Format("15:04:05.000"))
   269  	return nil
   270  }
   271  
   272  func (c *Clique) Finalize(blkInfo *storelaw.OrgBlockInfo) (*types.Block, error) {
   273  	// save all
   274  
   275  	//txpool := common2.SubTxPool{}
   276  	//
   277  	////block := txpool.GenerateBlock(common.Address{},2,true)
   278  	//blk,_,acctstate,_ := txpool.Execute(common.Address{})
   279  
   280  	//if err := c.ledger.SaveAll(blkInfo); err != nil{
   281  	//
   282  	//}
   283  
   284  	return blkInfo.Block, nil
   285  }
   286  
   287  func (c *Clique) Seal(block *types.Block, stop <-chan struct{}) (*types.Block, error) {
   288  	header := block.Header
   289  	number := header.Height
   290  	if number == 0 {
   291  		return nil, errUnknownBlock
   292  	}
   293  
   294  	if c.config.Period == 0 || len(block.Transactions) == 0 { //if c.config.Period == 0 && len(block.Transactions) == 0 {
   295  		return nil, errWaitTransactions
   296  	}
   297  
   298  	c.lock.RLock()
   299  	defer c.lock.RUnlock()
   300  
   301  	snap, err := c.snapshot(number-1, header.PrevBlockHash)
   302  	if err != nil {
   303  		return nil, err
   304  	}
   305  
   306  	if _, authorized := snap.Signers[c.account.Address()]; !authorized {
   307  		return nil, errUnauthorized
   308  	}
   309  	for seen, recent := range snap.Recents {
   310  		if recent == c.account.Address() {
   311  			if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit {
   312  				log.Info("Signed recently, must wait for others")
   313  				<-stop
   314  				return nil, nil
   315  			}
   316  		}
   317  	}
   318  	delay := time.Unix(0, int64(header.Timestamp)).Sub(time.Now())
   319  	//if header.Difficulty.Cmp(diffNoTurn) == 0 {
   320  	//	wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime
   321  	//	delay += time.Duration(rand.Int63n(int64(wiggle)))
   322  	//
   323  	//	log.Trace("Out-of-turn signing requested", "wiggle", wiggle)
   324  	//}
   325  	log.Info("Waiting for slot to sign and propagate", "delay", delay)
   326  	select {
   327  	case <-stop:
   328  		return nil, nil
   329  	case <-time.After(delay):
   330  	}
   331  	//time.Sleep(time.Duration(rand.Int63n(int64(10))))
   332  	aa := sigHash(header)
   333  	sighash, err := c.account.Sign(aa[:])
   334  	if err != nil {
   335  		fmt.Println(">>>sigFn err", err, time.Now().String())
   336  		return nil, err
   337  	}
   338  	copy(header.Extra, sighash)
   339  	return block, nil
   340  }