(txs []*types.Transaction, index int)
| 365 | } |
| 366 | |
| 367 | func (e *executor) execTxGroup(txs []*types.Transaction, index int) ([]*types.Receipt, error) { |
| 368 | txgroup := &types.Transactions{Txs: txs} |
| 369 | err := e.checkTxGroup(txgroup, index) |
| 370 | if err != nil { |
| 371 | return nil, err |
| 372 | } |
| 373 | feelog, err := e.execFee(txs[0], index) |
| 374 | if err != nil { |
| 375 | return nil, err |
| 376 | } |
| 377 | //开启内存事务处理,假设系统只有一个thread 执行 |
| 378 | //如果系统执行失败,回滚到这个状态 |
| 379 | rollbackLog := copyReceipt(feelog) |
| 380 | e.begin() |
| 381 | receipts := make([]*types.Receipt, len(txs)) |
| 382 | for i := 1; i < len(txs); i++ { |
| 383 | receipts[i] = &types.Receipt{Ty: types.ExecPack} |
| 384 | } |
| 385 | receipts[0], err = e.execTxOne(feelog, txs[0], index) |
| 386 | if err != nil { |
| 387 | //接口临时错误,取消执行 |
| 388 | if api.IsAPIEnvError(err) { |
| 389 | return nil, err |
| 390 | } |
| 391 | //状态数据库回滚 |
| 392 | if e.cfg.IsFork(e.height, "ForkExecRollback") { |
| 393 | e.rollback() |
| 394 | } |
| 395 | return receipts, nil |
| 396 | } |
| 397 | for i := 1; i < len(txs); i++ { |
| 398 | //如果有一笔执行失败了,那么全部回滚 |
| 399 | receipts[i], err = e.execTxOne(receipts[i], txs[i], index+i) |
| 400 | if err != nil { |
| 401 | //reset other exec , and break! |
| 402 | if api.IsAPIEnvError(err) { |
| 403 | return nil, err |
| 404 | } |
| 405 | for k := 1; k < i; k++ { |
| 406 | receipts[k] = &types.Receipt{Ty: types.ExecPack} |
| 407 | } |
| 408 | //撤销txs[0]的交易 |
| 409 | if e.cfg.IsFork(e.height, "ForkResetTx0") { |
| 410 | receipts[0] = rollbackLog |
| 411 | } |
| 412 | //撤销所有的数据库更新 |
| 413 | e.rollback() |
| 414 | return receipts, nil |
| 415 | } |
| 416 | } |
| 417 | err = e.commit() |
| 418 | if err != nil { |
| 419 | return nil, err |
| 420 | } |
| 421 | return receipts, nil |
| 422 | } |
| 423 | |
| 424 | func (e *executor) loadFlag(key []byte) (int64, error) { |
no test coverage detected