github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/consensus/neatcon/engine.go (about)

     1  package neatcon
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"math/big"
     7  	"time"
     8  
     9  	lru "github.com/hashicorp/golang-lru"
    10  	"github.com/neatio-net/neatio/chain/consensus"
    11  	"github.com/neatio-net/neatio/chain/consensus/neatcon/epoch"
    12  	ntcTypes "github.com/neatio-net/neatio/chain/consensus/neatcon/types"
    13  	"github.com/neatio-net/neatio/chain/core/state"
    14  	"github.com/neatio-net/neatio/chain/core/types"
    15  	"github.com/neatio-net/neatio/network/rpc"
    16  	"github.com/neatio-net/neatio/params"
    17  	"github.com/neatio-net/neatio/utilities/common"
    18  	"github.com/neatio-net/wire-go"
    19  )
    20  
    21  const (
    22  	fetcherID = "neatcon"
    23  )
    24  
    25  var (
    26  	errInvalidProposal = errors.New("invalid proposal")
    27  
    28  	errInvalidSignature = errors.New("invalid signature")
    29  
    30  	errUnknownBlock = errors.New("unknown block")
    31  
    32  	errUnauthorized = errors.New("unauthorized")
    33  
    34  	errInvalidDifficulty = errors.New("invalid difficulty")
    35  
    36  	errInvalidExtraDataFormat = errors.New("invalid extra data format")
    37  
    38  	errInvalidMixDigest = errors.New("invalid NeatCon mix digest")
    39  
    40  	errInvalidNonce = errors.New("invalid nonce")
    41  
    42  	errInvalidUncleHash = errors.New("non empty uncle hash")
    43  
    44  	errInconsistentValidatorSet = errors.New("inconsistent validator set")
    45  
    46  	errInvalidTimestamp = errors.New("invalid timestamp")
    47  
    48  	errInvalidVotingChain = errors.New("invalid voting chain")
    49  
    50  	errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
    51  
    52  	errInvalidCommittedSeals = errors.New("invalid committed seals")
    53  
    54  	errEmptyCommittedSeals = errors.New("zero committed seals")
    55  
    56  	errMismatchTxhashes = errors.New("mismatch transactions hashes")
    57  
    58  	errInvalidMainChainNumber = errors.New("invalid Main Chain Height")
    59  
    60  	errMainChainNotCatchup = errors.New("unable proceed the block due to main chain not catch up by waiting for more than 300 seconds, please catch up the main chain first")
    61  )
    62  
    63  var (
    64  	now = time.Now
    65  
    66  	inmemoryAddresses  = 20
    67  	recentAddresses, _ = lru.NewARC(inmemoryAddresses)
    68  
    69  	_ consensus.Engine = (*backend)(nil)
    70  
    71  	neatGenesisAddress = common.HexToAddress("0x0000000000000000000000000000000000000000")
    72  	foundationAddress  = common.HexToAddress("0xbbe9e63Dcb95105A3Ab5e9094B0C866F0f418987")
    73  
    74  	sideChainRewardAddress = common.StringToAddress("0x0000000000000000000000000000000000000535")
    75  )
    76  
    77  func (sb *backend) APIs(chain consensus.ChainReader) []rpc.API {
    78  	return []rpc.API{{
    79  		Namespace: "neat",
    80  		Version:   "1.0",
    81  		Service:   &API{chain: chain, neatcon: sb},
    82  		Public:    true,
    83  	}}
    84  }
    85  
    86  func (sb *backend) Start(chain consensus.ChainReader, currentBlock func() *types.Block, hasBadBlock func(hash common.Hash) bool) error {
    87  
    88  	sb.logger.Info("NeatCon backend Start")
    89  
    90  	sb.coreMu.Lock()
    91  	defer sb.coreMu.Unlock()
    92  	if sb.coreStarted {
    93  		return ErrStartedEngine
    94  	}
    95  
    96  	sb.proposedBlockHash = common.Hash{}
    97  	if sb.commitCh != nil {
    98  		close(sb.commitCh)
    99  	}
   100  	sb.commitCh = make(chan *types.Block, 1)
   101  	if sb.vcommitCh != nil {
   102  		close(sb.vcommitCh)
   103  	}
   104  	sb.vcommitCh = make(chan *ntcTypes.IntermediateBlockResult, 1)
   105  
   106  	sb.chain = chain
   107  	sb.currentBlock = currentBlock
   108  	sb.hasBadBlock = hasBadBlock
   109  
   110  	if _, err := sb.core.Start(); err != nil {
   111  		return err
   112  	}
   113  
   114  	sb.coreStarted = true
   115  
   116  	return nil
   117  }
   118  
   119  func (sb *backend) Stop() error {
   120  
   121  	sb.logger.Info("NeatCon backend stop")
   122  
   123  	sb.coreMu.Lock()
   124  	defer sb.coreMu.Unlock()
   125  	if !sb.coreStarted {
   126  		return ErrStoppedEngine
   127  	}
   128  	if !sb.core.Stop() {
   129  		return errors.New("neatcon stop error")
   130  	}
   131  	sb.coreStarted = false
   132  
   133  	return nil
   134  }
   135  
   136  func (sb *backend) Close() error {
   137  	sb.core.epochDB.Close()
   138  	return nil
   139  }
   140  
   141  func (sb *backend) Author(header *types.Header) (common.Address, error) {
   142  	return header.Coinbase, nil
   143  }
   144  
   145  func (sb *backend) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   146  
   147  	//sb.logger.Info("Your node is synchronized. This is Neat!")
   148  
   149  	return sb.verifyHeader(chain, header, nil)
   150  }
   151  
   152  func (sb *backend) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   153  
   154  	if header.Number == nil {
   155  		return errUnknownBlock
   156  	}
   157  
   158  	if header.Time.Cmp(big.NewInt(now().Unix())) > 0 {
   159  		sb.logger.Warnf("date/time different between different nodes. block from future with time:%v, bigger than now:%v", header.Time.Uint64(), now().Unix())
   160  
   161  	}
   162  
   163  	if _, err := ntcTypes.ExtractNeatConExtra(header); err != nil {
   164  		return errInvalidExtraDataFormat
   165  	}
   166  
   167  	if header.Nonce != (types.NeatConEmptyNonce) && !bytes.Equal(header.Nonce[:], types.NeatConNonce) {
   168  		return errInvalidNonce
   169  	}
   170  
   171  	if header.MixDigest != types.NeatConDigest {
   172  		return errInvalidMixDigest
   173  	}
   174  
   175  	if header.UncleHash != types.NeatConNilUncleHash {
   176  		return errInvalidUncleHash
   177  	}
   178  
   179  	if header.Difficulty == nil || header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 {
   180  		return errInvalidDifficulty
   181  	}
   182  
   183  	if header.Number.Uint64() > sb.GetEpoch().EndBlock {
   184  		for {
   185  			duration := 2 * time.Second
   186  			sb.logger.Infof("NeatCon VerifyHeader, Epoch Switch, wait for %v then try again", duration)
   187  			time.Sleep(duration)
   188  
   189  			if header.Number.Uint64() <= sb.GetEpoch().EndBlock {
   190  				break
   191  			}
   192  		}
   193  	}
   194  
   195  	if fieldError := sb.verifyCascadingFields(chain, header, parents); fieldError != nil {
   196  		return fieldError
   197  	}
   198  
   199  	if !sb.chainConfig.IsMainChain() {
   200  		if header.MainChainNumber == nil {
   201  			return errInvalidMainChainNumber
   202  		}
   203  
   204  		tried := 0
   205  		for {
   206  
   207  			ourMainChainHeight := sb.core.cch.GetHeightFromMainChain()
   208  			if ourMainChainHeight.Cmp(header.MainChainNumber) >= 0 {
   209  				break
   210  			}
   211  
   212  			if tried == 10 {
   213  				sb.logger.Warnf("NeatCon VerifyHeader, Main Chain Number mismatch, after retried %d times", tried)
   214  				return errMainChainNotCatchup
   215  			}
   216  
   217  			duration := 30 * time.Second
   218  			tried++
   219  			sb.logger.Infof("NeatCon VerifyHeader, Main Chain Number mismatch, wait for %v then try again (count %d)", duration, tried)
   220  			time.Sleep(duration)
   221  		}
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  func (sb *backend) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   228  
   229  	number := header.Number.Uint64()
   230  	if number == 0 {
   231  		return nil
   232  	}
   233  
   234  	var parent *types.Header
   235  	if len(parents) > 0 {
   236  		parent = parents[len(parents)-1]
   237  	} else {
   238  		parent = chain.GetHeader(header.ParentHash, number-1)
   239  	}
   240  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   241  		return consensus.ErrUnknownAncestor
   242  	}
   243  
   244  	err := sb.verifyCommittedSeals(chain, header, parents)
   245  	return err
   246  }
   247  
   248  func (sb *backend) VerifyHeaderBeforeConsensus(chain consensus.ChainReader, header *types.Header, seal bool) error {
   249  	//sb.logger.Info("NeatCon backend verify header before consensus")
   250  
   251  	if header.Number == nil {
   252  		return errUnknownBlock
   253  	}
   254  
   255  	if header.Time.Cmp(big.NewInt(now().Unix())) > 0 {
   256  		sb.logger.Warnf("date/time different between different nodes. block from future with time:%v, bigger than now:%v", header.Time.Uint64(), now().Unix())
   257  
   258  	}
   259  
   260  	if header.Nonce != (types.NeatConEmptyNonce) && !bytes.Equal(header.Nonce[:], types.NeatConNonce) {
   261  		return errInvalidNonce
   262  	}
   263  
   264  	if header.MixDigest != types.NeatConDigest {
   265  		return errInvalidMixDigest
   266  	}
   267  
   268  	if header.UncleHash != types.NeatConNilUncleHash {
   269  		return errInvalidUncleHash
   270  	}
   271  
   272  	if header.Difficulty == nil || header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 {
   273  		return errInvalidDifficulty
   274  	}
   275  
   276  	return nil
   277  }
   278  
   279  func (sb *backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   280  	abort := make(chan struct{})
   281  	results := make(chan error, len(headers))
   282  
   283  	//sb.logger.Info("NeatCon backend verify headers")
   284  
   285  	go func() {
   286  		for i, header := range headers {
   287  			err := sb.verifyHeader(chain, header, headers[:i])
   288  			select {
   289  			case <-abort:
   290  				return
   291  			case results <- err:
   292  			}
   293  		}
   294  	}()
   295  
   296  	return abort, results
   297  }
   298  
   299  func (sb *backend) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   300  
   301  	if len(block.Uncles()) > 0 {
   302  		return errInvalidUncleHash
   303  	}
   304  	return nil
   305  }
   306  
   307  func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   308  
   309  	ncExtra, err := ntcTypes.ExtractNeatConExtra(header)
   310  	if err != nil {
   311  		return errInvalidExtraDataFormat
   312  	}
   313  
   314  	epoch := sb.core.consensusState.Epoch
   315  	if epoch == nil || epoch.Validators == nil {
   316  		sb.logger.Errorf("verifyCommittedSeals error. Epoch %v", epoch)
   317  		return errInconsistentValidatorSet
   318  	}
   319  
   320  	epoch = epoch.GetEpochByBlockNumber(header.Number.Uint64())
   321  	if epoch == nil || epoch.Validators == nil {
   322  		sb.logger.Errorf("verifyCommittedSeals error. Epoch %v", epoch)
   323  		return errInconsistentValidatorSet
   324  	}
   325  
   326  	valSet := epoch.Validators
   327  	if !bytes.Equal(valSet.Hash(), ncExtra.ValidatorsHash) {
   328  		sb.logger.Errorf("verifyCommittedSeals error. Our Validator Set %x, ncExtra Valdiator %x", valSet.Hash(), ncExtra.ValidatorsHash)
   329  		sb.logger.Errorf("verifyCommittedSeals error. epoch validator set %v, extra data %v", valSet.String(), ncExtra.String())
   330  		return errInconsistentValidatorSet
   331  	}
   332  
   333  	seenCommit := ncExtra.SeenCommit
   334  	if !bytes.Equal(ncExtra.SeenCommitHash, seenCommit.Hash()) {
   335  		sb.logger.Errorf("verifyCommittedSeals SeenCommit is %#+v", seenCommit)
   336  		sb.logger.Errorf("verifyCommittedSeals error. Our SeenCommitHash %x, ncExtra SeenCommitHash %x", seenCommit.Hash(), ncExtra.SeenCommitHash)
   337  		return errInvalidCommittedSeals
   338  	}
   339  
   340  	if err = valSet.VerifyCommit(ncExtra.ChainID, ncExtra.Height, seenCommit); err != nil {
   341  		sb.logger.Errorf("verifyCommittedSeals verify commit err %v", err)
   342  		return errInvalidSignature
   343  	}
   344  
   345  	return nil
   346  }
   347  
   348  func (sb *backend) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   349  
   350  	number := header.Number.Uint64()
   351  	if number == 0 {
   352  		return errUnknownBlock
   353  	}
   354  
   355  	if header.Difficulty.Cmp(types.NeatConDefaultDifficulty) != 0 {
   356  		return errInvalidDifficulty
   357  	}
   358  
   359  	return nil
   360  }
   361  
   362  func (sb *backend) Prepare(chain consensus.ChainReader, header *types.Header) error {
   363  
   364  	header.Nonce = types.NeatConEmptyNonce
   365  	header.MixDigest = types.NeatConDigest
   366  
   367  	number := header.Number.Uint64()
   368  	parent := chain.GetHeader(header.ParentHash, number-1)
   369  	if parent == nil {
   370  		return consensus.ErrUnknownAncestor
   371  	}
   372  
   373  	header.Difficulty = types.NeatConDefaultDifficulty
   374  
   375  	extra, err := prepareExtra(header, nil)
   376  	if err != nil {
   377  		return err
   378  	}
   379  	header.Extra = extra
   380  
   381  	header.Time = big.NewInt(time.Now().Unix())
   382  
   383  	if sb.chainConfig.NeatChainId != params.MainnetChainConfig.NeatChainId && sb.chainConfig.NeatChainId != params.TestnetChainConfig.NeatChainId {
   384  		header.MainChainNumber = sb.core.cch.GetHeightFromMainChain()
   385  	}
   386  
   387  	return nil
   388  }
   389  
   390  func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   391  	totalGasFee *big.Int, uncles []*types.Header, receipts []*types.Receipt, ops *types.PendingOps) (*types.Block, error) {
   392  
   393  	sb.logger.Debugf("NeatCon Finalize, receipts are: %v", receipts)
   394  
   395  	if sb.chainConfig.NeatChainId == params.MainnetChainConfig.NeatChainId || sb.chainConfig.NeatChainId == params.TestnetChainConfig.NeatChainId {
   396  
   397  		readyId, updateBytes, removedId := sb.core.cch.ReadyForLaunchSideChain(header.Number, state)
   398  		if len(readyId) > 0 || updateBytes != nil || len(removedId) > 0 {
   399  			if ok := ops.Append(&types.LaunchSideChainsOp{
   400  				SideChainIds:       readyId,
   401  				NewPendingIdx:      updateBytes,
   402  				DeleteSideChainIds: removedId,
   403  			}); !ok {
   404  
   405  				sb.logger.Error("NeatCon Finalize, Fail to append LaunchSideChainsOp, only one LaunchSideChainsOp is allowed in each block")
   406  			}
   407  		}
   408  	}
   409  
   410  	curBlockNumber := header.Number.Uint64()
   411  	epoch := sb.GetEpoch().GetEpochByBlockNumber(curBlockNumber)
   412  
   413  	genesisHeader := chain.GetBlockByNumber(1)
   414  	if genesisHeader != nil {
   415  		genesisCoinbase := genesisHeader.Header().Coinbase
   416  		neatGenesisAddress = state.GetAddress(genesisCoinbase)
   417  	}
   418  
   419  	accumulateRewards(sb.chainConfig, state, header, epoch, totalGasFee)
   420  
   421  	if ok, newValidators, _ := epoch.ShouldEnterNewEpoch(header.Number.Uint64(), state); ok {
   422  		ops.Append(&ntcTypes.SwitchEpochOp{
   423  			ChainId:       sb.chainConfig.NeatChainId,
   424  			NewValidators: newValidators,
   425  		})
   426  
   427  	}
   428  
   429  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   430  	header.UncleHash = types.NeatConNilUncleHash
   431  
   432  	return types.NewBlock(header, txs, nil, receipts), nil
   433  }
   434  
   435  func (sb *backend) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (interface{}, error) {
   436  
   437  	//sb.logger.Info("NeatCon backend seal")
   438  
   439  	header := block.Header()
   440  	number := header.Number.Uint64()
   441  	parent := chain.GetHeader(header.ParentHash, number-1)
   442  	if parent == nil {
   443  		return nil, consensus.ErrUnknownAncestor
   444  	}
   445  	block, err := sb.updateBlock(parent, block)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  
   450  	delay := time.Unix(block.Header().Time.Int64(), 0).Sub(now())
   451  	select {
   452  	case <-time.After(delay):
   453  	case <-stop:
   454  		return nil, nil
   455  	}
   456  
   457  	sb.sealMu.Lock()
   458  	sb.proposedBlockHash = block.Hash()
   459  	clear := func() {
   460  		sb.proposedBlockHash = common.Hash{}
   461  		sb.sealMu.Unlock()
   462  	}
   463  	defer clear()
   464  
   465  	//sb.logger.Infof("NeatCon Seal, before fire event with block height: %d", block.NumberU64())
   466  	go ntcTypes.FireEventRequest(sb.core.EventSwitch(), ntcTypes.EventDataRequest{Proposal: block})
   467  
   468  	for {
   469  		select {
   470  		case result, ok := <-sb.commitCh:
   471  
   472  			if ok {
   473  				sb.logger.Debugf("NeatCon Seal, got result with block.Hash: %x, result.Hash: %x", block.Hash(), result.Hash())
   474  
   475  				if block.Hash() == result.Hash() {
   476  					return result, nil
   477  				}
   478  				sb.logger.Debug("NeatCon Seal, hash are different")
   479  			} else {
   480  				sb.logger.Debug("NeatCon Seal, has been restart, just return")
   481  				return nil, nil
   482  			}
   483  
   484  		case iresult, ok := <-sb.vcommitCh:
   485  
   486  			if ok {
   487  				sb.logger.Debugf("NeatCon Seal, v got result with block.Hash: %x, result.Hash: %x", block.Hash(), iresult.Block.Hash())
   488  				if block.Hash() != iresult.Block.Hash() {
   489  					return iresult, nil
   490  				}
   491  				sb.logger.Debug("NeatCon Seal, v hash are the same")
   492  			} else {
   493  				sb.logger.Debug("NeatCon Seal, v has been restart, just return")
   494  				return nil, nil
   495  			}
   496  
   497  		case <-stop:
   498  			sb.logger.Debug("NeatCon Seal, stop")
   499  			return nil, nil
   500  		}
   501  	}
   502  
   503  	return nil, nil
   504  }
   505  
   506  func (sb *backend) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   507  
   508  	return types.NeatConDefaultDifficulty
   509  }
   510  
   511  func (sb *backend) Commit(proposal *ntcTypes.NCBlock, seals [][]byte, isProposer func() bool) error {
   512  
   513  	block := proposal.Block
   514  
   515  	h := block.Header()
   516  
   517  	err := writeCommittedSeals(h, proposal.NTCExtra)
   518  	if err != nil {
   519  		return err
   520  	}
   521  
   522  	block = block.WithSeal(h)
   523  
   524  	sb.logger.Debugf("NeatCon Commit, hash: %x, number: %v", block.Hash(), block.Number().Int64())
   525  	sb.logger.Debugf("NeatCon Commit, block: %s", block.String())
   526  
   527  	if isProposer() && (sb.proposedBlockHash == block.Hash()) {
   528  
   529  		sb.logger.Debugf("NeatCon Commit, proposer | feed to Seal: %x", block.Hash())
   530  		sb.commitCh <- block
   531  		return nil
   532  	} else {
   533  		if proposal.IntermediateResult != nil {
   534  			sb.logger.Debugf("NeatCon Commit, validator | feed to Seal: %x", block.Hash())
   535  			proposal.IntermediateResult.Block = block
   536  			sb.vcommitCh <- proposal.IntermediateResult
   537  		} else {
   538  			sb.logger.Debugf("NeatCon Commit, validator | fetcher enqueue: %x", block.Hash())
   539  			if sb.broadcaster != nil {
   540  				sb.broadcaster.Enqueue(fetcherID, block)
   541  			}
   542  		}
   543  		return nil
   544  	}
   545  }
   546  
   547  func (sb *backend) ChainReader() consensus.ChainReader {
   548  
   549  	return sb.chain
   550  }
   551  
   552  func (sb *backend) ShouldStart() bool {
   553  	return sb.shouldStart
   554  }
   555  
   556  func (sb *backend) IsStarted() bool {
   557  	sb.coreMu.RLock()
   558  	start := sb.coreStarted
   559  	sb.coreMu.RUnlock()
   560  
   561  	return start
   562  }
   563  
   564  func (sb *backend) ForceStart() {
   565  	sb.shouldStart = true
   566  }
   567  
   568  func (sb *backend) GetEpoch() *epoch.Epoch {
   569  	return sb.core.consensusState.Epoch
   570  }
   571  
   572  func (sb *backend) SetEpoch(ep *epoch.Epoch) {
   573  	sb.core.consensusState.Epoch = ep
   574  }
   575  
   576  func (sb *backend) PrivateValidator() common.Address {
   577  	if sb.core.privValidator != nil {
   578  		return sb.core.privValidator.Address
   579  	}
   580  	return common.Address{}
   581  }
   582  
   583  func (sb *backend) updateBlock(parent *types.Header, block *types.Block) (*types.Block, error) {
   584  
   585  	sb.logger.Debug("NeatCon backend update block")
   586  
   587  	header := block.Header()
   588  	err := writeSeal(header, []byte{})
   589  	if err != nil {
   590  		return nil, err
   591  	}
   592  
   593  	return block.WithSeal(header), nil
   594  }
   595  
   596  func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) {
   597  
   598  	header.Extra = types.MagicExtra
   599  	return nil, nil
   600  }
   601  
   602  func writeSeal(h *types.Header, seal []byte) error {
   603  
   604  	if h.Extra == nil {
   605  		payload := types.MagicExtra
   606  		h.Extra = payload
   607  	}
   608  	return nil
   609  }
   610  
   611  func writeCommittedSeals(h *types.Header, ncExtra *ntcTypes.NeatConExtra) error {
   612  
   613  	h.Extra = wire.BinaryBytes(*ncExtra)
   614  	return nil
   615  }
   616  
   617  func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, ep *epoch.Epoch, totalGasFee *big.Int) {
   618  	tenPercentGasFee := big.NewInt(0).Div(totalGasFee, big.NewInt(10))
   619  	state.AddBalance(foundationAddress, tenPercentGasFee)
   620  
   621  	var coinbaseReward *big.Int
   622  	if config.NeatChainId == params.MainnetChainConfig.NeatChainId || config.NeatChainId == params.TestnetChainConfig.NeatChainId {
   623  		rewardPerBlock := ep.RewardPerBlock
   624  		if rewardPerBlock != nil && rewardPerBlock.Sign() == 1 {
   625  			zeroAddress := common.Address{}
   626  			if neatGenesisAddress == zeroAddress {
   627  				coinbaseReward = big.NewInt(0)
   628  				coinbaseReward.Add(rewardPerBlock, tenPercentGasFee)
   629  			} else {
   630  				coinbaseReward = new(big.Int).Mul(rewardPerBlock, big.NewInt(8))
   631  				coinbaseReward.Quo(coinbaseReward, big.NewInt(10))
   632  				foundationReward := new(big.Int).Sub(rewardPerBlock, coinbaseReward)
   633  				state.AddBalance(neatGenesisAddress, foundationReward)
   634  				coinbaseReward.Add(coinbaseReward, tenPercentGasFee)
   635  			}
   636  		} else {
   637  			coinbaseReward = tenPercentGasFee
   638  		}
   639  	} else {
   640  		rewardPerBlock := state.GetSideChainRewardPerBlock()
   641  		if rewardPerBlock != nil && rewardPerBlock.Sign() == 1 {
   642  			sideChainRewardBalance := state.GetBalance(sideChainRewardAddress)
   643  			if sideChainRewardBalance.Cmp(rewardPerBlock) == -1 {
   644  				rewardPerBlock = sideChainRewardBalance
   645  			}
   646  
   647  			state.SubBalance(sideChainRewardAddress, rewardPerBlock)
   648  
   649  			coinbaseReward = new(big.Int).Add(rewardPerBlock, tenPercentGasFee)
   650  		} else {
   651  			coinbaseReward = tenPercentGasFee
   652  		}
   653  	}
   654  
   655  	selfDeposit := state.GetDepositBalance(header.Coinbase)
   656  	totalProxiedDeposit := state.GetTotalDepositProxiedBalance(header.Coinbase)
   657  	totalDeposit := new(big.Int).Add(selfDeposit, totalProxiedDeposit)
   658  
   659  	var selfReward, delegateReward *big.Int
   660  	if totalProxiedDeposit.Sign() == 0 {
   661  		selfReward = coinbaseReward
   662  	} else {
   663  		selfReward = new(big.Int)
   664  
   665  		selfPercent := new(big.Float).Quo(new(big.Float).SetInt(selfDeposit), new(big.Float).SetInt(totalDeposit))
   666  
   667  		new(big.Float).Mul(new(big.Float).SetInt(coinbaseReward), selfPercent).Int(selfReward)
   668  
   669  		delegateReward = new(big.Int).Sub(coinbaseReward, selfReward)
   670  		commission := state.GetCommission(header.Coinbase)
   671  		if commission > 0 {
   672  
   673  			commissionReward := new(big.Int).Mul(delegateReward, big.NewInt(int64(commission)))
   674  			commissionReward.Quo(commissionReward, big.NewInt(100))
   675  
   676  			selfReward.Add(selfReward, commissionReward)
   677  
   678  			delegateReward.Sub(delegateReward, commissionReward)
   679  		}
   680  	}
   681  
   682  	state.AddRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, selfReward)
   683  
   684  	if delegateReward != nil && delegateReward.Sign() > 0 {
   685  		totalIndividualReward := big.NewInt(0)
   686  
   687  		state.ForEachProxied(header.Coinbase, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool {
   688  			if depositProxiedBalance.Sign() == 1 {
   689  
   690  				individualReward := new(big.Int).Quo(new(big.Int).Mul(depositProxiedBalance, delegateReward), totalProxiedDeposit)
   691  
   692  				state.AddRewardBalanceByDelegateAddress(key, header.Coinbase, individualReward)
   693  
   694  				totalIndividualReward.Add(totalIndividualReward, individualReward)
   695  			}
   696  			return true
   697  		})
   698  
   699  		cmp := delegateReward.Cmp(totalIndividualReward)
   700  		if cmp == 1 {
   701  
   702  			diff := new(big.Int).Sub(delegateReward, totalIndividualReward)
   703  
   704  			state.AddRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, diff)
   705  		} else if cmp == -1 {
   706  
   707  			diff := new(big.Int).Sub(totalIndividualReward, delegateReward)
   708  
   709  			state.SubRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, diff)
   710  		}
   711  	}
   712  
   713  }