github.com/turingchain2020/turingchain@v1.1.21/system/consensus/solo/solo.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package solo solo共识挖矿
     6  package solo
     7  
     8  import (
     9  	"time"
    10  
    11  	log "github.com/turingchain2020/turingchain/common/log/log15"
    12  	"github.com/turingchain2020/turingchain/common/merkle"
    13  	"github.com/turingchain2020/turingchain/queue"
    14  	drivers "github.com/turingchain2020/turingchain/system/consensus"
    15  	cty "github.com/turingchain2020/turingchain/system/dapp/coins/types"
    16  	"github.com/turingchain2020/turingchain/types"
    17  )
    18  
    19  var slog = log.New("module", "solo")
    20  
    21  //Client 客户端
    22  type Client struct {
    23  	*drivers.BaseClient
    24  	subcfg    *subConfig
    25  	sleepTime time.Duration
    26  }
    27  
    28  func init() {
    29  	drivers.Reg("solo", New)
    30  	drivers.QueryData.Register("solo", &Client{})
    31  }
    32  
    33  type subConfig struct {
    34  	Genesis          string `json:"genesis"`
    35  	GenesisBlockTime int64  `json:"genesisBlockTime"`
    36  	WaitTxMs         int64  `json:"waitTxMs"`
    37  	BenchMode        bool   `json:"benchMode"`
    38  }
    39  
    40  //New new
    41  func New(cfg *types.Consensus, sub []byte) queue.Module {
    42  	c := drivers.NewBaseClient(cfg)
    43  	var subcfg subConfig
    44  	if sub != nil {
    45  		types.MustDecode(sub, &subcfg)
    46  	}
    47  	if subcfg.WaitTxMs == 0 {
    48  		subcfg.WaitTxMs = 1000
    49  	}
    50  	if subcfg.Genesis == "" {
    51  		subcfg.Genesis = cfg.Genesis
    52  	}
    53  	if subcfg.GenesisBlockTime == 0 {
    54  		subcfg.GenesisBlockTime = cfg.GenesisBlockTime
    55  	}
    56  	solo := &Client{c, &subcfg, time.Duration(subcfg.WaitTxMs) * time.Millisecond}
    57  	c.SetChild(solo)
    58  	return solo
    59  }
    60  
    61  //Close close
    62  func (client *Client) Close() {
    63  	slog.Info("consensus solo closed")
    64  }
    65  
    66  //GetGenesisBlockTime 获取创世区块时间
    67  func (client *Client) GetGenesisBlockTime() int64 {
    68  	return client.subcfg.GenesisBlockTime
    69  }
    70  
    71  //CreateGenesisTx 创建创世交易
    72  func (client *Client) CreateGenesisTx() (ret []*types.Transaction) {
    73  	var tx types.Transaction
    74  	tx.Execer = []byte("coins")
    75  	tx.To = client.subcfg.Genesis
    76  	//gen payload
    77  	g := &cty.CoinsAction_Genesis{}
    78  	g.Genesis = &types.AssetsGenesis{}
    79  	g.Genesis.Amount = 1e8 * types.Coin
    80  	tx.Payload = types.Encode(&cty.CoinsAction{Value: g, Ty: cty.CoinsActionGenesis})
    81  	ret = append(ret, &tx)
    82  	return
    83  }
    84  
    85  //ProcEvent false
    86  func (client *Client) ProcEvent(msg *queue.Message) bool {
    87  	return false
    88  }
    89  
    90  //CheckBlock solo没有交易时返回错误
    91  func (client *Client) CheckBlock(parent *types.Block, current *types.BlockDetail) error {
    92  	if len(current.Block.Txs) == 0 {
    93  		return types.ErrEmptyTx
    94  	}
    95  	return nil
    96  }
    97  
    98  //CreateBlock 创建区块
    99  func (client *Client) CreateBlock() {
   100  	issleep := true
   101  	types.AssertConfig(client.GetAPI())
   102  	cfg := client.GetAPI().GetConfig()
   103  	beg := types.Now()
   104  	for {
   105  
   106  		if client.IsClosed() {
   107  			break
   108  		}
   109  		if !client.IsMining() || !client.IsCaughtUp() {
   110  			time.Sleep(client.sleepTime)
   111  			continue
   112  		}
   113  		if issleep {
   114  			time.Sleep(client.sleepTime)
   115  		}
   116  		lastBlock := client.GetCurrentBlock()
   117  		maxTxNum := int(cfg.GetP(lastBlock.Height + 1).MaxTxNumber)
   118  		txs := client.RequestTx(maxTxNum, nil)
   119  		txs = client.CheckTxDup(txs)
   120  
   121  		// 为方便测试,设定基准测试模式,每个块交易数保持恒定,为配置的最大交易数
   122  		if len(txs) == 0 || (client.subcfg.BenchMode && len(txs) < maxTxNum) {
   123  			log.Debug("======SoloWaitMoreTxs======", "currTxNum", len(txs))
   124  			issleep = true
   125  			continue
   126  		}
   127  		issleep = false
   128  
   129  		var newblock types.Block
   130  		newblock.ParentHash = lastBlock.Hash(cfg)
   131  		newblock.Height = lastBlock.Height + 1
   132  		client.AddTxsToBlock(&newblock, txs)
   133  		//solo 挖矿固定难度
   134  		newblock.Difficulty = cfg.GetP(0).PowLimitBits
   135  		//需要首先对交易进行排序然后再计算TxHash
   136  		if cfg.IsFork(newblock.GetHeight(), "ForkRootHash") {
   137  			newblock.Txs = types.TransactionSort(newblock.Txs)
   138  		}
   139  		newblock.TxHash = merkle.CalcMerkleRoot(cfg, newblock.Height, newblock.Txs)
   140  		newblock.BlockTime = types.Now().Unix()
   141  		if lastBlock.BlockTime >= newblock.BlockTime {
   142  			newblock.BlockTime = lastBlock.BlockTime + 1
   143  		}
   144  		err := client.WriteBlock(lastBlock.StateHash, &newblock)
   145  		log.Info("SoloNewBlock", "height", newblock.Height, "txs", len(newblock.Txs), "cost", types.Since(beg))
   146  		beg = types.Now()
   147  		//判断有没有交易是被删除的,这类交易要从mempool 中删除
   148  		if err != nil {
   149  			issleep = true
   150  			continue
   151  		}
   152  	}
   153  }
   154  
   155  //CmpBestBlock 比较newBlock是不是最优区块
   156  func (client *Client) CmpBestBlock(newBlock *types.Block, cmpBlock *types.Block) bool {
   157  	return false
   158  }