github.com/aergoio/aergo@v1.3.1/chain/chainhandle.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package chain 7 8 import ( 9 "bytes" 10 "container/list" 11 "encoding/json" 12 "errors" 13 "fmt" 14 "math/big" 15 16 "github.com/aergoio/aergo/consensus" 17 "github.com/aergoio/aergo/contract" 18 "github.com/aergoio/aergo/contract/name" 19 "github.com/aergoio/aergo/internal/common" 20 "github.com/aergoio/aergo/internal/enc" 21 "github.com/aergoio/aergo/message" 22 "github.com/aergoio/aergo/state" 23 "github.com/aergoio/aergo/types" 24 "github.com/golang/protobuf/proto" 25 ) 26 27 var ( 28 ErrorNoAncestor = errors.New("not found ancestor") 29 ErrBlockOrphan = errors.New("block is ohphan, so not connected in chain") 30 ErrBlockCachedErrLRU = errors.New("block is in errored blocks cache") 31 ErrStateNoMarker = errors.New("statedb marker of block is not exists") 32 33 errBlockStale = errors.New("produced block becomes stale") 34 errBlockInvalidFork = errors.New("invalid fork occured") 35 errBlockTimestamp = errors.New("invalid timestamp") 36 37 InAddBlock = make(chan struct{}, 1) 38 ) 39 40 type ErrReorg struct { 41 err error 42 } 43 44 func (ec *ErrReorg) Error() string { 45 return fmt.Sprintf("reorg failed. maybe need reconfiguration. error: %s", ec.err.Error()) 46 } 47 48 type ErrBlock struct { 49 err error 50 block *types.BlockInfo 51 } 52 53 func (ec *ErrBlock) Error() string { 54 return fmt.Sprintf("Error: %s. block(%s, %d)", ec.err.Error(), enc.ToString(ec.block.Hash), ec.block.No) 55 } 56 57 type ErrTx struct { 58 err error 59 tx *types.Tx 60 } 61 62 func (ec *ErrTx) Error() string { 63 return fmt.Sprintf("error executing tx:%s, tx=%s", ec.err.Error(), enc.ToString(ec.tx.GetHash())) 64 } 65 66 func (cs *ChainService) getBestBlockNo() types.BlockNo { 67 return cs.cdb.getBestBlockNo() 68 } 69 70 // GetGenesisInfo returns the information on the genesis block. 71 func (cs *ChainService) GetGenesisInfo() *types.Genesis { 72 return cs.cdb.GetGenesisInfo() 73 } 74 75 func (cs *ChainService) GetBestBlock() (*types.Block, error) { 76 return cs.cdb.GetBestBlock() 77 } 78 79 func (cs *ChainService) getBlockByNo(blockNo types.BlockNo) (*types.Block, error) { 80 return cs.cdb.GetBlockByNo(blockNo) 81 } 82 83 func (cs *ChainService) GetBlock(blockHash []byte) (*types.Block, error) { 84 return cs.getBlock(blockHash) 85 } 86 87 func (cs *ChainService) getBlock(blockHash []byte) (*types.Block, error) { 88 return cs.cdb.getBlock(blockHash) 89 } 90 91 func (cs *ChainService) GetHashByNo(blockNo types.BlockNo) ([]byte, error) { 92 return cs.getHashByNo(blockNo) 93 } 94 95 func (cs *ChainService) getHashByNo(blockNo types.BlockNo) ([]byte, error) { 96 return cs.cdb.getHashByNo(blockNo) 97 } 98 99 func (cs *ChainService) getTx(txHash []byte) (*types.Tx, *types.TxIdx, error) { 100 tx, txidx, err := cs.cdb.getTx(txHash) 101 if err != nil { 102 return nil, nil, err 103 } 104 block, err := cs.cdb.getBlock(txidx.BlockHash) 105 blockInMainChain, err := cs.cdb.GetBlockByNo(block.Header.BlockNo) 106 if !bytes.Equal(block.BlockHash(), blockInMainChain.BlockHash()) { 107 return tx, nil, errors.New("tx is not in the main chain") 108 } 109 return tx, txidx, err 110 } 111 112 func (cs *ChainService) getReceipt(txHash []byte) (*types.Receipt, error) { 113 tx, i, err := cs.cdb.getTx(txHash) 114 if err != nil { 115 return nil, err 116 } 117 118 block, err := cs.cdb.getBlock(i.BlockHash) 119 blockInMainChain, err := cs.cdb.GetBlockByNo(block.Header.BlockNo) 120 if !bytes.Equal(block.BlockHash(), blockInMainChain.BlockHash()) { 121 return nil, errors.New("cannot find a receipt") 122 } 123 124 r, err := cs.cdb.getReceipt(block.BlockHash(), block.GetHeader().BlockNo, i.Idx) 125 if err != nil { 126 return r, err 127 } 128 r.ContractAddress = types.AddressOrigin(r.ContractAddress) 129 r.From = tx.GetBody().GetAccount() 130 r.To = tx.GetBody().GetRecipient() 131 return r, nil 132 } 133 134 func (cs *ChainService) getEvents(events *[]*types.Event, blkNo types.BlockNo, filter *types.FilterInfo, 135 argFilter []types.ArgFilter) uint64 { 136 blkHash, err := cs.cdb.getHashByNo(blkNo) 137 if err != nil { 138 return 0 139 } 140 receipts, err := cs.cdb.getReceipts(blkHash, blkNo) 141 if err != nil { 142 return 0 143 } 144 if receipts.BloomFilter(filter) == false { 145 return 0 146 } 147 var totalSize uint64 148 for idx, r := range receipts.Get() { 149 if r.BloomFilter(filter) == false { 150 continue 151 } 152 for _, e := range r.Events { 153 if e.Filter(filter, argFilter) { 154 e.SetMemoryInfo(r, blkHash, blkNo, int32(idx)) 155 *events = append(*events, e) 156 totalSize += uint64(proto.Size(e)) 157 } 158 } 159 } 160 return totalSize 161 } 162 163 const MaxEventSize = 4 * 1024 * 1024 164 165 func (cs *ChainService) listEvents(filter *types.FilterInfo) ([]*types.Event, error) { 166 from := filter.Blockfrom 167 to := filter.Blockto 168 169 if filter.RecentBlockCnt > 0 { 170 to = cs.cdb.getBestBlockNo() 171 if to <= uint64(filter.RecentBlockCnt) { 172 from = 0 173 } else { 174 from = to - uint64(filter.RecentBlockCnt) 175 } 176 } else { 177 if to == 0 { 178 to = cs.cdb.getBestBlockNo() 179 } 180 } 181 err := filter.ValidateCheck(to) 182 if err != nil { 183 return nil, err 184 } 185 argFilter, err := filter.GetExArgFilter() 186 if err != nil { 187 return nil, err 188 } 189 events := []*types.Event{} 190 var totalSize uint64 191 if filter.Desc { 192 for i := to; i >= from && i != 0; i-- { 193 totalSize += cs.getEvents(&events, types.BlockNo(i), filter, argFilter) 194 if totalSize > MaxEventSize { 195 return nil, errors.New(fmt.Sprintf("too large size of event (%v)", totalSize)) 196 } 197 } 198 } else { 199 for i := from; i <= to; i++ { 200 totalSize += cs.getEvents(&events, types.BlockNo(i), filter, argFilter) 201 if totalSize > MaxEventSize { 202 return nil, errors.New(fmt.Sprintf("too large size of event (%v)", totalSize)) 203 } 204 } 205 } 206 return events, nil 207 } 208 209 type chainProcessor struct { 210 *ChainService 211 block *types.Block // starting block 212 lastBlock *types.Block 213 state *state.BlockState 214 mainChain *list.List 215 isByBP bool 216 isMainChain bool 217 218 add func(blk *types.Block) error 219 apply func(blk *types.Block) error 220 run func() error 221 } 222 223 func newChainProcessor(block *types.Block, state *state.BlockState, cs *ChainService) (*chainProcessor, error) { 224 var isMainChain bool 225 var err error 226 227 if isMainChain, err = cs.cdb.isMainChain(block); err != nil { 228 return nil, err 229 } 230 231 cp := &chainProcessor{ 232 ChainService: cs, 233 block: block, 234 state: state, 235 isByBP: (state != nil), 236 isMainChain: isMainChain, 237 } 238 239 if cp.isMainChain { 240 cp.apply = cp.execute 241 } else { 242 cp.apply = cp.addBlock 243 } 244 245 if cp.isByBP { 246 cp.run = func() error { 247 blk := cp.block 248 cp.notifyBlockByBP(blk) 249 return cp.apply(blk) 250 } 251 } else { 252 cp.run = func() error { 253 blk := cp.block 254 255 for blk != nil { 256 if err = cp.apply(blk); err != nil { 257 return err 258 } 259 260 // Remove a block depnding on blk from the orphan cache. 261 if blk, err = cp.resolveOrphan(blk); err != nil { 262 return err 263 } 264 } 265 return nil 266 } 267 } 268 269 return cp, nil 270 } 271 272 func (cp *chainProcessor) addBlock(blk *types.Block) error { 273 dbTx := cp.cdb.store.NewTx() 274 defer dbTx.Discard() 275 276 if err := cp.cdb.addBlock(dbTx, blk); err != nil { 277 return err 278 } 279 280 dbTx.Commit() 281 282 if logger.IsDebugEnabled() { 283 logger.Debug().Bool("isMainChain", cp.isMainChain). 284 Uint64("latest", cp.cdb.getBestBlockNo()). 285 Uint64("blockNo", blk.BlockNo()). 286 Str("hash", blk.ID()). 287 Str("prev_hash", enc.ToString(blk.GetHeader().GetPrevBlockHash())). 288 Msg("block added to the block indices") 289 } 290 cp.lastBlock = blk 291 292 return nil 293 } 294 295 func (cp *chainProcessor) notifyBlockByBP(block *types.Block) { 296 if cp.isByBP { 297 cp.notifyBlock(block, true) 298 } 299 } 300 301 func (cp *chainProcessor) notifyBlockByOther(block *types.Block) { 302 if !cp.isByBP { 303 logger.Debug().Msg("notify block from other bp") 304 cp.notifyBlock(block, false) 305 } 306 } 307 308 func checkDebugSleep(isBP bool) { 309 if isBP { 310 _ = TestDebugger.Check(DEBUG_CHAIN_BP_SLEEP, 0, nil) 311 } else { 312 _ = TestDebugger.Check(DEBUG_CHAIN_OTHER_SLEEP, 0, nil) 313 } 314 } 315 316 func (cp *chainProcessor) executeBlock(block *types.Block) error { 317 checkDebugSleep(cp.isByBP) 318 319 err := cp.ChainService.executeBlock(cp.state, block) 320 cp.state = nil 321 return err 322 } 323 324 func (cp *chainProcessor) execute(block *types.Block) error { 325 if !cp.isMainChain { 326 return nil 327 } 328 329 var err error 330 331 err = cp.executeBlock(block) 332 if err != nil { 333 logger.Error().Str("error", err.Error()).Str("hash", block.ID()). 334 Msg("failed to execute block") 335 return err 336 } 337 //SyncWithConsensus :ga 338 // After executing MemPoolDel in the chain service, MemPoolGet must be executed on the consensus. 339 // To do this, cdb.setLatest() must be executed after MemPoolDel. 340 // In this case, messages of mempool is synchronized in actor message queue. 341 if _, err = cp.connectToChain(block); err != nil { 342 return err 343 } 344 345 cp.notifyBlockByOther(block) 346 347 return nil 348 } 349 350 func (cp *chainProcessor) connectToChain(block *types.Block) (types.BlockNo, error) { 351 dbTx := cp.cdb.store.NewTx() 352 defer dbTx.Discard() 353 354 // skip to add hash/block if wal of block is already written 355 oldLatest := cp.cdb.connectToChain(dbTx, block, cp.isByBP && cp.HasWAL()) 356 if err := cp.cdb.addTxsOfBlock(&dbTx, block.GetBody().GetTxs(), block.BlockHash()); err != nil { 357 return 0, err 358 } 359 360 dbTx.Commit() 361 362 return oldLatest, nil 363 } 364 365 func (cp *chainProcessor) reorganize() error { 366 // - Reorganize if new bestblock then process Txs 367 // - Add block if new bestblock then update context connect next orphan 368 if !cp.isMainChain && cp.needReorg(cp.lastBlock) { 369 err := cp.reorg(cp.lastBlock, nil) 370 if e, ok := err.(consensus.ErrorConsensus); ok { 371 logger.Info().Err(e).Msg("reorg stopped by consensus error") 372 return nil 373 } 374 375 if err != nil { 376 logger.Info().Err(err).Msg("reorg stopped by unexpected error") 377 return &ErrReorg{err: err} 378 } 379 } 380 381 return nil 382 } 383 384 func (cs *ChainService) addBlockInternal(newBlock *types.Block, usedBstate *state.BlockState, peerID types.PeerID) (err error, cache bool) { 385 if !cs.VerifyTimestamp(newBlock) { 386 return &ErrBlock{ 387 err: errBlockTimestamp, 388 block: &types.BlockInfo{ 389 Hash: newBlock.BlockHash(), 390 No: newBlock.BlockNo(), 391 }, 392 }, false 393 } 394 395 var ( 396 bestBlock *types.Block 397 savedBlock *types.Block 398 ) 399 400 if bestBlock, err = cs.cdb.GetBestBlock(); err != nil { 401 return err, false 402 } 403 404 // The newly produced block becomes stale because the more block(s) are 405 // connected to the blockchain so that the best block is changed. In this 406 // case, newBlock is rejected because it is unlikely that newBlock belongs 407 // to the main branch. Warning: the condition 'usedBstate != nil' is used 408 // to check whether newBlock is produced by the current node itself. Later, 409 // more explicit condition may be needed instead of this. 410 if usedBstate != nil && newBlock.PrevID() != bestBlock.ID() { 411 return &ErrBlock{ 412 err: errBlockStale, 413 block: &types.BlockInfo{ 414 Hash: newBlock.BlockHash(), 415 No: newBlock.BlockNo(), 416 }, 417 }, false 418 } 419 420 //Fork should never occur in raft. 421 checkFork := func(block *types.Block) error { 422 if cs.IsForkEnable() { 423 return nil 424 } 425 if usedBstate != nil { 426 return nil 427 } 428 429 savedBlock, err = cs.getBlockByNo(newBlock.GetHeader().GetBlockNo()) 430 if err == nil { 431 /* TODO change to error after testing */ 432 logger.Fatal().Str("newblock", newBlock.ID()).Str("savedblock", savedBlock.ID()).Msg("drop block making invalid fork") 433 return &ErrBlock{ 434 err: errBlockInvalidFork, 435 block: &types.BlockInfo{Hash: newBlock.BlockHash(), No: newBlock.BlockNo()}, 436 } 437 } 438 439 return nil 440 } 441 442 if err := checkFork(newBlock); err != nil { 443 return err, false 444 } 445 446 if !newBlock.ValidChildOf(bestBlock) { 447 return fmt.Errorf("invalid chain id - best: %v, current: %v", 448 bestBlock.GetHeader().GetChainID(), newBlock.GetHeader().GetChainID()), false 449 } 450 451 if err := cs.VerifySign(newBlock); err != nil { 452 return err, true 453 } 454 455 // handle orphan 456 if cs.isOrphan(newBlock) { 457 if usedBstate != nil { 458 return fmt.Errorf("block received from BP can not be orphan"), false 459 } 460 err := cs.handleOrphan(newBlock, bestBlock, peerID) 461 if err == nil { 462 return nil, false 463 } 464 465 return err, false 466 } 467 468 select { 469 case InAddBlock <- struct{}{}: 470 } 471 defer func() { 472 <-InAddBlock 473 }() 474 475 cp, err := newChainProcessor(newBlock, usedBstate, cs) 476 if err != nil { 477 return err, true 478 } 479 480 if err := cp.run(); err != nil { 481 return err, true 482 } 483 484 // TODO: reorganization should be done before chain execution to avoid an 485 // unnecessary chain execution & rollback. 486 if err := cp.reorganize(); err != nil { 487 return err, true 488 } 489 490 logger.Info().Uint64("best", cs.cdb.getBestBlockNo()).Msg("Block added successfully") 491 492 return nil, true 493 } 494 495 func (cs *ChainService) addBlock(newBlock *types.Block, usedBstate *state.BlockState, peerID types.PeerID) error { 496 hashID := types.ToHashID(newBlock.BlockHash()) 497 498 if cs.errBlocks.Contains(hashID) { 499 return ErrBlockCachedErrLRU 500 } 501 502 var err error 503 504 if cs.IsConnectedBlock(newBlock) { 505 logger.Warn().Str("hash", newBlock.ID()).Uint64("no", newBlock.BlockNo()).Msg("block is already connected") 506 return nil 507 } 508 509 var needCache bool 510 err, needCache = cs.addBlockInternal(newBlock, usedBstate, peerID) 511 if err != nil { 512 if needCache { 513 evicted := cs.errBlocks.Add(hashID, newBlock) 514 logger.Error().Err(err).Bool("evicted", evicted).Uint64("no", newBlock.GetHeader().BlockNo). 515 Str("hash", newBlock.ID()).Msg("add errored block to errBlocks lru") 516 } 517 // err must be returned regardless of the value of needCache. 518 return err 519 } 520 521 return nil 522 } 523 524 func (cs *ChainService) CountTxsInChain() int { 525 var txCount int 526 527 blk, err := cs.GetBestBlock() 528 if err != nil { 529 return -1 530 } 531 532 var no uint64 533 for { 534 no = blk.GetHeader().GetBlockNo() 535 if no == 0 { 536 break 537 } 538 539 txCount += len(blk.GetBody().GetTxs()) 540 541 blk, err = cs.getBlock(blk.GetHeader().GetPrevBlockHash()) 542 if err != nil { 543 txCount = -1 544 break 545 } 546 } 547 548 return txCount 549 } 550 551 type TxExecFn func(bState *state.BlockState, tx types.Transaction) error 552 type ValidatePostFn func() error 553 type ValidateSignWaitFn func() error 554 555 type blockExecutor struct { 556 *state.BlockState 557 sdb *state.ChainStateDB 558 execTx TxExecFn 559 txs []*types.Tx 560 validatePost ValidatePostFn 561 coinbaseAcccount []byte 562 commitOnly bool 563 verifyOnly bool 564 validateSignWait ValidateSignWaitFn 565 } 566 567 func newBlockExecutor(cs *ChainService, bState *state.BlockState, block *types.Block, verifyOnly bool) (*blockExecutor, error) { 568 var exec TxExecFn 569 var validateSignWait ValidateSignWaitFn 570 571 commitOnly := false 572 573 // The DPoS block factory excutes transactions during block generation. In 574 // such a case it send block with block state so that bState != nil. On the 575 // contrary, the block propagated from the network is not half-executed. 576 // Hence we need a new block state and tx executor (execTx). 577 if bState == nil { 578 if err := cs.validator.ValidateBlock(block); err != nil { 579 return nil, err 580 } 581 582 bState = state.NewBlockState(cs.sdb.OpenNewStateDB(cs.sdb.GetRoot())) 583 584 exec = NewTxExecutor(cs.ChainConsensus, cs.cdb, block.BlockNo(), block.GetHeader().GetTimestamp(), block.GetHeader().GetPrevBlockHash(), contract.ChainService, block.GetHeader().ChainID) 585 586 validateSignWait = func() error { 587 return cs.validator.WaitVerifyDone() 588 } 589 } else { 590 logger.Debug().Uint64("block no", block.BlockNo()).Msg("received block from block factory") 591 // In this case (bState != nil), the transactions has already been 592 // executed by the block factory. 593 commitOnly = true 594 } 595 596 return &blockExecutor{ 597 BlockState: bState, 598 sdb: cs.sdb, 599 execTx: exec, 600 txs: block.GetBody().GetTxs(), 601 coinbaseAcccount: block.GetHeader().GetCoinbaseAccount(), 602 validatePost: func() error { 603 return cs.validator.ValidatePost(bState.GetRoot(), bState.Receipts(), block) 604 }, 605 commitOnly: commitOnly, 606 verifyOnly: verifyOnly, 607 validateSignWait: validateSignWait, 608 }, nil 609 } 610 611 // NewTxExecutor returns a new TxExecFn. 612 func NewTxExecutor(ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, blockNo types.BlockNo, ts int64, prevBlockHash []byte, preLoadService int, chainID []byte) TxExecFn { 613 return func(bState *state.BlockState, tx types.Transaction) error { 614 if bState == nil { 615 logger.Error().Msg("bstate is nil in txexec") 616 return ErrGatherChain 617 } 618 snapshot := bState.Snapshot() 619 620 err := executeTx(ccc, cdb, bState, tx, blockNo, ts, prevBlockHash, preLoadService, common.Hasher(chainID)) 621 if err != nil { 622 logger.Error().Err(err).Str("hash", enc.ToString(tx.GetHash())).Msg("tx failed") 623 if err2 := bState.Rollback(snapshot); err2 != nil { 624 logger.Panic().Err(err).Msg("faield to rollback block state") 625 } 626 627 return err 628 } 629 return nil 630 } 631 } 632 633 func (e *blockExecutor) execute() error { 634 // Receipt must be committed unconditionally. 635 if !e.commitOnly { 636 defer contract.CloseDatabase() 637 var preLoadTx *types.Tx 638 nCand := len(e.txs) 639 for i, tx := range e.txs { 640 if i != nCand-1 { 641 preLoadTx = e.txs[i+1] 642 contract.PreLoadRequest(e.BlockState, preLoadTx, tx, contract.ChainService) 643 } 644 if err := e.execTx(e.BlockState, types.NewTransaction(tx)); err != nil { 645 //FIXME maybe system error. restart or panic 646 // all txs have executed successfully in BP node 647 return err 648 } 649 contract.SetPreloadTx(preLoadTx, contract.ChainService) 650 } 651 652 if e.validateSignWait != nil { 653 if err := e.validateSignWait(); err != nil { 654 return err 655 } 656 } 657 658 //TODO check result of verifing txs 659 if err := SendRewardCoinbase(e.BlockState, e.coinbaseAcccount); err != nil { 660 return err 661 } 662 663 if err := contract.SaveRecoveryPoint(e.BlockState); err != nil { 664 return err 665 } 666 667 if err := e.Update(); err != nil { 668 return err 669 } 670 } 671 672 if err := e.validatePost(); err != nil { 673 return err 674 } 675 676 // TODO: sync status of bstate and cdb what to do if cdb.commit fails after 677 678 if !e.verifyOnly { 679 if err := e.commit(); err != nil { 680 return err 681 } 682 } 683 684 logger.Debug().Msg("block executor finished") 685 return nil 686 } 687 688 func (e *blockExecutor) commit() error { 689 if err := e.BlockState.Commit(); err != nil { 690 return err 691 } 692 693 //TODO: after implementing BlockRootHash, remove statedb.lastest 694 if err := e.sdb.UpdateRoot(e.BlockState); err != nil { 695 return err 696 } 697 698 return nil 699 } 700 701 // TODO: Refactoring: batch 702 func (cs *ChainService) executeBlock(bstate *state.BlockState, block *types.Block) error { 703 // Caution: block must belong to the main chain. 704 logger.Debug().Str("hash", block.ID()).Uint64("no", block.GetHeader().BlockNo).Msg("start to execute") 705 706 var ( 707 bestBlock *types.Block 708 err error 709 ) 710 711 if bestBlock, err = cs.cdb.GetBestBlock(); err != nil { 712 return err 713 } 714 715 // Check consensus info validity 716 if err = cs.IsBlockValid(block, bestBlock); err != nil { 717 return err 718 } 719 720 // TODO refactoring: receive execute function as argument (executeBlock or executeBlockReco) 721 ex, err := newBlockExecutor(cs, bstate, block, false) 722 if err != nil { 723 return err 724 } 725 726 // contract & state DB update is done during execution. 727 if err := ex.execute(); err != nil { 728 return err 729 } 730 731 if len(ex.BlockState.Receipts().Get()) != 0 { 732 cs.cdb.writeReceipts(block.BlockHash(), block.BlockNo(), ex.BlockState.Receipts()) 733 } 734 735 cs.notifyEvents(block, ex.BlockState) 736 737 cs.Update(block) 738 739 logger.Debug().Uint64("no", block.GetHeader().BlockNo).Msg("end to execute") 740 741 return nil 742 } 743 744 // verifyBlock execute block and verify state root but doesn't save data to database. 745 // ChainVerifier use this function. 746 func (cs *ChainService) verifyBlock(block *types.Block) error { 747 var ( 748 err error 749 ex *blockExecutor 750 ) 751 752 // Caution: block must belong to the main chain. 753 logger.Debug().Str("hash", block.ID()).Uint64("no", block.GetHeader().BlockNo).Msg("start to verify") 754 755 ex, err = newBlockExecutor(cs, nil, block, true) 756 if err != nil { 757 return err 758 } 759 760 // contract & state DB update is done during execution. 761 if err = ex.execute(); err != nil { 762 return err 763 } 764 765 // set root of sdb to block root hash 766 if err = cs.sdb.SetRoot(block.GetHeader().GetBlocksRootHash()); err != nil { 767 return fmt.Errorf("failed to set root of sdb(no=%d,hash=%v)", block.BlockNo(), block.ID()) 768 } 769 770 logger.Debug().Uint64("no", block.GetHeader().BlockNo).Msg("end verify") 771 772 return nil 773 } 774 775 // TODO: Refactoring: batch 776 func (cs *ChainService) executeBlockReco(_ *state.BlockState, block *types.Block) error { 777 // Caution: block must belong to the main chain. 778 logger.Debug().Str("hash", block.ID()).Uint64("no", block.GetHeader().BlockNo).Msg("start to execute for reco") 779 780 var ( 781 bestBlock *types.Block 782 err error 783 ) 784 785 if bestBlock, err = cs.cdb.GetBestBlock(); err != nil { 786 return err 787 } 788 789 // Check consensus info validity 790 // TODO remove bestblock 791 if err = cs.IsBlockValid(block, bestBlock); err != nil { 792 return err 793 } 794 795 if !cs.sdb.GetStateDB().HasMarker(block.GetHeader().GetBlocksRootHash()) { 796 logger.Error().Str("hash", block.ID()).Uint64("no", block.GetHeader().GetBlockNo()).Msg("state marker does not exist") 797 return ErrStateNoMarker 798 } 799 800 // move stateroot 801 if err := cs.sdb.SetRoot(block.GetHeader().GetBlocksRootHash()); err != nil { 802 return fmt.Errorf("failed to set sdb(branchRoot:no=%d,hash=%v)", block.GetHeader().GetBlockNo(), 803 block.ID()) 804 } 805 806 cs.Update(block) 807 808 logger.Debug().Uint64("no", block.GetHeader().BlockNo).Msg("end to execute for reco") 809 810 return nil 811 } 812 813 func (cs *ChainService) notifyEvents(block *types.Block, bstate *state.BlockState) { 814 blkNo := block.GetHeader().GetBlockNo() 815 blkHash := block.BlockHash() 816 817 logger.Debug().Uint64("no", blkNo).Msg("add event from executed block") 818 819 cs.RequestTo(message.MemPoolSvc, &message.MemPoolDel{ 820 Block: block, 821 }) 822 823 cs.TellTo(message.RPCSvc, block) 824 825 events := []*types.Event{} 826 for idx, receipt := range bstate.Receipts().Get() { 827 for _, e := range receipt.Events { 828 e.SetMemoryInfo(receipt, blkHash, blkNo, int32(idx)) 829 events = append(events, e) 830 } 831 } 832 833 if len(events) != 0 { 834 cs.TellTo(message.RPCSvc, events) 835 } 836 } 837 838 const maxRetSize = 1024 839 840 func adjustRv(ret string) string { 841 if len(ret) > maxRetSize { 842 modified, _ := json.Marshal(ret[:maxRetSize-4] + " ...") 843 844 return string(modified) 845 } 846 return ret 847 } 848 849 func executeTx(ccc consensus.ChainConsensusCluster, cdb contract.ChainAccessor, bs *state.BlockState, tx types.Transaction, blockNo uint64, ts int64, prevBlockHash []byte, preLoadService int, chainIDHash []byte) error { 850 851 txBody := tx.GetBody() 852 853 var account []byte 854 if tx.HasVerifedAccount() { 855 account = tx.GetVerifedAccount() 856 tx.RemoveVerifedAccount() 857 resolvedAccount := name.Resolve(bs, txBody.GetAccount()) 858 if !bytes.Equal(account, resolvedAccount) { 859 return types.ErrSignNotMatch 860 } 861 } else { 862 account = name.Resolve(bs, txBody.GetAccount()) 863 } 864 865 err := tx.Validate(chainIDHash, IsPublic()) 866 if err != nil { 867 return err 868 } 869 870 sender, err := bs.GetAccountStateV(account) 871 if err != nil { 872 return err 873 } 874 875 err = tx.ValidateWithSenderState(sender.State()) 876 if err != nil { 877 return err 878 } 879 880 recipient := name.Resolve(bs, txBody.Recipient) 881 var receiver *state.V 882 status := "SUCCESS" 883 if len(recipient) > 0 { 884 receiver, err = bs.GetAccountStateV(recipient) 885 if receiver != nil && txBody.Type == types.TxType_REDEPLOY { 886 status = "RECREATED" 887 receiver.SetRedeploy() 888 } 889 } else { 890 receiver, err = bs.CreateAccountStateV(contract.CreateContractID(txBody.Account, txBody.Nonce)) 891 status = "CREATED" 892 } 893 if err != nil { 894 return err 895 } 896 897 var txFee *big.Int 898 var rv string 899 var events []*types.Event 900 switch txBody.Type { 901 case types.TxType_NORMAL, types.TxType_REDEPLOY: 902 rv, events, txFee, err = contract.Execute(bs, cdb, tx.GetTx(), blockNo, ts, prevBlockHash, sender, receiver, preLoadService) 903 sender.SubBalance(txFee) 904 case types.TxType_GOVERNANCE: 905 txFee = new(big.Int).SetUint64(0) 906 events, err = executeGovernanceTx(ccc, bs, txBody, sender, receiver, blockNo) 907 if err != nil { 908 logger.Warn().Err(err).Str("txhash", enc.ToString(tx.GetHash())).Msg("governance tx Error") 909 } 910 } 911 912 if err != nil { 913 if !contract.IsRuntimeError(err) { 914 return err 915 } 916 sender.Reset() 917 sender.SubBalance(txFee) 918 sender.SetNonce(txBody.Nonce) 919 sErr := sender.PutState() 920 if sErr != nil { 921 return sErr 922 } 923 status = "ERROR" 924 rv = err.Error() 925 } else { 926 sender.SetNonce(txBody.Nonce) 927 err = sender.PutState() 928 if err != nil { 929 return err 930 } 931 if sender.AccountID() != receiver.AccountID() { 932 err = receiver.PutState() 933 if err != nil { 934 return err 935 } 936 } 937 rv = adjustRv(rv) 938 } 939 bs.BpReward = new(big.Int).Add(new(big.Int).SetBytes(bs.BpReward), txFee).Bytes() 940 941 receipt := types.NewReceipt(receiver.ID(), status, rv) 942 receipt.FeeUsed = txFee.Bytes() 943 receipt.TxHash = tx.GetHash() 944 receipt.Events = events 945 946 return bs.AddReceipt(receipt) 947 } 948 949 func SendRewardCoinbase(bState *state.BlockState, coinbaseAccount []byte) error { 950 bpReward := new(big.Int).SetBytes(bState.BpReward) 951 if bpReward.Cmp(new(big.Int).SetUint64(0)) <= 0 || coinbaseAccount == nil { 952 logger.Debug().Str("reward", new(big.Int).SetBytes(bState.BpReward).String()).Msg("coinbase is skipped") 953 return nil 954 } 955 956 receiverID := types.ToAccountID(coinbaseAccount) 957 receiverState, err := bState.GetAccountState(receiverID) 958 if err != nil { 959 return err 960 } 961 962 receiverChange := types.State(*receiverState) 963 receiverChange.Balance = new(big.Int).Add(receiverChange.GetBalanceBigInt(), bpReward).Bytes() 964 965 err = bState.PutState(receiverID, &receiverChange) 966 if err != nil { 967 return err 968 } 969 970 logger.Debug().Str("reward", bpReward.String()). 971 Str("newbalance", receiverChange.GetBalanceBigInt().String()).Msg("send reward to coinbase account") 972 973 return nil 974 } 975 976 // find an orphan block which is the child of the added block 977 func (cs *ChainService) resolveOrphan(block *types.Block) (*types.Block, error) { 978 hash := block.BlockHash() 979 980 orphanID := types.ToBlockID(hash) 981 orphan, exists := cs.op.cache[orphanID] 982 if !exists { 983 return nil, nil 984 } 985 986 orphanBlock := orphan.Block 987 988 if (block.GetHeader().GetBlockNo() + 1) != orphanBlock.GetHeader().GetBlockNo() { 989 return nil, fmt.Errorf("invalid orphan block no (p=%d, c=%d)", block.GetHeader().GetBlockNo(), 990 orphanBlock.GetHeader().GetBlockNo()) 991 } 992 993 logger.Info().Str("parent", block.ID()). 994 Str("orphan", orphanBlock.ID()). 995 Msg("connect orphan") 996 997 if err := cs.op.removeOrphan(orphanID); err != nil { 998 return nil, err 999 } 1000 1001 return orphanBlock, nil 1002 } 1003 1004 func (cs *ChainService) isOrphan(block *types.Block) bool { 1005 prevhash := block.Header.PrevBlockHash 1006 _, err := cs.getBlock(prevhash) 1007 1008 return err != nil 1009 } 1010 1011 func (cs *ChainService) handleOrphan(block *types.Block, bestBlock *types.Block, peerID types.PeerID) error { 1012 err := cs.addOrphan(block) 1013 if err != nil { 1014 logger.Error().Err(err).Str("hash", block.ID()).Msg("add orphan block failed") 1015 1016 return err 1017 } 1018 1019 cs.RequestTo(message.SyncerSvc, &message.SyncStart{PeerID: peerID, TargetNo: block.GetHeader().GetBlockNo()}) 1020 1021 return nil 1022 } 1023 1024 func (cs *ChainService) addOrphan(block *types.Block) error { 1025 return cs.op.addOrphan(block) 1026 } 1027 1028 func (cs *ChainService) findAncestor(Hashes [][]byte) (*types.BlockInfo, error) { 1029 // 1. check endpoint is on main chain (or, return nil) 1030 logger.Debug().Int("len", len(Hashes)).Msg("find ancestor") 1031 1032 var mainhash []byte 1033 var mainblock *types.Block 1034 var err error 1035 // 2. get the highest block of Hashes hash on main chain 1036 for _, hash := range Hashes { 1037 // need to be short 1038 mainblock, err = cs.cdb.getBlock(hash) 1039 if err != nil { 1040 mainblock = nil 1041 continue 1042 } 1043 // get main hash with same block height 1044 mainhash, err = cs.cdb.getHashByNo( 1045 types.BlockNo(mainblock.GetHeader().GetBlockNo())) 1046 if err != nil { 1047 mainblock = nil 1048 continue 1049 } 1050 1051 if bytes.Equal(mainhash, mainblock.BlockHash()) { 1052 break 1053 } 1054 mainblock = nil 1055 } 1056 1057 // TODO: handle the case that can't find the hash in main chain 1058 if mainblock == nil { 1059 logger.Debug().Msg("Can't search same ancestor") 1060 return nil, ErrorNoAncestor 1061 } 1062 1063 return &types.BlockInfo{Hash: mainblock.BlockHash(), No: mainblock.GetHeader().GetBlockNo()}, nil 1064 } 1065 1066 func (cs *ChainService) setSkipMempool(isSync bool) { 1067 //don't use mempool if sync is in progress 1068 cs.validator.signVerifier.SetSkipMempool(isSync) 1069 }