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 }