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 }