github.com/turingchain2020/turingchain@v1.1.21/executor/execenv.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  
     7  import (
     8  	"bytes"
     9  
    10  	"github.com/turingchain2020/turingchain/executor/authority"
    11  
    12  	"github.com/turingchain2020/turingchain/account"
    13  	"github.com/turingchain2020/turingchain/client"
    14  	"github.com/turingchain2020/turingchain/client/api"
    15  	"github.com/turingchain2020/turingchain/common"
    16  	"github.com/turingchain2020/turingchain/common/address"
    17  	dbm "github.com/turingchain2020/turingchain/common/db"
    18  	drivers "github.com/turingchain2020/turingchain/system/dapp"
    19  	"github.com/turingchain2020/turingchain/types"
    20  	"github.com/golang/protobuf/proto"
    21  )
    22  
    23  //执行器 -> db 环境
    24  type executor struct {
    25  	stateDB      dbm.KV
    26  	localDB      dbm.KVDB
    27  	coinsAccount *account.DB
    28  	ctx          *executorCtx
    29  	height       int64
    30  	blocktime    int64
    31  	// 增加区块的难度值,后面的执行器逻辑需要这些属性
    32  	difficulty uint64
    33  	txs        []*types.Transaction
    34  	api        client.QueueProtocolAPI
    35  	gcli       types.TuringchainClient
    36  	execapi    api.ExecutorAPI
    37  	receipts   []*types.ReceiptData
    38  	//单个区块执行期间执行器缓存
    39  	driverCache map[string]drivers.Driver
    40  	//在单笔交易执行期间,将当前交易的执行driver缓存,避免多次load
    41  	currTxIdx  int
    42  	currExecTx *types.Transaction
    43  	currDriver drivers.Driver
    44  	cfg        *types.TuringchainConfig
    45  	exec       *Executor
    46  }
    47  
    48  type executorCtx struct {
    49  	stateHash  []byte
    50  	height     int64
    51  	blocktime  int64
    52  	difficulty uint64
    53  	parentHash []byte
    54  	mainHash   []byte
    55  	mainHeight int64
    56  }
    57  
    58  func newExecutor(ctx *executorCtx, exec *Executor, localdb dbm.KVDB, txs []*types.Transaction, receipts []*types.ReceiptData) *executor {
    59  	client := exec.client
    60  	types.AssertConfig(client)
    61  	cfg := client.GetConfig()
    62  	enableMVCC := exec.pluginEnable["mvcc"]
    63  	opt := &StateDBOption{EnableMVCC: enableMVCC, Height: ctx.height}
    64  
    65  	e := &executor{
    66  		stateDB:      NewStateDB(client, ctx.stateHash, localdb, opt),
    67  		localDB:      localdb,
    68  		coinsAccount: account.NewCoinsAccount(cfg),
    69  		height:       ctx.height,
    70  		blocktime:    ctx.blocktime,
    71  		difficulty:   ctx.difficulty,
    72  		ctx:          ctx,
    73  		txs:          txs,
    74  		receipts:     receipts,
    75  		api:          exec.qclient,
    76  		gcli:         exec.grpccli,
    77  		driverCache:  make(map[string]drivers.Driver),
    78  		currTxIdx:    -1,
    79  		cfg:          cfg,
    80  		exec:         exec,
    81  	}
    82  	e.coinsAccount.SetDB(e.stateDB)
    83  	return e
    84  }
    85  
    86  func (e *executor) enableMVCC(hash []byte) {
    87  	e.stateDB.(*StateDB).enableMVCC(hash)
    88  }
    89  
    90  // AddMVCC convert key value to mvcc kv data
    91  func AddMVCC(db dbm.KVDB, detail *types.BlockDetail) (kvlist []*types.KeyValue) {
    92  	kvs := detail.KV
    93  	hash := detail.Block.StateHash
    94  	mvcc := dbm.NewSimpleMVCC(db)
    95  	//检查版本号是否是连续的
    96  	kvlist, err := mvcc.AddMVCC(kvs, hash, detail.PrevStatusHash, detail.Block.Height)
    97  	if err != nil {
    98  		panic(err)
    99  	}
   100  	return kvlist
   101  }
   102  
   103  // DelMVCC convert key value to mvcc kv data
   104  func DelMVCC(db dbm.KVDB, detail *types.BlockDetail) (kvlist []*types.KeyValue) {
   105  	hash := detail.Block.StateHash
   106  	mvcc := dbm.NewSimpleMVCC(db)
   107  	kvlist, err := mvcc.DelMVCC(hash, detail.Block.Height, true)
   108  	if err != nil {
   109  		panic(err)
   110  	}
   111  	return kvlist
   112  }
   113  
   114  //隐私交易费扣除规则:
   115  //1.公对私交易:直接从coin合约中扣除
   116  //2.私对私交易或者私对公交易:交易费的扣除从隐私合约账户在coin合约中的账户中扣除
   117  func (e *executor) processFee(tx *types.Transaction) (*types.Receipt, error) {
   118  	from := tx.From()
   119  	accFrom := e.coinsAccount.LoadAccount(from)
   120  	if accFrom.GetBalance()-tx.Fee >= 0 {
   121  		copyfrom := *accFrom
   122  		accFrom.Balance = accFrom.GetBalance() - tx.Fee
   123  		receiptBalance := &types.ReceiptAccountTransfer{Prev: &copyfrom, Current: accFrom}
   124  		set := e.coinsAccount.GetKVSet(accFrom)
   125  		e.coinsAccount.SaveKVSet(set)
   126  		return e.cutFeeReceipt(set, receiptBalance), nil
   127  	}
   128  	return nil, types.ErrNoBalance
   129  }
   130  
   131  func (e *executor) cutFeeReceipt(kvset []*types.KeyValue, receiptBalance proto.Message) *types.Receipt {
   132  	feelog := &types.ReceiptLog{Ty: types.TyLogFee, Log: types.Encode(receiptBalance)}
   133  	return &types.Receipt{
   134  		Ty:   types.ExecPack,
   135  		KV:   kvset,
   136  		Logs: append([]*types.ReceiptLog{}, feelog),
   137  	}
   138  }
   139  
   140  func (e *executor) getRealExecName(tx *types.Transaction, index int) []byte {
   141  	exec := e.loadDriver(tx, index)
   142  	realexec := exec.GetDriverName()
   143  	var execer []byte
   144  	if realexec != "none" {
   145  		execer = []byte(realexec)
   146  	} else {
   147  		execer = tx.Execer
   148  	}
   149  	return execer
   150  }
   151  
   152  func (e *executor) checkTx(tx *types.Transaction, index int) error {
   153  
   154  	if e.height > 0 && e.blocktime > 0 && tx.IsExpire(e.cfg, e.height, e.blocktime) {
   155  		//如果已经过期
   156  		return types.ErrTxExpire
   157  	}
   158  	if err := tx.Check(e.cfg, e.height, e.cfg.GetMinTxFeeRate(), e.cfg.GetMaxTxFee()); err != nil {
   159  		return err
   160  	}
   161  	//允许重写的情况
   162  	//看重写的名字 name, 是否被允许执行
   163  	if !types.IsAllowExecName(e.getRealExecName(tx, index), tx.Execer) {
   164  		elog.Error("checkTx execNameNotAllow", "realname", string(e.getRealExecName(tx, index)), "exec", string(tx.Execer))
   165  		return types.ErrExecNameNotAllow
   166  	}
   167  	return nil
   168  }
   169  
   170  func (e *executor) setEnv(exec drivers.Driver) {
   171  	exec.SetAPI(e.api)
   172  	//执行器共用一个coins account对象
   173  	exec.SetCoinsAccount(e.coinsAccount)
   174  	exec.SetStateDB(e.stateDB)
   175  	exec.SetLocalDB(e.localDB)
   176  	exec.SetEnv(e.height, e.blocktime, e.difficulty)
   177  	exec.SetBlockInfo(e.ctx.parentHash, e.ctx.mainHash, e.ctx.mainHeight)
   178  	exec.SetExecutorAPI(e.api, e.gcli)
   179  	e.execapi = exec.GetExecutorAPI()
   180  	exec.SetTxs(e.txs)
   181  	exec.SetReceipt(e.receipts)
   182  }
   183  
   184  func (e *executor) checkTxGroup(txgroup *types.Transactions, index int) error {
   185  
   186  	if e.height > 0 && e.blocktime > 0 && txgroup.IsExpire(e.cfg, e.height, e.blocktime) {
   187  		//如果已经过期
   188  		return types.ErrTxExpire
   189  	}
   190  	if err := txgroup.Check(e.cfg, e.height, e.cfg.GetMinTxFeeRate(), e.cfg.GetMaxTxFee()); err != nil {
   191  		return err
   192  	}
   193  	return nil
   194  }
   195  
   196  func (e *executor) execCheckTx(tx *types.Transaction, index int) error {
   197  	//基本检查
   198  	err := e.checkTx(tx, index)
   199  	if err != nil {
   200  		return err
   201  	}
   202  	//检查地址的有效性
   203  	if err := address.CheckAddress(tx.To); err != nil {
   204  		return err
   205  	}
   206  	var exec drivers.Driver
   207  
   208  	//暂时只对none driver做了缓存处理 TODO: 增加其他执行器pool缓存
   209  	if types.Bytes2Str(tx.Execer) == "none" {
   210  		exec = e.getNoneDriver()
   211  		defer e.freeNoneDriver(exec)
   212  	} else {
   213  		exec = e.loadDriver(tx, index)
   214  	}
   215  	//手续费检查
   216  	if !exec.IsFree() && e.cfg.GetMinTxFeeRate() > 0 {
   217  		from := tx.From()
   218  		accFrom := e.coinsAccount.LoadAccount(from)
   219  
   220  		//余额少于手续费时直接返回错误
   221  		if accFrom.GetBalance() < tx.GetTxFee() {
   222  			elog.Error("execCheckTx", "ispara", e.cfg.IsPara(), "exec", string(tx.Execer), "Balance", accFrom.GetBalance(), "TxFee", tx.GetTxFee())
   223  			return types.ErrNoBalance
   224  		}
   225  
   226  		if accFrom.GetBalance() < e.cfg.GInt("MinBalanceTransfer") {
   227  			elog.Error("execCheckTx", "ispara", e.cfg.IsPara(), "exec", string(tx.Execer), "nonce", tx.Nonce, "Balance", accFrom.GetBalance())
   228  			return types.ErrBalanceLessThanTenTimesFee
   229  		}
   230  
   231  	}
   232  
   233  	// 证书检查
   234  	if authority.IsAuthEnable && e.cfg.IsFork(e.height, "ForkExecCert") {
   235  		err := authority.Author.Validate(tx.GetSignature())
   236  		if err != nil {
   237  			elog.Error("execCheckTx.authority", "exec", string(tx.Execer), "err", err.Error())
   238  			return err
   239  		}
   240  	}
   241  
   242  	return exec.CheckTx(tx, index)
   243  }
   244  
   245  // Exec base exec func
   246  func (e *executor) Exec(tx *types.Transaction, index int) (receipt *types.Receipt, err error) {
   247  	//针对一个交易执行阶段panic的处理,防止链停止,返回TyLogErr
   248  	defer func() {
   249  		if r := recover(); r != nil {
   250  			receipt = nil
   251  			err = types.ErrExecPanic
   252  			elog.Error("execTx.Exec", "index", index, "hash", common.ToHex(tx.Hash()), "err", r, "stack", GetStack())
   253  			return
   254  		}
   255  	}()
   256  
   257  	exec := e.loadDriver(tx, index)
   258  	//to 必须是一个地址
   259  	if err := drivers.CheckAddress(e.cfg, tx.GetRealToAddr(), e.height); err != nil {
   260  		return nil, err
   261  	}
   262  	if e.localDB != nil && e.cfg.IsFork(e.height, "ForkLocalDBAccess") {
   263  		e.localDB.(*LocalDB).DisableWrite()
   264  		if exec.ExecutorOrder() != drivers.ExecLocalSameTime {
   265  			e.localDB.(*LocalDB).DisableRead()
   266  		}
   267  		defer func() {
   268  			e.localDB.(*LocalDB).EnableWrite()
   269  			if exec.ExecutorOrder() != drivers.ExecLocalSameTime {
   270  				e.localDB.(*LocalDB).EnableRead()
   271  			}
   272  		}()
   273  	}
   274  	//第一步先检查 CheckTx
   275  	if err := exec.CheckTx(tx, index); err != nil {
   276  		return nil, err
   277  	}
   278  	r, err := exec.Exec(tx, index)
   279  	return r, err
   280  }
   281  
   282  func (e *executor) execLocal(tx *types.Transaction, r *types.ReceiptData, index int) (*types.LocalDBSet, error) {
   283  	exec := e.loadDriver(tx, index)
   284  	return exec.ExecLocal(tx, r, index)
   285  }
   286  
   287  func (e *executor) execDelLocal(tx *types.Transaction, r *types.ReceiptData, index int) (*types.LocalDBSet, error) {
   288  	exec := e.loadDriver(tx, index)
   289  	return exec.ExecDelLocal(tx, r, index)
   290  }
   291  
   292  func (e *executor) getNoneDriver() drivers.Driver {
   293  	none := e.exec.noneDriverPool.Get().(drivers.Driver)
   294  	e.setEnv(none)
   295  	return none
   296  }
   297  
   298  func (e *executor) freeNoneDriver(none drivers.Driver) {
   299  	e.exec.noneDriverPool.Put(none)
   300  }
   301  
   302  // 加载none执行器
   303  func (e *executor) loadNoneDriver() drivers.Driver {
   304  	none, ok := e.driverCache["none"]
   305  	var err error
   306  	if !ok {
   307  		none, err = drivers.LoadDriverWithClient(e.api, "none", 0)
   308  		if err != nil {
   309  			panic(err)
   310  		}
   311  		e.driverCache["none"] = none
   312  	}
   313  	return none
   314  }
   315  
   316  // loadDriver 加载执行器
   317  // 对单笔交易执行期间的执行器做了缓存,避免多次加载
   318  // 只有参数的tx,index,和记录的当前交易,当前索引,均相等时,才返回缓存的当前交易执行器
   319  func (e *executor) loadDriver(tx *types.Transaction, index int) (c drivers.Driver) {
   320  
   321  	// 交易和index都相等时,返回已缓存的当前交易执行器
   322  	if e.currExecTx == tx && e.currTxIdx == index {
   323  		return e.currDriver
   324  	}
   325  	var err error
   326  	name := types.Bytes2Str(tx.Execer)
   327  	driver, ok := e.driverCache[name]
   328  	isFork := e.cfg.IsFork(e.height, "ForkCacheDriver")
   329  
   330  	if !ok {
   331  		driver, err = drivers.LoadDriverWithClient(e.api, name, e.height)
   332  		if err != nil {
   333  			driver = e.loadNoneDriver()
   334  		}
   335  		e.driverCache[name] = driver
   336  	}
   337  
   338  	//fork之前,多笔相同执行器的交易只有第一笔会进行Allow判定,从缓存中获取的执行器不需要进行allow判定
   339  	//fork之后,所有的交易均需要单独执行Allow判定
   340  	if !ok || isFork {
   341  		driver.SetEnv(e.height, 0, 0)
   342  		err = driver.Allow(tx, index)
   343  	}
   344  
   345  	// allow不通过时,统一加载none执行器
   346  	if err != nil {
   347  		driver = e.loadNoneDriver()
   348  		//fork之前,cache中存放的是经过allow判定后,实际用于执行的执行器,比如主链执行平行链交易的执行器对应的是none对象
   349  		//fork之后,cache中存放的是和Execer名称对应的driver对象
   350  		//历史遗留问题 fork之前的问题在于cache缓存错乱,不应该缓存实际用于执行的,即缓存包含了allow的逻辑,导致错乱
   351  		//增加fork是由于已经存在由于cache问题导致的错误交易
   352  		//正确逻辑是,cache中的执行器对象和名称是一一对应的,保证了driver对象复用,但同时不同交易的allow需要重新判定
   353  		if !isFork {
   354  			e.driverCache[name] = driver
   355  		}
   356  	} else {
   357  		driver.SetName(types.Bytes2Str(types.GetRealExecName(tx.Execer)))
   358  		driver.SetCurrentExecName(name)
   359  	}
   360  	e.setEnv(driver)
   361  
   362  	//均不相等时,表明当前交易已更新,需要同步更新缓存,并记录当前交易及其index
   363  	if e.currExecTx != tx && e.currTxIdx != index {
   364  		e.currExecTx = tx
   365  		e.currTxIdx = index
   366  		e.currDriver = driver
   367  	}
   368  	return driver
   369  }
   370  
   371  func (e *executor) execTxGroup(txs []*types.Transaction, index int) ([]*types.Receipt, error) {
   372  	txgroup := &types.Transactions{Txs: txs}
   373  	err := e.checkTxGroup(txgroup, index)
   374  	if err != nil {
   375  		return nil, err
   376  	}
   377  	feelog, err := e.execFee(txs[0], index)
   378  	if err != nil {
   379  		return nil, err
   380  	}
   381  	//开启内存事务处理,假设系统只有一个thread 执行
   382  	//如果系统执行失败,回滚到这个状态
   383  	rollbackLog := copyReceipt(feelog)
   384  	e.begin()
   385  	receipts := make([]*types.Receipt, len(txs))
   386  	for i := 1; i < len(txs); i++ {
   387  		receipts[i] = &types.Receipt{Ty: types.ExecPack}
   388  	}
   389  	receipts[0], err = e.execTxOne(feelog, txs[0], index)
   390  	if err != nil {
   391  		//接口临时错误,取消执行
   392  		if api.IsAPIEnvError(err) {
   393  			return nil, err
   394  		}
   395  		//状态数据库回滚
   396  		if e.cfg.IsFork(e.height, "ForkExecRollback") {
   397  			e.rollback()
   398  		}
   399  		return receipts, nil
   400  	}
   401  	for i := 1; i < len(txs); i++ {
   402  		//如果有一笔执行失败了,那么全部回滚
   403  		receipts[i], err = e.execTxOne(receipts[i], txs[i], index+i)
   404  		if err != nil {
   405  			//reset other exec , and break!
   406  			if api.IsAPIEnvError(err) {
   407  				return nil, err
   408  			}
   409  			for k := 1; k < i; k++ {
   410  				receipts[k] = &types.Receipt{Ty: types.ExecPack}
   411  			}
   412  			//撤销txs[0]的交易
   413  			if e.cfg.IsFork(e.height, "ForkResetTx0") {
   414  				receipts[0] = rollbackLog
   415  			}
   416  			//撤销所有的数据库更新
   417  			e.rollback()
   418  			return receipts, nil
   419  		}
   420  	}
   421  	err = e.commit()
   422  	if err != nil {
   423  		return nil, err
   424  	}
   425  	return receipts, nil
   426  }
   427  
   428  func (e *executor) loadFlag(key []byte) (int64, error) {
   429  	flag := &types.Int64{}
   430  	flagBytes, err := e.localDB.Get(key)
   431  	if err == nil {
   432  		err = types.Decode(flagBytes, flag)
   433  		if err != nil {
   434  			return 0, err
   435  		}
   436  		return flag.GetData(), nil
   437  	} else if err == types.ErrNotFound {
   438  		return 0, nil
   439  	}
   440  	return 0, err
   441  }
   442  
   443  func (e *executor) execFee(tx *types.Transaction, index int) (*types.Receipt, error) {
   444  	feelog := &types.Receipt{Ty: types.ExecPack}
   445  	execer := string(tx.Execer)
   446  	ex := e.loadDriver(tx, index)
   447  	//执行器名称 和  pubkey 相同,费用从内置的执行器中扣除,但是checkTx 中要过
   448  	//默认checkTx 中对这样的交易会返回
   449  	if bytes.Equal(address.ExecPubKey(execer), tx.GetSignature().GetPubkey()) {
   450  		err := ex.CheckTx(tx, index)
   451  		if err != nil {
   452  			return nil, err
   453  		}
   454  	}
   455  	var err error
   456  	//公链不允许手续费为0
   457  	if !e.cfg.IsPara() && e.cfg.GetMinTxFeeRate() > 0 && !ex.IsFree() {
   458  		feelog, err = e.processFee(tx)
   459  		if err != nil {
   460  			return nil, err
   461  		}
   462  	}
   463  	return feelog, nil
   464  }
   465  
   466  func copyReceipt(feelog *types.Receipt) *types.Receipt {
   467  	receipt := types.Receipt{}
   468  	receipt = *feelog
   469  	receipt.KV = make([]*types.KeyValue, len(feelog.KV))
   470  	copy(receipt.KV, feelog.KV)
   471  	receipt.Logs = make([]*types.ReceiptLog, len(feelog.Logs))
   472  	copy(receipt.Logs, feelog.Logs)
   473  	return &receipt
   474  }
   475  
   476  func (e *executor) execTxOne(feelog *types.Receipt, tx *types.Transaction, index int) (*types.Receipt, error) {
   477  	//只有到pack级别的,才会增加index
   478  	e.startTx()
   479  	receipt, err := e.Exec(tx, index)
   480  	if err != nil {
   481  		elog.Error("exec tx error = ", "err", err, "exec", string(tx.Execer), "action", tx.ActionName())
   482  		//add error log
   483  		errlog := &types.ReceiptLog{Ty: types.TyLogErr, Log: []byte(err.Error())}
   484  		feelog.Logs = append(feelog.Logs, errlog)
   485  		return feelog, err
   486  	}
   487  	//合并两个receipt,如果执行不返回错误,那么就认为成功
   488  	//需要检查两个东西:
   489  	//1. statedb 中 Set的 key 必须是 在 receipt.GetKV() 这个集合中
   490  	//2. receipt.GetKV() 中的 key, 必须符合权限控制要求
   491  	memkvset := e.stateDB.(*StateDB).GetSetKeys()
   492  	err = e.checkKV(memkvset, receipt.GetKV())
   493  	if err != nil {
   494  		errlog := &types.ReceiptLog{Ty: types.TyLogErr, Log: []byte(err.Error())}
   495  		feelog.Logs = append(feelog.Logs, errlog)
   496  		return feelog, err
   497  	}
   498  	feelog, err = e.checkKeyAllow(feelog, tx, index, receipt.GetKV())
   499  	if err != nil {
   500  		return feelog, err
   501  	}
   502  	err = e.execLocalSameTime(tx, receipt, index)
   503  	if err != nil {
   504  		elog.Error("execLocalSameTime", "err", err)
   505  		errlog := &types.ReceiptLog{Ty: types.TyLogErr, Log: []byte(err.Error())}
   506  		feelog.Logs = append(feelog.Logs, errlog)
   507  		return feelog, err
   508  	}
   509  	if receipt != nil {
   510  		feelog.KV = append(feelog.KV, receipt.KV...)
   511  		feelog.Logs = append(feelog.Logs, receipt.Logs...)
   512  		feelog.Ty = receipt.Ty
   513  	}
   514  	if e.cfg.IsFork(e.height, "ForkStateDBSet") {
   515  		for _, v := range feelog.KV {
   516  			if err := e.stateDB.Set(v.Key, v.Value); err != nil {
   517  				panic(err)
   518  			}
   519  		}
   520  	}
   521  	return feelog, nil
   522  }
   523  
   524  func (e *executor) checkKV(memset []string, kvs []*types.KeyValue) error {
   525  	keys := make(map[string]bool)
   526  	for _, kv := range kvs {
   527  		k := kv.GetKey()
   528  		keys[string(k)] = true
   529  	}
   530  	for _, key := range memset {
   531  		if _, ok := keys[key]; !ok {
   532  			elog.Error("err memset key", "key", key)
   533  			//非法的receipt,交易执行失败
   534  			return types.ErrNotAllowMemSetKey
   535  		}
   536  	}
   537  	return nil
   538  }
   539  
   540  func (e *executor) checkKeyAllow(feelog *types.Receipt, tx *types.Transaction, index int, kvs []*types.KeyValue) (*types.Receipt, error) {
   541  	for _, kv := range kvs {
   542  		k := kv.GetKey()
   543  		if !e.isAllowExec(k, tx, index) {
   544  			elog.Error("err receipt key", "key", string(k), "tx.exec", string(tx.GetExecer()),
   545  				"tx.action", tx.ActionName())
   546  			//非法的receipt,交易执行失败
   547  			errlog := &types.ReceiptLog{Ty: types.TyLogErr, Log: []byte(types.ErrNotAllowKey.Error())}
   548  			feelog.Logs = append(feelog.Logs, errlog)
   549  			return feelog, types.ErrNotAllowKey
   550  		}
   551  	}
   552  	return feelog, nil
   553  }
   554  
   555  func (e *executor) begin() {
   556  	if e.cfg.IsFork(e.height, "ForkExecRollback") {
   557  		if e.stateDB != nil {
   558  			e.stateDB.Begin()
   559  		}
   560  		if e.localDB != nil {
   561  			e.localDB.Begin()
   562  		}
   563  	}
   564  }
   565  
   566  func (e *executor) commit() error {
   567  	if e.cfg.IsFork(e.height, "ForkExecRollback") {
   568  		if e.stateDB != nil {
   569  			if err := e.stateDB.Commit(); err != nil {
   570  				return err
   571  			}
   572  		}
   573  		if e.localDB != nil {
   574  			if err := e.localDB.Commit(); err != nil {
   575  				return err
   576  			}
   577  		}
   578  	}
   579  	return nil
   580  }
   581  
   582  func (e *executor) startTx() {
   583  	if e.stateDB != nil {
   584  		e.stateDB.(*StateDB).StartTx()
   585  	}
   586  	if e.localDB != nil {
   587  		e.localDB.(*LocalDB).StartTx()
   588  	}
   589  }
   590  
   591  func (e *executor) rollback() {
   592  	if e.cfg.IsFork(e.height, "ForkExecRollback") {
   593  		if e.stateDB != nil {
   594  			e.stateDB.Rollback()
   595  		}
   596  		if e.localDB != nil {
   597  			e.localDB.Rollback()
   598  		}
   599  	}
   600  }
   601  
   602  func (e *executor) execTx(exec *Executor, tx *types.Transaction, index int) (*types.Receipt, error) {
   603  	if e.height == 0 { //genesis block 不检查手续费
   604  		receipt, err := e.Exec(tx, index)
   605  		if err != nil {
   606  			panic(err)
   607  		}
   608  		if err == nil && receipt == nil {
   609  			panic("genesis block: executor not exist")
   610  		}
   611  		return receipt, nil
   612  	}
   613  	//交易检查规则:
   614  	//1. mempool 检查区块,尽量检查更多的错误
   615  	//2. 打包的时候,尽量打包更多的交易,只要基本的签名,以及格式没有问题
   616  	err := e.checkTx(tx, index)
   617  	if err != nil {
   618  		elog.Error("execTx.checkTx ", "txhash", common.ToHex(tx.Hash()), "err", err)
   619  		if e.cfg.IsPara() {
   620  			panic(err)
   621  		}
   622  		return nil, err
   623  	}
   624  	//处理交易手续费(先把手续费收了)
   625  	//如果收了手续费,表示receipt 至少是pack 级别
   626  	//收不了手续费的交易才是 error 级别
   627  	feelog, err := e.execFee(tx, index)
   628  	if err != nil {
   629  		return nil, err
   630  	}
   631  	//ignore err
   632  	e.begin()
   633  	feelog, err = e.execTxOne(feelog, tx, index)
   634  	if err != nil {
   635  		e.rollback()
   636  		elog.Error("exec tx = ", "index", index, "execer", string(tx.Execer), "err", err)
   637  	} else {
   638  		err := e.commit()
   639  		if err != nil {
   640  			return nil, err
   641  		}
   642  	}
   643  
   644  	if api.IsAPIEnvError(err) {
   645  		return nil, err
   646  	}
   647  	return feelog, nil
   648  }
   649  
   650  //allowExec key 行为判断放入 执行器
   651  /*
   652  权限控制规则:
   653  1. 默认行为:
   654  执行器只能修改执行器下面的 key
   655  或者能修改其他执行器 exec key 下面的数据
   656  
   657  2. friend 合约行为, 合约可以定义其他合约 可以修改的 key的内容
   658  */
   659  func (e *executor) isAllowExec(key []byte, tx *types.Transaction, index int) bool {
   660  	realExecer := e.getRealExecName(tx, index)
   661  	return isAllowKeyWrite(e, key, realExecer, tx, index)
   662  }
   663  
   664  func (e *executor) isExecLocalSameTime(tx *types.Transaction, index int) bool {
   665  	exec := e.loadDriver(tx, index)
   666  	return exec.ExecutorOrder() == drivers.ExecLocalSameTime
   667  }
   668  
   669  func (e *executor) checkPrefix(execer []byte, kvs []*types.KeyValue) error {
   670  	for i := 0; i < len(kvs); i++ {
   671  		err := isAllowLocalKey(e.cfg, execer, kvs[i].Key)
   672  		if err != nil {
   673  			//测试的情况下,先panic,实际情况下会删除返回错误
   674  			panic(err)
   675  			//return err
   676  		}
   677  	}
   678  	return nil
   679  }
   680  
   681  func (e *executor) execLocalSameTime(tx *types.Transaction, receipt *types.Receipt, index int) error {
   682  	if e.isExecLocalSameTime(tx, index) {
   683  		var r = &types.ReceiptData{}
   684  		if receipt != nil {
   685  			r.Ty = receipt.Ty
   686  			r.Logs = receipt.Logs
   687  		}
   688  		_, err := e.execLocalTx(tx, r, index)
   689  		return err
   690  	}
   691  	return nil
   692  }
   693  
   694  func (e *executor) execLocalTx(tx *types.Transaction, r *types.ReceiptData, index int) (*types.LocalDBSet, error) {
   695  	kv, err := e.execLocal(tx, r, index)
   696  	if err == types.ErrActionNotSupport {
   697  		return nil, nil
   698  	}
   699  	if err != nil {
   700  		return nil, err
   701  	}
   702  	memkvset := e.localDB.(*LocalDB).GetSetKeys()
   703  	if kv != nil && kv.KV != nil {
   704  		err := e.checkKV(memkvset, kv.KV)
   705  		if err != nil {
   706  			return nil, types.ErrNotAllowMemSetLocalKey
   707  		}
   708  		err = e.checkPrefix(tx.Execer, kv.KV)
   709  		if err != nil {
   710  			return nil, err
   711  		}
   712  		for _, kv := range kv.KV {
   713  			err = e.localDB.Set(kv.Key, kv.Value)
   714  			if err != nil {
   715  				panic(err)
   716  			}
   717  		}
   718  	} else {
   719  		if len(memkvset) > 0 {
   720  			return nil, types.ErrNotAllowMemSetLocalKey
   721  		}
   722  	}
   723  	return kv, nil
   724  }