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 }