github.com/turingchain2020/turingchain@v1.1.21/executor/executor.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 executor 实现执行器模块基类功能 6 package executor 7 8 //store package store the world - state data 9 import ( 10 "fmt" 11 "runtime" 12 "strings" 13 "sync" 14 15 "github.com/turingchain2020/turingchain/executor/authority" 16 17 "github.com/turingchain2020/turingchain/client/api" 18 dbm "github.com/turingchain2020/turingchain/common/db" 19 clog "github.com/turingchain2020/turingchain/common/log" 20 log "github.com/turingchain2020/turingchain/common/log/log15" 21 "github.com/turingchain2020/turingchain/pluginmgr" 22 "github.com/turingchain2020/turingchain/rpc/grpcclient" 23 drivers "github.com/turingchain2020/turingchain/system/dapp" 24 25 // register drivers 26 "github.com/turingchain2020/turingchain/client" 27 "github.com/turingchain2020/turingchain/queue" 28 "github.com/turingchain2020/turingchain/types" 29 typ "github.com/turingchain2020/turingchain/types" 30 ) 31 32 var elog = log.New("module", "execs") 33 34 // SetLogLevel set log level 35 func SetLogLevel(level string) { 36 clog.SetLogLevel(level) 37 } 38 39 // DisableLog disable log 40 func DisableLog() { 41 elog.SetHandler(log.DiscardHandler()) 42 } 43 44 // Executor executor struct 45 type Executor struct { 46 disableLocal bool 47 client queue.Client 48 qclient client.QueueProtocolAPI 49 grpccli types.TuringchainClient 50 pluginEnable map[string]bool 51 alias map[string]string 52 noneDriverPool *sync.Pool 53 } 54 55 func execInit(cfg *typ.TuringchainConfig) { 56 pluginmgr.InitExec(cfg) 57 } 58 59 var runonce sync.Once 60 61 // New new executor 62 func New(cfg *typ.TuringchainConfig) *Executor { 63 // init executor 64 runonce.Do(func() { 65 execInit(cfg) 66 }) 67 mcfg := cfg.GetModuleConfig().Exec 68 exec := &Executor{} 69 exec.pluginEnable = make(map[string]bool) 70 exec.pluginEnable["stat"] = mcfg.EnableStat 71 exec.pluginEnable["mvcc"] = mcfg.EnableMVCC 72 exec.pluginEnable["addrindex"] = !mcfg.DisableAddrIndex 73 exec.pluginEnable["txindex"] = true 74 exec.pluginEnable["fee"] = true 75 exec.noneDriverPool = &sync.Pool{ 76 New: func() interface{} { 77 none, err := drivers.LoadDriver("none", 0) 78 if err != nil { 79 panic("load none driver err") 80 } 81 return none 82 }, 83 } 84 exec.alias = make(map[string]string) 85 for _, v := range mcfg.Alias { 86 data := strings.Split(v, ":") 87 if len(data) != 2 { 88 panic("exec.alias config error: " + v) 89 } 90 if _, ok := exec.alias[data[0]]; ok { 91 panic("exec.alias repeat name: " + v) 92 } 93 if pluginmgr.HasExec(data[0]) { 94 panic("exec.alias repeat name with system Exec: " + v) 95 } 96 exec.alias[data[0]] = data[1] 97 } 98 99 sub := cfg.GetSubConfig().Exec["cert"] 100 if sub != nil { 101 var scfg types.AuthorityCfg 102 types.MustDecode(sub, &scfg) 103 104 err := authority.Author.Init(&scfg) 105 if err != nil { 106 panic("exec.auth error to initialize authority:" + err.Error()) 107 } 108 } 109 110 return exec 111 } 112 113 //Wait Executor ready 114 func (exec *Executor) Wait() {} 115 116 // SetQueueClient set client queue, for recv msg 117 func (exec *Executor) SetQueueClient(qcli queue.Client) { 118 exec.client = qcli 119 exec.client.Sub("execs") 120 var err error 121 exec.qclient, err = client.New(qcli, nil) 122 if err != nil { 123 panic(err) 124 } 125 types.AssertConfig(exec.client) 126 cfg := exec.client.GetConfig() 127 if cfg.IsPara() { 128 exec.grpccli, err = grpcclient.NewMainChainClient(cfg, "") 129 if err != nil { 130 panic(err) 131 } 132 } 133 134 //recv 消息的处理 135 go func() { 136 for msg := range exec.client.Recv() { 137 elog.Debug("exec recv", "msg", msg) 138 if msg.Ty == types.EventExecTxList { 139 go exec.procExecTxList(msg) 140 } else if msg.Ty == types.EventAddBlock { 141 go exec.procExecAddBlock(msg) 142 } else if msg.Ty == types.EventDelBlock { 143 go exec.procExecDelBlock(msg) 144 } else if msg.Ty == types.EventCheckTx { 145 go exec.procExecCheckTx(msg) 146 } else if msg.Ty == types.EventBlockChainQuery { 147 go exec.procExecQuery(msg) 148 } else if msg.Ty == types.EventUpgrade { 149 //执行升级过程中不允许执行其他的事件,这个事件直接不采用异步执行 150 exec.procUpgrade(msg) 151 } 152 } 153 }() 154 } 155 156 func (exec *Executor) procUpgrade(msg *queue.Message) { 157 var kvset types.LocalDBSet 158 for _, plugin := range pluginmgr.GetExecList() { 159 elog.Info("begin upgrade plugin ", "name", plugin) 160 kvset1, err := exec.upgradePlugin(plugin) 161 if err != nil { 162 msg.Reply(exec.client.NewMessage("", types.EventUpgrade, err)) 163 panic(err) 164 } 165 if kvset1 != nil && kvset1.KV != nil && len(kvset1.KV) > 0 { 166 kvset.KV = append(kvset.KV, kvset1.KV...) 167 } 168 } 169 elog.Info("upgrade plugin success") 170 msg.Reply(exec.client.NewMessage("", types.EventUpgrade, &kvset)) 171 } 172 173 func (exec *Executor) upgradePlugin(plugin string) (*types.LocalDBSet, error) { 174 header, err := exec.qclient.GetLastHeader() 175 if err != nil { 176 return nil, err 177 } 178 driver, err := drivers.LoadDriverWithClient(exec.qclient, plugin, header.GetHeight()) 179 if err == types.ErrUnknowDriver { //已经注册插件,但是没有启动 180 elog.Info("upgrade ignore ", "name", plugin) 181 return nil, nil 182 } 183 if err != nil { 184 return nil, err 185 } 186 var localdb dbm.KVDB 187 if !exec.disableLocal { 188 localdb = NewLocalDB(exec.client, false) 189 defer localdb.(*LocalDB).Close() 190 driver.SetLocalDB(localdb) 191 } 192 //目前升级不允许访问statedb 193 driver.SetStateDB(nil) 194 driver.SetAPI(exec.qclient) 195 driver.SetExecutorAPI(exec.qclient, exec.grpccli) 196 driver.SetEnv(header.GetHeight(), header.GetBlockTime(), uint64(header.GetDifficulty())) 197 localdb.Begin() 198 kvset, err := driver.Upgrade() 199 if err != nil { 200 localdb.Rollback() 201 return nil, err 202 } 203 localdb.Commit() 204 return kvset, nil 205 } 206 207 func (exec *Executor) procExecQuery(msg *queue.Message) { 208 //panic 处理 209 defer func() { 210 if r := recover(); r != nil { 211 elog.Error("query panic error", "err", r) 212 msg.Reply(exec.client.NewMessage("", types.EventReceipts, types.ErrExecPanic)) 213 return 214 } 215 }() 216 header, err := exec.qclient.GetLastHeader() 217 if err != nil { 218 msg.Reply(exec.client.NewMessage("", types.EventBlockChainQuery, err)) 219 return 220 } 221 data := msg.GetData().(*types.ChainExecutor) 222 driver, err := drivers.LoadDriverWithClient(exec.qclient, data.Driver, header.GetHeight()) 223 if err != nil { 224 msg.Reply(exec.client.NewMessage("", types.EventBlockChainQuery, err)) 225 return 226 } 227 if data.StateHash == nil { 228 data.StateHash = header.StateHash 229 } 230 var localdb dbm.KVDB 231 if !exec.disableLocal { 232 //query 只需要读取localdb 233 localdb = NewLocalDB(exec.client, true) 234 defer localdb.(*LocalDB).Close() 235 driver.SetLocalDB(localdb) 236 } 237 opt := &StateDBOption{EnableMVCC: exec.pluginEnable["mvcc"], Height: header.GetHeight()} 238 239 db := NewStateDB(exec.client, data.StateHash, localdb, opt) 240 db.(*StateDB).enableMVCC(nil) 241 driver.SetStateDB(db) 242 driver.SetAPI(exec.qclient) 243 driver.SetExecutorAPI(exec.qclient, exec.grpccli) 244 driver.SetEnv(header.GetHeight(), header.GetBlockTime(), uint64(header.GetDifficulty())) 245 //查询的情况下下,执行器不做严格校验,allow,尽可能的加载执行器,并且做查询 246 247 ret, err := driver.Query(data.FuncName, data.Param) 248 if err != nil { 249 msg.Reply(exec.client.NewMessage("", types.EventBlockChainQuery, err)) 250 return 251 } 252 msg.Reply(exec.client.NewMessage("", types.EventBlockChainQuery, ret)) 253 } 254 255 func (exec *Executor) procExecCheckTx(msg *queue.Message) { 256 //panic 处理 257 defer func() { 258 if r := recover(); r != nil { 259 elog.Error("check panic error", "err", r) 260 msg.Reply(exec.client.NewMessage("", types.EventReceipts, types.ErrExecPanic)) 261 return 262 } 263 }() 264 datas := msg.GetData().(*types.ExecTxList) 265 ctx := &executorCtx{ 266 stateHash: datas.StateHash, 267 height: datas.Height, 268 blocktime: datas.BlockTime, 269 difficulty: datas.Difficulty, 270 mainHash: datas.MainHash, 271 mainHeight: datas.MainHeight, 272 parentHash: datas.ParentHash, 273 } 274 var localdb dbm.KVDB 275 276 if !exec.disableLocal { 277 //交易检查只需要读取localdb,只读模式 278 localdb = NewLocalDB(exec.client, true) 279 defer localdb.(*LocalDB).Close() 280 } 281 execute := newExecutor(ctx, exec, localdb, datas.Txs, nil) 282 execute.enableMVCC(nil) 283 //返回一个列表表示成功还是失败 284 result := &types.ReceiptCheckTxList{} 285 for i := 0; i < len(datas.Txs); i++ { 286 tx := datas.Txs[i] 287 index := i 288 if datas.IsMempool { 289 index = -1 290 } 291 err := execute.execCheckTx(tx, index) 292 if err != nil { 293 result.Errs = append(result.Errs, err.Error()) 294 } else { 295 result.Errs = append(result.Errs, "") 296 } 297 } 298 msg.Reply(exec.client.NewMessage("", types.EventReceiptCheckTx, result)) 299 } 300 301 // GetStack ... 302 func GetStack() string { 303 var buf [4048]byte 304 n := runtime.Stack(buf[:], false) 305 return fmt.Sprintf("==> %s\n", string(buf[:n])) 306 } 307 308 func (exec *Executor) procExecTxList(msg *queue.Message) { 309 //panic 处理 310 defer func() { 311 if r := recover(); r != nil { 312 elog.Error("exec tx list panic error", "err", r, "stack", GetStack()) 313 msg.Reply(exec.client.NewMessage("", types.EventReceipts, types.ErrExecPanic)) 314 return 315 } 316 }() 317 datas := msg.GetData().(*types.ExecTxList) 318 ctx := &executorCtx{ 319 stateHash: datas.StateHash, 320 height: datas.Height, 321 blocktime: datas.BlockTime, 322 difficulty: datas.Difficulty, 323 mainHash: datas.MainHash, 324 mainHeight: datas.MainHeight, 325 parentHash: datas.ParentHash, 326 } 327 var localdb dbm.KVDB 328 if !exec.disableLocal { 329 localdb = NewLocalDB(exec.client, false) 330 defer localdb.(*LocalDB).Close() 331 } 332 execute := newExecutor(ctx, exec, localdb, datas.Txs, nil) 333 execute.enableMVCC(nil) 334 var receipts []*types.Receipt 335 index := 0 336 for i := 0; i < len(datas.Txs); i++ { 337 tx := datas.Txs[i] 338 //检查groupcount 339 if tx.GroupCount < 0 || tx.GroupCount == 1 || tx.GroupCount > 20 { 340 receipts = append(receipts, types.NewErrReceipt(types.ErrTxGroupCount)) 341 continue 342 } 343 if tx.GroupCount == 0 { 344 receipt, err := execute.execTx(exec, tx, index) 345 if api.IsAPIEnvError(err) { 346 msg.Reply(exec.client.NewMessage("", types.EventReceipts, err)) 347 return 348 } 349 if err != nil { 350 receipts = append(receipts, types.NewErrReceipt(err)) 351 continue 352 } 353 //update local 354 receipts = append(receipts, receipt) 355 index++ 356 continue 357 } 358 //所有tx.GroupCount > 0 的交易都是错误的交易 359 if !execute.cfg.IsFork(datas.Height, "ForkTxGroup") { 360 receipts = append(receipts, types.NewErrReceipt(types.ErrTxGroupNotSupport)) 361 continue 362 } 363 //判断GroupCount 是否会产生越界 364 if i+int(tx.GroupCount) > len(datas.Txs) { 365 receipts = append(receipts, types.NewErrReceipt(types.ErrTxGroupCount)) 366 continue 367 } 368 receiptlist, err := execute.execTxGroup(datas.Txs[i:i+int(tx.GroupCount)], index) 369 i = i + int(tx.GroupCount) - 1 370 if len(receiptlist) > 0 && len(receiptlist) != int(tx.GroupCount) { 371 panic("len(receiptlist) must be equal tx.GroupCount") 372 } 373 if err != nil { 374 if api.IsAPIEnvError(err) { 375 msg.Reply(exec.client.NewMessage("", types.EventReceipts, err)) 376 return 377 } 378 for n := 0; n < int(tx.GroupCount); n++ { 379 receipts = append(receipts, types.NewErrReceipt(err)) 380 } 381 continue 382 } 383 receipts = append(receipts, receiptlist...) 384 index += int(tx.GroupCount) 385 } 386 msg.Reply(exec.client.NewMessage("", types.EventReceipts, 387 &types.Receipts{Receipts: receipts})) 388 } 389 390 func (exec *Executor) procExecAddBlock(msg *queue.Message) { 391 //panic 处理 392 defer func() { 393 if r := recover(); r != nil { 394 elog.Error("add blk panic error", "err", r) 395 msg.Reply(exec.client.NewMessage("", types.EventReceipts, types.ErrExecPanic)) 396 return 397 } 398 }() 399 datas := msg.GetData().(*types.BlockDetail) 400 b := datas.Block 401 ctx := &executorCtx{ 402 stateHash: b.StateHash, 403 height: b.Height, 404 blocktime: b.BlockTime, 405 difficulty: uint64(b.Difficulty), 406 mainHash: b.MainHash, 407 mainHeight: b.MainHeight, 408 parentHash: b.ParentHash, 409 } 410 var localdb dbm.KVDB 411 if !exec.disableLocal { 412 localdb = NewLocalDB(exec.client, false) 413 defer localdb.(*LocalDB).Close() 414 } 415 execute := newExecutor(ctx, exec, localdb, b.Txs, datas.Receipts) 416 //因为mvcc 还没有写入,所以目前的mvcc版本是前一个区块的版本 417 execute.enableMVCC(datas.PrevStatusHash) 418 var kvset types.LocalDBSet 419 for _, kv := range datas.KV { 420 err := execute.stateDB.Set(kv.Key, kv.Value) 421 if err != nil { 422 panic(err) 423 } 424 } 425 for name, plugin := range globalPlugins { 426 kvs, ok, err := plugin.CheckEnable(execute, exec.pluginEnable[name]) 427 if err != nil { 428 panic(err) 429 } 430 if !ok { 431 continue 432 } 433 if len(kvs) > 0 { 434 kvset.KV = append(kvset.KV, kvs...) 435 } 436 kvs, err = plugin.ExecLocal(execute, datas) 437 if err != nil { 438 msg.Reply(exec.client.NewMessage("", types.EventAddBlock, err)) 439 return 440 } 441 if len(kvs) > 0 { 442 kvset.KV = append(kvset.KV, kvs...) 443 for _, kv := range kvs { 444 err := execute.localDB.Set(kv.Key, kv.Value) 445 if err != nil { 446 panic(err) 447 } 448 } 449 } 450 } 451 for i := 0; i < len(b.Txs); i++ { 452 tx := b.Txs[i] 453 execute.localDB.(*LocalDB).StartTx() 454 kv, err := execute.execLocalTx(tx, datas.Receipts[i], i) 455 if err != nil { 456 msg.Reply(exec.client.NewMessage("", types.EventAddBlock, err)) 457 return 458 } 459 if kv != nil && kv.KV != nil { 460 kvset.KV = append(kvset.KV, kv.KV...) 461 } 462 } 463 msg.Reply(exec.client.NewMessage("", types.EventAddBlock, &kvset)) 464 } 465 466 func (exec *Executor) procExecDelBlock(msg *queue.Message) { 467 //panic 处理 468 defer func() { 469 if r := recover(); r != nil { 470 elog.Error("del blk panic error", "err", r) 471 msg.Reply(exec.client.NewMessage("", types.EventReceipts, types.ErrExecPanic)) 472 return 473 } 474 }() 475 datas := msg.GetData().(*types.BlockDetail) 476 b := datas.Block 477 ctx := &executorCtx{ 478 stateHash: b.StateHash, 479 height: b.Height, 480 blocktime: b.BlockTime, 481 difficulty: uint64(b.Difficulty), 482 mainHash: b.MainHash, 483 mainHeight: b.MainHeight, 484 parentHash: b.ParentHash, 485 } 486 var localdb dbm.KVDB 487 if !exec.disableLocal { 488 localdb = NewLocalDB(exec.client, false) 489 defer localdb.(*LocalDB).Close() 490 } 491 execute := newExecutor(ctx, exec, localdb, b.Txs, nil) 492 execute.enableMVCC(nil) 493 var kvset types.LocalDBSet 494 for _, kv := range datas.KV { 495 err := execute.stateDB.Set(kv.Key, kv.Value) 496 if err != nil { 497 panic(err) 498 } 499 } 500 for name, plugin := range globalPlugins { 501 kvs, ok, err := plugin.CheckEnable(execute, exec.pluginEnable[name]) 502 if err != nil { 503 panic(err) 504 } 505 if !ok { 506 continue 507 } 508 if len(kvs) > 0 { 509 kvset.KV = append(kvset.KV, kvs...) 510 } 511 kvs, err = plugin.ExecDelLocal(execute, datas) 512 if err != nil { 513 msg.Reply(exec.client.NewMessage("", types.EventAddBlock, err)) 514 return 515 } 516 if len(kvs) > 0 { 517 kvset.KV = append(kvset.KV, kvs...) 518 } 519 } 520 for i := len(b.Txs) - 1; i >= 0; i-- { 521 tx := b.Txs[i] 522 kv, err := execute.execDelLocal(tx, datas.Receipts[i], i) 523 if err == types.ErrActionNotSupport { 524 continue 525 } 526 if err != nil { 527 msg.Reply(exec.client.NewMessage("", types.EventDelBlock, err)) 528 return 529 } 530 if kv != nil && kv.KV != nil { 531 err := execute.checkPrefix(tx.Execer, kv.KV) 532 if err != nil { 533 msg.Reply(exec.client.NewMessage("", types.EventDelBlock, err)) 534 return 535 } 536 kvset.KV = append(kvset.KV, kv.KV...) 537 } 538 } 539 msg.Reply(exec.client.NewMessage("", types.EventDelBlock, &kvset)) 540 } 541 542 // Close close executor 543 func (exec *Executor) Close() { 544 elog.Info("exec module closed") 545 if exec.client != nil { 546 exec.client.Close() 547 } 548 }