github.com/turingchain2020/turingchain@v1.1.21/system/dapp/driver.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 dapp 系统基础dapp包
     6  package dapp
     7  
     8  //package none execer for unknow execer
     9  //all none transaction exec ok, execept nofee
    10  //nofee transaction will not pack into block
    11  
    12  import (
    13  	"bytes"
    14  	"reflect"
    15  
    16  	"github.com/turingchain2020/turingchain/account"
    17  	"github.com/turingchain2020/turingchain/client"
    18  	"github.com/turingchain2020/turingchain/client/api"
    19  	"github.com/turingchain2020/turingchain/common/address"
    20  	dbm "github.com/turingchain2020/turingchain/common/db"
    21  	log "github.com/turingchain2020/turingchain/common/log/log15"
    22  	"github.com/turingchain2020/turingchain/types"
    23  )
    24  
    25  var blog = log.New("module", "execs.base")
    26  
    27  const (
    28  	// TxIndexFrom transaction index from
    29  	TxIndexFrom = 1
    30  	// TxIndexTo transaction index to
    31  	TxIndexTo = 2
    32  
    33  	//ExecLocalSameTime Exec 的时候 同时执行 ExecLocal
    34  	ExecLocalSameTime = int64(1)
    35  )
    36  
    37  // Driver defines some interface
    38  type Driver interface {
    39  	SetStateDB(dbm.KV)
    40  	SetCoinsAccount(*account.DB)
    41  	GetCoinsAccount() *account.DB
    42  	SetLocalDB(dbm.KVDB)
    43  	//当前交易执行器名称
    44  	GetCurrentExecName() string
    45  	//驱动的名字,这个名称是固定的
    46  	GetDriverName() string
    47  	//执行器的别名(一个驱动(code),允许创建多个执行器,类似evm一份代码可以创建多个合约)
    48  	GetName() string
    49  	GetExecutorAPI() api.ExecutorAPI
    50  	//设置执行器的真实名称
    51  	SetName(string)
    52  	SetCurrentExecName(string)
    53  	Allow(tx *types.Transaction, index int) error
    54  	IsFriend(myexec []byte, writekey []byte, othertx *types.Transaction) bool
    55  	GetActionName(tx *types.Transaction) string
    56  	SetEnv(height, blocktime int64, difficulty uint64)
    57  	SetBlockInfo([]byte, []byte, int64)
    58  	CheckTx(tx *types.Transaction, index int) error
    59  	Exec(tx *types.Transaction, index int) (*types.Receipt, error)
    60  	ExecLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error)
    61  	ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error)
    62  	Query(funcName string, params []byte) (types.Message, error)
    63  	IsFree() bool
    64  	SetAPI(client.QueueProtocolAPI)
    65  	SetExecutorAPI(queueapi client.QueueProtocolAPI, turingchainapi types.TuringchainClient)
    66  	SetTxs(txs []*types.Transaction)
    67  	SetReceipt(receipts []*types.ReceiptData)
    68  
    69  	//GetTxs and TxGroup
    70  	GetTxs() []*types.Transaction
    71  	GetTxGroup(index int) ([]*types.Transaction, error)
    72  	GetPayloadValue() types.Message
    73  	GetFuncMap() map[string]reflect.Method
    74  	GetExecutorType() types.ExecutorType
    75  	CheckReceiptExecOk() bool
    76  	ExecutorOrder() int64
    77  	Upgrade() (*types.LocalDBSet, error)
    78  }
    79  
    80  // DriverBase defines driverbase type
    81  type DriverBase struct {
    82  	statedb              dbm.KV
    83  	localdb              dbm.KVDB
    84  	coinsaccount         *account.DB
    85  	height               int64
    86  	blocktime            int64
    87  	parentHash, mainHash []byte
    88  	mainHeight           int64
    89  	name                 string
    90  	curname              string
    91  	child                Driver
    92  	childValue           reflect.Value
    93  	isFree               bool
    94  	difficulty           uint64
    95  	api                  client.QueueProtocolAPI
    96  	execapi              api.ExecutorAPI
    97  	txs                  []*types.Transaction
    98  	receipts             []*types.ReceiptData
    99  	ety                  types.ExecutorType
   100  }
   101  
   102  //Upgrade default upgrade only print a message
   103  func (d *DriverBase) Upgrade() (*types.LocalDBSet, error) {
   104  	blog.Info("upgrade ", "dapp", d.GetName())
   105  	return nil, nil
   106  }
   107  
   108  // GetPayloadValue define get payload func
   109  func (d *DriverBase) GetPayloadValue() types.Message {
   110  	if d.ety == nil {
   111  		return nil
   112  	}
   113  	return d.ety.GetPayload()
   114  }
   115  
   116  // GetExecutorType defines get executortype func
   117  func (d *DriverBase) GetExecutorType() types.ExecutorType {
   118  	return d.ety
   119  }
   120  
   121  //ExecutorOrder 执行顺序, 如果要使用 ExecLocalSameTime
   122  //那么会同时执行 ExecLocal
   123  func (d *DriverBase) ExecutorOrder() int64 {
   124  	return 0
   125  }
   126  
   127  //GetLastHash 获取最后区块的hash,主链和平行链不同
   128  func (d *DriverBase) GetLastHash() []byte {
   129  	types.AssertConfig(d.api)
   130  	cfg := d.api.GetConfig()
   131  	if cfg.IsPara() {
   132  		return d.mainHash
   133  	}
   134  	return d.parentHash
   135  }
   136  
   137  //GetParentHash 获取上一个区块的hash
   138  func (d *DriverBase) GetParentHash() []byte {
   139  	return d.parentHash
   140  }
   141  
   142  // GetFuncMap defines get execfuncmap func
   143  func (d *DriverBase) GetFuncMap() map[string]reflect.Method {
   144  	if d.ety == nil {
   145  		return nil
   146  	}
   147  	return d.ety.GetExecFuncMap()
   148  }
   149  
   150  // SetAPI set queue protocol api
   151  func (d *DriverBase) SetAPI(queueapi client.QueueProtocolAPI) {
   152  	d.api = queueapi
   153  }
   154  
   155  // SetExecutorAPI set queue protocol api
   156  func (d *DriverBase) SetExecutorAPI(queueapi client.QueueProtocolAPI, turingchainapi types.TuringchainClient) {
   157  	d.execapi = api.New(queueapi, turingchainapi)
   158  }
   159  
   160  // GetAPI return queue protocol api
   161  func (d *DriverBase) GetAPI() client.QueueProtocolAPI {
   162  	return d.api
   163  }
   164  
   165  // GetExecutorAPI return executor api
   166  func (d *DriverBase) GetExecutorAPI() api.ExecutorAPI {
   167  	return d.execapi
   168  }
   169  
   170  // SetEnv set env
   171  func (d *DriverBase) SetEnv(height, blocktime int64, difficulty uint64) {
   172  	d.height = height
   173  	d.blocktime = blocktime
   174  	d.difficulty = difficulty
   175  }
   176  
   177  //SetBlockInfo 设置区块的信息
   178  func (d *DriverBase) SetBlockInfo(parentHash, mainHash []byte, mainHeight int64) {
   179  	d.parentHash = parentHash
   180  	d.mainHash = mainHash
   181  	d.mainHeight = mainHeight
   182  }
   183  
   184  // SetIsFree set isfree
   185  func (d *DriverBase) SetIsFree(isFree bool) {
   186  	d.isFree = isFree
   187  }
   188  
   189  // IsFree return isfree
   190  func (d *DriverBase) IsFree() bool {
   191  	return d.isFree
   192  }
   193  
   194  // SetExecutorType set exectortype
   195  func (d *DriverBase) SetExecutorType(e types.ExecutorType) {
   196  	d.ety = e
   197  }
   198  
   199  // SetChild set childvalue
   200  func (d *DriverBase) SetChild(e Driver) {
   201  	d.child = e
   202  	d.childValue = reflect.ValueOf(e)
   203  }
   204  
   205  // ExecLocal local exec
   206  func (d *DriverBase) ExecLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
   207  	lset, err := d.callLocal("ExecLocal_", tx, receipt, index)
   208  	if err != nil || lset == nil { // 不能向上层返回LocalDBSet为nil, 以及error
   209  		blog.Debug("call ExecLocal", "tx.Execer", string(tx.Execer), "err", err)
   210  		return &types.LocalDBSet{}, nil
   211  	}
   212  	return lset, nil
   213  }
   214  
   215  // ExecDelLocal local execdel
   216  func (d *DriverBase) ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
   217  	lset, err := d.callLocal("ExecDelLocal_", tx, receipt, index)
   218  	if err != nil || lset == nil { // 不能向上层返回LocalDBSet为nil, 以及error
   219  		blog.Error("call ExecDelLocal", "execer", string(tx.Execer), "err", err)
   220  		return &types.LocalDBSet{}, nil
   221  	}
   222  	return lset, nil
   223  }
   224  
   225  func (d *DriverBase) callLocal(prefix string, tx *types.Transaction, receipt *types.ReceiptData, index int) (set *types.LocalDBSet, err error) {
   226  	if d.ety == nil {
   227  		return nil, types.ErrActionNotSupport
   228  	}
   229  
   230  	if d.child.CheckReceiptExecOk() {
   231  		if receipt.GetTy() != types.ExecOk {
   232  			return &types.LocalDBSet{}, nil
   233  		}
   234  	}
   235  
   236  	defer func() {
   237  		if r := recover(); r != nil {
   238  			blog.Error("call localexec error", "prefix", prefix, "tx.exec", string(tx.Execer), "info", r)
   239  			err = types.ErrActionNotSupport
   240  			set = nil
   241  		}
   242  	}()
   243  	name, value, err := d.ety.DecodePayloadValue(tx)
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  	//call action
   248  	funcname := prefix + name
   249  	funcmap := d.child.GetFuncMap()
   250  	if _, ok := funcmap[funcname]; !ok {
   251  		return nil, types.ErrActionNotSupport
   252  	}
   253  	valueret := funcmap[funcname].Func.Call([]reflect.Value{d.childValue, value, reflect.ValueOf(tx), reflect.ValueOf(receipt), reflect.ValueOf(index)})
   254  	if !types.IsOK(valueret, 2) {
   255  		return nil, types.ErrMethodReturnType
   256  	}
   257  	r1 := valueret[0].Interface()
   258  	if r1 != nil {
   259  		if r, ok := r1.(*types.LocalDBSet); ok {
   260  			set = r
   261  		} else {
   262  			return nil, types.ErrMethodReturnType
   263  		}
   264  	}
   265  	r2 := valueret[1].Interface()
   266  	err = nil
   267  	if r2 != nil {
   268  		if r, ok := r2.(error); ok {
   269  			err = r
   270  		} else {
   271  			return nil, types.ErrMethodReturnType
   272  		}
   273  	}
   274  	return set, err
   275  }
   276  
   277  // CheckAddress check address
   278  func CheckAddress(cfg *types.TuringchainConfig, addr string, height int64) error {
   279  	if IsDriverAddress(addr, height) {
   280  		return nil
   281  	}
   282  	err := address.CheckAddress(addr)
   283  	if !cfg.IsFork(height, "ForkMultiSignAddress") && err == address.ErrCheckVersion {
   284  		return nil
   285  	}
   286  	if !cfg.IsFork(height, "ForkBase58AddressCheck") && err == address.ErrAddressChecksum {
   287  		return nil
   288  	}
   289  
   290  	return err
   291  }
   292  
   293  // Exec call the check exectx subclass, you can also do it without calling , implement your own checktx
   294  func (d *DriverBase) Exec(tx *types.Transaction, index int) (receipt *types.Receipt, err error) {
   295  	if d.ety == nil {
   296  		return nil, nil
   297  	}
   298  	defer func() {
   299  		if r := recover(); r != nil {
   300  			blog.Error("call exec error", "tx.exec", string(tx.Execer), "info", r)
   301  			err = types.ErrActionNotSupport
   302  			receipt = nil
   303  		}
   304  	}()
   305  	//为了兼容原来的系统,多加了一个判断
   306  	if d.child.GetPayloadValue() == nil {
   307  		return nil, nil
   308  	}
   309  	if d.ety == nil {
   310  		return nil, nil
   311  	}
   312  	name, value, err := d.ety.DecodePayloadValue(tx)
   313  	if err != nil {
   314  		return nil, err
   315  	}
   316  	funcmap := d.child.GetFuncMap()
   317  	funcname := "Exec_" + name
   318  	if _, ok := funcmap[funcname]; !ok {
   319  		return nil, types.ErrActionNotSupport
   320  	}
   321  	valueret := funcmap[funcname].Func.Call([]reflect.Value{d.childValue, value, reflect.ValueOf(tx), reflect.ValueOf(index)})
   322  	if !types.IsOK(valueret, 2) {
   323  		return nil, types.ErrMethodReturnType
   324  	}
   325  	//parameter 1
   326  	r1 := valueret[0].Interface()
   327  	if r1 != nil {
   328  		if r, ok := r1.(*types.Receipt); ok {
   329  			receipt = r
   330  		} else {
   331  			return nil, types.ErrMethodReturnType
   332  		}
   333  	}
   334  	//parameter 2
   335  	r2 := valueret[1].Interface()
   336  	err = nil
   337  	if r2 != nil {
   338  		if r, ok := r2.(error); ok {
   339  			err = r
   340  		} else {
   341  			return nil, types.ErrMethodReturnType
   342  		}
   343  	}
   344  	return receipt, err
   345  }
   346  
   347  // CheckTx  default:,tx.To address points to the contract address
   348  func (d *DriverBase) CheckTx(tx *types.Transaction, index int) error {
   349  	execer := string(tx.Execer)
   350  	if ExecAddress(execer) != tx.To {
   351  		return types.ErrToAddrNotSameToExecAddr
   352  	}
   353  	return nil
   354  }
   355  
   356  // SetStateDB set db state
   357  func (d *DriverBase) SetStateDB(db dbm.KV) {
   358  	if d.coinsaccount == nil {
   359  		//log.Error("new CoinsAccount")
   360  		types.AssertConfig(d.api)
   361  		d.coinsaccount = account.NewCoinsAccount(d.api.GetConfig())
   362  	}
   363  	d.statedb = db
   364  	d.coinsaccount.SetDB(db)
   365  }
   366  
   367  // GetTxGroup get txgroup
   368  func (d *DriverBase) GetTxGroup(index int) ([]*types.Transaction, error) {
   369  	if len(d.txs) <= index {
   370  		return nil, types.ErrTxGroupIndex
   371  	}
   372  	tx := d.txs[index]
   373  	c := int(tx.GroupCount)
   374  	if c <= 0 || c > int(types.MaxTxGroupSize) {
   375  		return nil, types.ErrTxGroupCount
   376  	}
   377  	types.AssertConfig(d.api)
   378  	cfg := d.api.GetConfig()
   379  	for i := index; i >= 0 && i >= index-c; i-- {
   380  		if bytes.Equal(d.txs[i].Header, d.txs[i].Hash()) { //find header
   381  			txgroup := types.Transactions{Txs: d.txs[i : i+c]}
   382  			err := txgroup.Check(cfg, d.GetHeight(), cfg.GetMinTxFeeRate(), cfg.GetMaxTxFee())
   383  			if err != nil {
   384  				return nil, err
   385  			}
   386  			return txgroup.Txs, nil
   387  		}
   388  	}
   389  	return nil, types.ErrTxGroupFormat
   390  }
   391  
   392  // GetReceipt return receipts
   393  func (d *DriverBase) GetReceipt() []*types.ReceiptData {
   394  	return d.receipts
   395  }
   396  
   397  // SetReceipt set receipt
   398  func (d *DriverBase) SetReceipt(receipts []*types.ReceiptData) {
   399  	d.receipts = receipts
   400  }
   401  
   402  // GetStateDB set statedb
   403  func (d *DriverBase) GetStateDB() dbm.KV {
   404  	return d.statedb
   405  }
   406  
   407  // SetLocalDB set localdb
   408  func (d *DriverBase) SetLocalDB(db dbm.KVDB) {
   409  	d.localdb = db
   410  }
   411  
   412  // GetLocalDB return localdb
   413  func (d *DriverBase) GetLocalDB() dbm.KVDB {
   414  	return d.localdb
   415  }
   416  
   417  // GetHeight return height
   418  func (d *DriverBase) GetHeight() int64 {
   419  	return d.height
   420  }
   421  
   422  // GetMainHeight return height
   423  func (d *DriverBase) GetMainHeight() int64 {
   424  	types.AssertConfig(d.api)
   425  	if d.api.GetConfig().IsPara() {
   426  		return d.mainHeight
   427  	}
   428  	return d.height
   429  }
   430  
   431  // GetBlockTime return block time
   432  func (d *DriverBase) GetBlockTime() int64 {
   433  	return d.blocktime
   434  }
   435  
   436  // GetDifficulty return difficulty
   437  func (d *DriverBase) GetDifficulty() uint64 {
   438  	return d.difficulty
   439  }
   440  
   441  // GetName defines return name func
   442  func (d *DriverBase) GetName() string {
   443  	if d.name == "" {
   444  		return d.child.GetDriverName()
   445  	}
   446  	return d.name
   447  }
   448  
   449  // GetCurrentExecName defines get current execname
   450  func (d *DriverBase) GetCurrentExecName() string {
   451  	if d.curname == "" {
   452  		return d.child.GetDriverName()
   453  	}
   454  	return d.curname
   455  }
   456  
   457  // SetName set name
   458  func (d *DriverBase) SetName(name string) {
   459  	d.name = name
   460  }
   461  
   462  // SetCurrentExecName set current execname
   463  func (d *DriverBase) SetCurrentExecName(name string) {
   464  	d.curname = name
   465  }
   466  
   467  // GetActionName get action name
   468  func (d *DriverBase) GetActionName(tx *types.Transaction) string {
   469  	return tx.ActionName()
   470  }
   471  
   472  // CheckSignatureData check signature data
   473  func (d *DriverBase) CheckSignatureData(tx *types.Transaction, index int) bool {
   474  	return true
   475  }
   476  
   477  // SetCoinsAccount sets coins account.
   478  func (d *DriverBase) SetCoinsAccount(acc *account.DB) {
   479  	d.coinsaccount = acc
   480  }
   481  
   482  // GetCoinsAccount get coins account
   483  func (d *DriverBase) GetCoinsAccount() *account.DB {
   484  	if d.coinsaccount == nil {
   485  		types.AssertConfig(d.api)
   486  		d.coinsaccount = account.NewCoinsAccount(d.api.GetConfig())
   487  		d.coinsaccount.SetDB(d.statedb)
   488  	}
   489  	return d.coinsaccount
   490  }
   491  
   492  // GetTxs get transactions
   493  func (d *DriverBase) GetTxs() []*types.Transaction {
   494  	return d.txs
   495  }
   496  
   497  // SetTxs set transactions
   498  func (d *DriverBase) SetTxs(txs []*types.Transaction) {
   499  	d.txs = txs
   500  }
   501  
   502  // CheckReceiptExecOk default return true to check if receipt ty is ok, for specific plugin can overwrite it self
   503  func (d *DriverBase) CheckReceiptExecOk() bool {
   504  	return false
   505  }
   506  
   507  //AddRollbackKV add rollback kv
   508  func (d *DriverBase) AddRollbackKV(tx *types.Transaction, execer []byte, kvs []*types.KeyValue) []*types.KeyValue {
   509  	k := types.CalcRollbackKey(types.GetRealExecName(execer), tx.Hash())
   510  	kvc := NewKVCreator(d.GetLocalDB(), types.CalcLocalPrefix(execer), k)
   511  	kvc.AddListNoPrefix(kvs)
   512  	kvc.AddRollbackKV()
   513  	return kvc.KVList()
   514  }
   515  
   516  //DelRollbackKV del rollback kv when exec_del_local
   517  func (d *DriverBase) DelRollbackKV(tx *types.Transaction, execer []byte) ([]*types.KeyValue, error) {
   518  	krollback := types.CalcRollbackKey(types.GetRealExecName(execer), tx.Hash())
   519  	kvc := NewKVCreator(d.GetLocalDB(), types.CalcLocalPrefix(execer), krollback)
   520  	kvs, err := kvc.GetRollbackKVList()
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  	for _, kv := range kvs {
   525  		kvc.AddNoPrefix(kv.Key, kv.Value)
   526  	}
   527  	kvc.DelRollbackKV()
   528  	return kvc.KVList(), nil
   529  }