github.com/turingchain2020/turingchain@v1.1.21/blockchain/restore.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 blockchain
     6  
     7  import (
     8  	"strings"
     9  
    10  	"fmt"
    11  
    12  	dbm "github.com/turingchain2020/turingchain/common/db"
    13  	"github.com/turingchain2020/turingchain/common/version"
    14  	"github.com/turingchain2020/turingchain/types"
    15  )
    16  
    17  // Upgrade 升级localDB和storeDB
    18  func (chain *BlockChain) Upgrade() {
    19  	chainlog.Info("chain upgrade start")
    20  	chain.UpgradeChain()
    21  	chainlog.Info("storedb upgrade start")
    22  	chain.UpgradeStore()
    23  	chainlog.Info("upgrade all dapp")
    24  	chain.UpgradePlugin()
    25  	chainlog.Info("chain reduce start")
    26  	chain.ReduceChain()
    27  }
    28  
    29  // UpgradePlugin 升级插件
    30  func (chain *BlockChain) UpgradePlugin() {
    31  	msg := chain.client.NewMessage("execs", types.EventUpgrade, nil)
    32  	err := chain.client.Send(msg, true)
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  	resp, err := chain.client.Wait(msg)
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  	if resp == nil {
    41  		return
    42  	}
    43  	kv := resp.GetData().(*types.LocalDBSet)
    44  	if kv == nil || len(kv.KV) == 0 {
    45  		return
    46  	}
    47  
    48  	chain.blockStore.mustSaveKvset(kv)
    49  }
    50  
    51  //UpgradeStore 升级storedb
    52  func (chain *BlockChain) UpgradeStore() {
    53  	meta, err := chain.blockStore.GetStoreUpgradeMeta()
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  	curheight := chain.GetBlockHeight()
    58  	if curheight == -1 {
    59  		meta = &types.UpgradeMeta{
    60  			Version: version.GetStoreDBVersion(),
    61  		}
    62  		err = chain.blockStore.SetStoreUpgradeMeta(meta)
    63  		if err != nil {
    64  			panic(err)
    65  		}
    66  	}
    67  	if chain.NeedReExec(meta) {
    68  		//如果没有开始重建index,那么先del all keys
    69  		if !meta.Starting && chain.cfg.EnableReExecLocal {
    70  			chainlog.Info("begin del all keys")
    71  			chain.blockStore.delAllKeys()
    72  			chainlog.Info("end del all keys")
    73  		}
    74  		start := meta.Height
    75  		//reExecBlock 的过程中,会每个高度都去更新meta
    76  		chain.ReExecBlock(start, curheight)
    77  		meta := &types.UpgradeMeta{
    78  			Starting: false,
    79  			Version:  version.GetStoreDBVersion(),
    80  			Height:   0,
    81  		}
    82  		err = chain.blockStore.SetStoreUpgradeMeta(meta)
    83  		if err != nil {
    84  			panic(err)
    85  		}
    86  	}
    87  }
    88  
    89  // ReExecBlock 从对应高度本地重新执行区块
    90  func (chain *BlockChain) ReExecBlock(startHeight, curHeight int64) {
    91  	var prevStateHash []byte
    92  	if startHeight > 0 {
    93  		blockdetail, err := chain.GetBlock(startHeight - 1)
    94  		if err != nil {
    95  			panic(fmt.Sprintf("get height=%d err, this not allow fail", startHeight-1))
    96  		}
    97  		prevStateHash = blockdetail.Block.StateHash
    98  	}
    99  
   100  	for i := startHeight; i <= curHeight; i++ {
   101  		blockdetail, err := chain.GetBlock(i)
   102  		if err != nil {
   103  			panic(fmt.Sprintf("get height=%d err, this not allow fail", i))
   104  		}
   105  		block := blockdetail.Block
   106  		err = execBlockUpgrade(chain.client, prevStateHash, block, false)
   107  		if err != nil {
   108  			panic(fmt.Sprintf("execBlockEx height=%d err=%s, this not allow fail", i, err.Error()))
   109  		}
   110  
   111  		if chain.cfg.EnableReExecLocal {
   112  			// 保存tx信息到db中
   113  			newbatch := chain.blockStore.NewBatch(false)
   114  			err = chain.blockStore.AddTxs(newbatch, blockdetail)
   115  			if err != nil {
   116  				panic(fmt.Sprintf("execBlockEx connectBlock readd Txs fail height=%d err=%s, this not allow fail", i, err.Error()))
   117  			}
   118  			dbm.MustWrite(newbatch)
   119  		}
   120  
   121  		prevStateHash = block.StateHash
   122  		//更新高度
   123  		err = chain.upgradeMeta(i)
   124  		if err != nil {
   125  			panic(err)
   126  		}
   127  	}
   128  }
   129  
   130  // NeedReExec 是否需要重新执行
   131  func (chain *BlockChain) NeedReExec(meta *types.UpgradeMeta) bool {
   132  	if meta.Starting { //正在
   133  		return true
   134  	}
   135  	v1 := meta.Version
   136  	v2 := version.GetStoreDBVersion()
   137  	v1arr := strings.Split(v1, ".") // 数据库中版本
   138  	v2arr := strings.Split(v2, ".") // 程序中的版本
   139  	if len(v1arr) != 3 || len(v2arr) != 3 {
   140  		panic("upgrade store meta version error")
   141  	}
   142  	if v2arr[0] > "2" {
   143  		chainlog.Info("NeedReExec", "version program", v1, "version DB", v2)
   144  		panic("not support upgrade store to greater than 2.0.0")
   145  	}
   146  	if v1arr[0] > v2arr[0] { // 数据库已经是新版本不允许降级使用旧程序
   147  		chainlog.Info("NeedReExec", "version program", v1, "version DB", v2)
   148  		panic("not support degrade the program")
   149  	}
   150  	return v1arr[0] != v2arr[0]
   151  }
   152  
   153  func (chain *BlockChain) upgradeMeta(height int64) error {
   154  	meta := &types.UpgradeMeta{
   155  		Starting: true,
   156  		Version:  version.GetStoreDBVersion(),
   157  		Height:   height + 1,
   158  	}
   159  	return chain.blockStore.SetStoreUpgradeMeta(meta)
   160  }