github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/consensus/tribe/status.go (about)

     1  package tribe
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/elliptic"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  	"time"
    11  
    12  	"github.com/SmartMeshFoundation/Spectrum/common"
    13  	"github.com/SmartMeshFoundation/Spectrum/core/types"
    14  	"github.com/SmartMeshFoundation/Spectrum/crypto"
    15  	"github.com/SmartMeshFoundation/Spectrum/log"
    16  	"github.com/SmartMeshFoundation/Spectrum/params"
    17  )
    18  
    19  func NewTribeStatus() *TribeStatus {
    20  	ts := &TribeStatus{
    21  		Signers:     make([]*Signer, 0),
    22  		SignerLevel: LevelNone,
    23  	}
    24  	return ts
    25  }
    26  
    27  func (self *TribeStatus) SetTribe(tribe *Tribe) {
    28  	self.tribe = tribe
    29  }
    30  
    31  func (self *TribeStatus) getNodekey() *ecdsa.PrivateKey {
    32  	if self.nodeKey == nil {
    33  		panic(errors.New("GetNodekey but nodekey not ready"))
    34  	}
    35  	return self.nodeKey
    36  }
    37  
    38  func (self *TribeStatus) SetNodeKey(nodeKey *ecdsa.PrivateKey) {
    39  	self.nodeKey = nodeKey
    40  }
    41  
    42  func (self *TribeStatus) GetNodeKey() *ecdsa.PrivateKey {
    43  	return self.nodeKey
    44  }
    45  
    46  func (self *TribeStatus) GetMinerAddress() common.Address {
    47  	if self.nodeKey == nil {
    48  		panic(errors.New("GetMinerAddress but nodekey not ready"))
    49  	}
    50  	pub := self.nodeKey.PublicKey
    51  	add := crypto.PubkeyToAddress(pub)
    52  	return add
    53  }
    54  func (self *TribeStatus) IsLeader(addr common.Address) bool {
    55  	for _, a := range self.Leaders {
    56  		if a == addr {
    57  			return true
    58  		}
    59  	}
    60  	return false
    61  }
    62  func (self *TribeStatus) GetMinerAddressByChan(rtn chan common.Address) {
    63  	go func() {
    64  		for {
    65  			if self.nodeKey != nil && self.tribe.isInit {
    66  				break
    67  			}
    68  			<-time.After(time.Second)
    69  		}
    70  		pub := self.nodeKey.PublicKey
    71  		rtn <- crypto.PubkeyToAddress(pub)
    72  	}()
    73  }
    74  
    75  //func (self *TribeStatus) GetSignersFromChiefByHash(hash common.Hash, number *big.Int) ([]*Signer, error) {
    76  //	sc, ok := self.signersCache.Get(hash)
    77  //	if ok {
    78  //		return sc.([]*Signer), nil
    79  //	}
    80  //	rtn := params.SendToMsgBoxWithHash("GetStatus", hash, number)
    81  //	r := <-rtn
    82  //	if !r.Success {
    83  //		return nil, r.Entity.(error)
    84  //	}
    85  //	cs := r.Entity.(params.ChiefStatus)
    86  //	signers := cs.SignerList
    87  //	scores := cs.ScoreList
    88  //	sl := make([]*Signer, 0, len(signers))
    89  //	for i, signer := range signers {
    90  //		score := scores[i]
    91  //		sl = append(sl, &Signer{signer, score.Int64()})
    92  //	}
    93  //	self.signersCache.Add(hash, sl)
    94  //	return sl, nil
    95  //}
    96  
    97  // 在每次出块prepare的时候去获取一次,同时在同步区块的时候去获取一次,同步区块获取的是最新块的父区块信息,出块时获取的是当前本地最新块的状态信息
    98  func (self *TribeStatus) LoadStatusFromChief(hash common.Hash, number *big.Int) error {
    99  	//log.Info(fmt.Sprintf("LoadSignersFromChief hash=%s,number=%s", hash.String(), number))
   100  	cs, err := params.TribeGetStatus(number, hash)
   101  	if err != nil {
   102  		log.Warn("TribeGetStatusError", "err", err, "num", number, "hash", hash.Hex())
   103  		return err
   104  	}
   105  	signers := cs.SignerList
   106  	scores := cs.ScoreList
   107  	sl := make([]*Signer, 0, len(signers))
   108  	for i, signer := range signers {
   109  		score := scores[i]
   110  		sl = append(sl, &Signer{signer, score.Int64()})
   111  	}
   112  	self.LeaderLimit = cs.LeaderLimit
   113  	self.Leaders = cs.LeaderList
   114  	if len(self.Leaders) == 0 && params.IsSIP100Block(number) {
   115  		panic(fmt.Sprintf("LoadSignersFromChief err ,hash=%s,number=%s,cs=%#v", hash.String(), number, cs))
   116  	}
   117  	self.Number = cs.Number.Int64()
   118  	self.blackList = cs.BlackList
   119  	self.loadSigners(sl)
   120  	self.Epoch, self.SignerLimit = cs.Epoch, cs.SignerLimit
   121  	go self.resetSignersLevel(hash, number)
   122  	return nil
   123  }
   124  
   125  func (self *TribeStatus) resetSignersLevel(hash common.Hash, number *big.Int) {
   126  	m := self.GetMinerAddress()
   127  	for _, s := range self.Signers {
   128  		if s.Address == m {
   129  			self.SignerLevel = LevelSigner
   130  			return
   131  		}
   132  	}
   133  	for _, s := range self.blackList {
   134  		if s == m {
   135  			self.SignerLevel = LevelSinner
   136  			return
   137  		}
   138  	}
   139  
   140  	for _, s := range self.Leaders {
   141  		if s == m {
   142  			self.SignerLevel = LevelSigner
   143  			return
   144  		}
   145  	}
   146  
   147  	ci := params.GetChiefInfo(number)
   148  	switch ci.Version {
   149  	case "0.0.6":
   150  		// if filterVolunteer return 1 then is volunteer
   151  		rtn := params.SendToMsgBoxForFilterVolunteer(hash, number, m)
   152  		r := <-rtn
   153  		if r.Success {
   154  			if fr := r.Entity.(*big.Int); fr != nil && fr.Int64() == 0 {
   155  				self.SignerLevel = LevelVolunteer
   156  				return
   157  			}
   158  		}
   159  	}
   160  	// default none
   161  	self.SignerLevel = LevelNone
   162  }
   163  
   164  //每一块都会调用
   165  func (self *TribeStatus) loadSigners(sl []*Signer) {
   166  	self.Signers = append(self.Signers[:0], sl...)
   167  }
   168  
   169  //InTurnForCalcDiffcultyChief100 计算规则参考inTurnForCalcChief100
   170  func (self *TribeStatus) InTurnForCalcDiffcultyChief100(signer common.Address, parent *types.Header) *big.Int {
   171  	return self.inTurnForCalcDifficultyChief100(parent.Number.Int64()+1, parent.Hash(), signer)
   172  }
   173  
   174  /*
   175  inTurnForCalcDifficultyChief100 计算如果当前出块节点是signer的话,它对应的难度是多少.
   176  signers:[0,...,16] 0号对应的是常委会节点,1-16对应的是普通出块节点
   177  场景1:
   178  1. 当前应该出块节点应该是3,如果signer是3,那么难度就是6.
   179  2. 如果singers[0]对应的是常委2, 这时候常委2出块,难度是5,常委3出块难度是4,...,常委1出块难度则是1
   180  场景2:当前出块节点应该是singers[0],也就是某个常委会节点
   181  1. 如果signers[0] 出块,那么难度就是6
   182  2. 假设signers[0]是常委2,那么常委3替他出块难度是5,常委4出块就是4,...常委1出块难度则是2
   183  
   184  这里的number参数主要是选定合约版本,而parentHash则是用来选择读取哪个block时候的合约状态
   185  */
   186  func (self *TribeStatus) inTurnForCalcDifficultyChief100(number int64, parentHash common.Hash, signer common.Address) *big.Int {
   187  
   188  	signers := self.Signers
   189  	sl := len(signers)
   190  
   191  	defer func() {
   192  		log.Debug(fmt.Sprintf("inTurnForCalcDifficultyChief100  numer=%d,parentHash=%s signer=%s  ", number, parentHash.String(), signer.String()),
   193  			"signers", signers)
   194  	}()
   195  	//	log.Info(fmt.Sprintf("singers=%v,signer=%s,leaders=%v,number=%d,parentHash=%s", signers, signer.String(), self.Leaders, number, parentHash.String()))
   196  	if idx, _, err := self.fetchOnSigners(signer, signers); err == nil {
   197  		// main
   198  		if sl > 0 && number%int64(sl) == idx.Int64() {
   199  			return big.NewInt(diff)
   200  		}
   201  		// second
   202  		if idx.Int64() == 0 {
   203  			return big.NewInt(diff - 1)
   204  		}
   205  
   206  	} else if sl > 0 {
   207  		if leaders, err := leaderSort(signers[0].Address, self.Leaders); err == nil {
   208  			for i, leader := range leaders {
   209  				if signer == leader && number%int64(sl) == 0 {
   210  					return big.NewInt(diff - int64(i+1))
   211  				} else if signer == leader {
   212  					return big.NewInt(diff - int64(i+2))
   213  				}
   214  			}
   215  		}
   216  	}
   217  	return diffNoTurn
   218  }
   219  
   220  //InTurnForVerifyDifficultyChief100: 计算规则参考inTurnForCalcChief100
   221  func (self *TribeStatus) InTurnForVerifyDifficultyChief100(number int64, parentHash common.Hash, signer common.Address) *big.Int {
   222  	return self.inTurnForCalcDifficultyChief100(number, parentHash, signer)
   223  }
   224  
   225  /*
   226  假设list=[1,2,3,4,5]
   227  first=3,那么返回[4,5,1,2]
   228  如果first=2,返回[3,4,5,1]
   229  如果first=5,返回[1,2,3,4]
   230  不允许返回错误,是因为考虑到运行过程中leader可能会被删除,从而导致找不到leader
   231  */
   232  func leaderSort(first common.Address, list []common.Address) ([]common.Address, error) {
   233  	for i, o := range list {
   234  		if first == o {
   235  			return append(list[i+1:], list[:i]...), nil
   236  		}
   237  	}
   238  
   239  	return list, nil
   240  }
   241  
   242  //InTurnForCalcDifficulty 在0.6版本yiqian 计算难度
   243  func (self *TribeStatus) InTurnForCalcDifficulty(signer common.Address, parent *types.Header) *big.Int {
   244  	number := parent.Number.Int64() + 1
   245  	signers := self.Signers
   246  	if idx, _, err := self.fetchOnSigners(signer, signers); err == nil {
   247  		sl := len(signers)
   248  		if params.IsSIP002Block(big.NewInt(number)) {
   249  			if sl > 0 && number%int64(sl) == idx.Int64() {
   250  				return diffInTurnMain
   251  			} else if sl > 0 && (number+1)%int64(sl) == idx.Int64() {
   252  				return diffInTurn
   253  			}
   254  		} else {
   255  			if sl > 0 && number%int64(sl) == idx.Int64() {
   256  				return diffInTurn
   257  			}
   258  		}
   259  	}
   260  
   261  	return diffNoTurn
   262  }
   263  
   264  //0.6版本之前校验难度
   265  func (self *TribeStatus) InTurnForVerifyDiffculty(number int64, parentHash common.Hash, signer common.Address) *big.Int {
   266  	if ci := params.GetChiefInfo(big.NewInt(number)); ci != nil {
   267  		switch ci.Version {
   268  		case "1.0.0":
   269  			//TODO max value is a var ???
   270  			return self.InTurnForVerifyDifficultyChief100(number, parentHash, signer)
   271  		}
   272  	}
   273  
   274  	var signers []*Signer
   275  	if number > 3 {
   276  		signers = self.Signers
   277  	} else {
   278  		return diffInTurn
   279  	}
   280  	if idx, _, err := self.fetchOnSigners(signer, signers); err == nil {
   281  		sl := len(signers)
   282  		if params.IsSIP002Block(big.NewInt(number)) {
   283  			if sl > 0 && number%int64(sl) == idx.Int64() {
   284  				return diffInTurnMain
   285  			} else if sl > 0 && (number+1)%int64(sl) == idx.Int64() {
   286  				return diffInTurn
   287  			}
   288  		} else {
   289  			if sl > 0 && number%int64(sl) == idx.Int64() {
   290  				return diffInTurn
   291  			}
   292  		}
   293  	}
   294  	return diffNoTurn
   295  }
   296  
   297  func (self *TribeStatus) genesisSigner(header *types.Header) (common.Address, error) {
   298  	extraVanity := extraVanityFn(header.Number)
   299  	signer := common.Address{}
   300  	copy(signer[:], header.Extra[extraVanity:])
   301  	self.loadSigners([]*Signer{{signer, 3}})
   302  	return signer, nil
   303  }
   304  
   305  //address对应的signer以及其在signers中的下标
   306  func (self *TribeStatus) fetchOnSigners(address common.Address, signers []*Signer) (*big.Int, *Signer, error) {
   307  	if signers == nil {
   308  		signers = self.Signers
   309  	}
   310  	if l := len(signers); l > 0 {
   311  		for i := 0; i < l; i++ {
   312  			if s := signers[i]; s.Address == address {
   313  				return big.NewInt(int64(i)), s, nil
   314  			}
   315  		}
   316  	}
   317  	return nil, nil, errors.New("not_found")
   318  }
   319  
   320  func verifyVrfNum(parent, header *types.Header) (err error) {
   321  	var (
   322  		np  = header.Extra[:extraVanityFn(header.Number)]
   323  		sig = header.Extra[len(header.Extra)-extraSeal:]
   324  		msg = append(parent.Number.Bytes(), parent.Extra[:32]...)
   325  	)
   326  	pubbuf, err := ecrecoverPubkey(header, sig)
   327  	if err != nil {
   328  		//panic(err) //这地方不能panic,否则一个节点出一个恶意的块,所以的节点就全崩了.
   329  		return err
   330  	}
   331  	x, y := elliptic.Unmarshal(crypto.S256(), pubbuf)
   332  	pubkey := ecdsa.PublicKey{Curve: crypto.S256(), X: x, Y: y}
   333  	err = crypto.SimpleVRFVerify(&pubkey, msg, np)
   334  	log.Debug("[verifyVrfNum]", "err", err, "num", header.Number, "vrfn", new(big.Int).SetBytes(np[:32]), "parent", header.ParentHash.Bytes())
   335  	return
   336  }
   337  
   338  /*
   339  validateSigner:
   340  1. 验证出块时间符合规则,具体规则见GetPeriodChief100描述
   341  2.
   342  */
   343  func (self *TribeStatus) validateSigner(parentHeader, header *types.Header, signer common.Address) bool {
   344  	var (
   345  		err     error
   346  		signers = self.Signers
   347  		number  = header.Number.Int64()
   348  	)
   349  	//if number > 1 && self.Number != parentNumber {
   350  	if number <= CHIEF_NUMBER {
   351  		return true
   352  	}
   353  
   354  	if params.IsSIP002Block(header.Number) {
   355  		// second time of verification block time
   356  		period := self.tribe.GetPeriod(header, signers)
   357  		pt := parentHeader.Time.Uint64()
   358  		if pt+period > header.Time.Uint64() {
   359  			log.Error("[ValidateSigner] second time verification block time error", "num", header.Number, "pt", pt, "period", period, ", pt+period=", pt+period, " , ht=", header.Time.Uint64())
   360  			log.Error("[ValidateSigner] second time verification block time error", "err", ErrInvalidTimestampSIP002)
   361  			return false
   362  		}
   363  	}
   364  
   365  	if params.IsSIP100Block(header.Number) && header.Coinbase == common.HexToAddress("0x") {
   366  		log.Error("error_signer", "num", header.Number.String(), "miner", header.Coinbase.Hex(), "signer", signer.Hex())
   367  		return false
   368  	}
   369  
   370  	idx, _, err := self.fetchOnSigners(signer, signers)
   371  	if params.IsSIP100Block(header.Number) {
   372  		if err == nil {
   373  			// 轮到谁出就谁出的块
   374  			idx_m := number % int64(len(signers))
   375  			if idx_m == idx.Int64() {
   376  				return true
   377  			}
   378  			// 其他只能有常委会节点替代
   379  			if idx.Int64() == 0 {
   380  				return true
   381  			}
   382  		} else {
   383  			// other leader
   384  			for _, leader := range self.Leaders {
   385  				if signer == leader { //有没有测试过多个常委会节点同时出块的情况呢?
   386  					return true
   387  				}
   388  			}
   389  		}
   390  	} else if err == nil {
   391  		return true
   392  	}
   393  	return false
   394  }
   395  
   396  /*
   397  VerifySignerBalance: 在chief1.0之前直接通过账号余额来判断是否具有出块资格,chief1.0之后只能通过抵押到poc合约中才具有资格.
   398  */
   399  //func (self *TribeStatus) VerifySignerBalance(state *state.StateDB, addr common.Address, header *types.Header) error {
   400  //	// SIP100 skip this verify
   401  //	if params.IsSIP100Block(header.Number) {
   402  //		return nil
   403  //	}
   404  //	var (
   405  //		pnum, num *big.Int
   406  //	)
   407  //	if addr == common.HexToAddress("0x") {
   408  //		if _addr, err := ecrecover(header, self.tribe); err == nil {
   409  //			addr = _addr
   410  //		} else {
   411  //			return err
   412  //		}
   413  //	}
   414  //	if header != nil {
   415  //		num = header.Number
   416  //		pnum = new(big.Int).Sub(num, big.NewInt(1))
   417  //	} else {
   418  //		return errors.New("params of header can not be null")
   419  //	}
   420  //	// skip when v in meshbox.sol
   421  //	if params.IsReadyMeshbox(pnum) && params.MeshboxExistAddress(addr) {
   422  //		return nil
   423  //	}
   424  //
   425  //	return nil
   426  //
   427  //}
   428  
   429  // every block
   430  // sync download or mine
   431  // check chief tx
   432  func (self *TribeStatus) ValidateBlock(parent, block *types.Block, validateSigner bool) error {
   433  	if block.Number().Int64() <= CHIEF_NUMBER {
   434  		return nil
   435  	}
   436  	var err error
   437  	if validateSigner {
   438  		//The miner updates the chife contract information when prepare, and the follower  updates the chief contract information whenValidateBlock.
   439  		err = self.LoadStatusFromChief(parent.Hash(), block.Number())
   440  		if err != nil {
   441  			log.Error(fmt.Sprintf("[ValidateBlock] LoadSignersFromChief ,parent=%s,current=%s,currentNumber=%s", parent.Hash().String(), block.Hash().String(), block.Number()))
   442  			return err
   443  		}
   444  	}
   445  
   446  	header := block.Header()
   447  	number := header.Number.Int64()
   448  
   449  	//number := block.Number().Int64()
   450  	// add by liangc : seal call this func must skip validate signer 因为这时候签名都还没准备好
   451  	if validateSigner {
   452  		signer, err := ecrecover(header, self.tribe)
   453  		// verify signer
   454  		if err != nil {
   455  			return err
   456  		}
   457  		// verify difficulty 就算是
   458  		if !params.IsBeforeChief100block(header.Number) {
   459  			difficulty := self.InTurnForVerifyDiffculty(number, header.ParentHash, signer)
   460  			if difficulty.Cmp(header.Difficulty) != 0 {
   461  				log.Error("** ValidateBlock ERROR **", "head.diff", header.Difficulty.String(), "target.diff", difficulty.String(), "err", errInvalidDifficulty, "validateFromSeal", !validateSigner)
   462  				return errInvalidDifficulty
   463  			}
   464  		}
   465  		// verify vrf num
   466  		if params.IsSIP100Block(header.Number) {
   467  			err = verifyVrfNum(parent.Header(), header)
   468  			if err != nil {
   469  				log.Error("vrf_num_fail", "num", number, "err", err)
   470  				return err
   471  			}
   472  		}
   473  		if !self.validateSigner(parent.Header(), header, signer) {
   474  			return errUnauthorized
   475  		}
   476  	}
   477  	// check first tx , must be chief.tx , and onely one chief.tx in tx list
   478  	if block != nil && block.Transactions().Len() == 0 {
   479  		return ErrTribeNotAllowEmptyTxList
   480  	}
   481  
   482  	var total = 0
   483  	for i, tx := range block.Transactions() {
   484  		from := types.GetFromByTx(tx)
   485  		/*
   486  			must verify tx.from ==signer:
   487  			otherwise:
   488  			if miner A minging the block#16,then A can make chief.update tx fail,
   489  			so signerList will never update, A will make sure he can mine block for every round.
   490  		*/
   491  		if tx.To() != nil && params.IsChiefAddressOnBlock(block.Number(), *tx.To()) && params.IsChiefUpdate(tx.Data()) {
   492  			if i != 0 {
   493  				return ErrTribeChiefTxMustAtPositionZero
   494  			}
   495  			if validateSigner {
   496  				signer, err := ecrecover(header, self.tribe)
   497  				// verify signer
   498  				if err != nil {
   499  					return err
   500  				}
   501  
   502  				if from == nil || *from != signer {
   503  					return ErrTribeChiefTxSignerAndBlockSignerNotMatch
   504  				}
   505  
   506  				if params.IsSIP100Block(header.Number) {
   507  					// TODO SIP100 check volunteer by vrfnp
   508  					volunteerHex := common.Bytes2Hex(tx.Data()[4:])
   509  					volunteer := common.HexToAddress(volunteerHex)
   510  					vrfn := header.Extra[:32]
   511  					if !params.VerifyMiner(header.ParentHash, volunteer, vrfn) {
   512  						return errors.New("verify_volunteer_fail")
   513  					}
   514  				}
   515  			}
   516  			total++
   517  		}
   518  	}
   519  	if total == 0 {
   520  		return ErrTribeMustContainChiefTx
   521  	}
   522  
   523  	log.Debug("ValidateBlockp-->", "num", block.NumberU64(), "check_signer", validateSigner)
   524  	return nil
   525  }
   526  
   527  func (self *TribeStatus) String() string {
   528  	if b, e := json.Marshal(self); e != nil {
   529  		return "error: " + e.Error()
   530  	} else {
   531  		return "status: " + string(b)
   532  	}
   533  }