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  }