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: ©from, 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 }