github.com/amazechain/amc@v0.1.3/internal/consensus/apos/consensus.go (about)

     1  package apos
     2  
     3  import (
     4  	"github.com/amazechain/amc/common/block"
     5  	"github.com/amazechain/amc/common/math"
     6  	"github.com/amazechain/amc/common/types"
     7  	"github.com/amazechain/amc/internal/consensus"
     8  	"github.com/amazechain/amc/log"
     9  	"github.com/amazechain/amc/modules/state"
    10  	"github.com/amazechain/amc/params"
    11  	"github.com/holiman/uint256"
    12  	"sort"
    13  )
    14  
    15  func AccumulateRewards(r *Reward, number *uint256.Int, chain consensus.ChainHeaderReader) (map[types.Address]*uint256.Int, map[types.Address]*uint256.Int, error) {
    16  
    17  	rewardMap := make(map[types.Address]*uint256.Int, 0)
    18  	unpayMap := make(map[types.Address]*uint256.Int, 0)
    19  
    20  	endNumber := new(uint256.Int).Sub(number, r.rewardEpoch)
    21  	//calculate last batch but this one
    22  	currentNr := number.Clone()
    23  	currentNr.SubUint64(currentNr, 1)
    24  
    25  	depositeMap := map[types.Address]struct {
    26  		reward    *uint256.Int
    27  		maxReward *uint256.Int
    28  	}{}
    29  	for currentNr.Cmp(endNumber) >= 0 {
    30  		block, err := chain.GetBlockByNumber(currentNr)
    31  		if nil != err {
    32  			return nil, nil, err
    33  		}
    34  
    35  		verifiers := block.Body().Verifier()
    36  		for _, verifier := range verifiers {
    37  			_, ok := depositeMap[verifier.Address]
    38  			if !ok {
    39  				low, max := chain.GetDepositInfo(verifier.Address)
    40  				if low == nil || max == nil {
    41  					continue
    42  				}
    43  				depositeMap[verifier.Address] = struct {
    44  					reward    *uint256.Int
    45  					maxReward *uint256.Int
    46  				}{reward: low, maxReward: max}
    47  
    48  				log.Debug("account deposite infos", "addr", verifier.Address, "perblock", low, "perepoch", max)
    49  			}
    50  
    51  			addrReward, ok := rewardMap[verifier.Address]
    52  			if !ok {
    53  				addrReward = uint256.NewInt(0)
    54  			}
    55  
    56  			rewardMap[verifier.Address] = math.Min256(addrReward.Add(addrReward, depositeMap[verifier.Address].reward), depositeMap[verifier.Address].maxReward.Clone())
    57  		}
    58  
    59  		currentNr.SubUint64(currentNr, 1)
    60  	}
    61  
    62  	for addr, amount := range rewardMap {
    63  		var payAmount, unpayAmount *uint256.Int
    64  
    65  		lastSedi, err := chain.GetAccountRewardUnpaid(addr)
    66  		if err != nil {
    67  			log.Debug("build reward Big map get account reward error,err=", err)
    68  			return nil, nil, err
    69  		}
    70  		if lastSedi != nil {
    71  			amount.Add(amount, lastSedi)
    72  		}
    73  
    74  		if amount.Cmp(r.rewardLimit) >= 0 {
    75  			payAmount = amount.Clone()
    76  			unpayAmount = uint256.NewInt(0)
    77  		} else {
    78  			payAmount = uint256.NewInt(0)
    79  			unpayAmount = amount.Clone()
    80  		}
    81  
    82  		rewardMap[addr] = payAmount
    83  		unpayMap[addr] = unpayAmount
    84  	}
    85  
    86  	//log.Debug("buildrewards maps", "rewardMap", rewardMap, "rewardmap len", len(rewardMap), "issetreward", setRewards)
    87  	//
    88  	//if setRewards {
    89  	//	if err := r.setRewardByEpochPaid(tx, epoch, rewardMap); err != nil {
    90  	//		return nil, err
    91  	//	}
    92  	//}
    93  
    94  	return rewardMap, unpayMap, nil
    95  }
    96  
    97  func doReward(chainConf *params.ChainConfig, state *state.IntraBlockState, header *block.Header, chain consensus.ChainHeaderReader) ([]*block.Reward, map[types.Address]*uint256.Int, error) {
    98  	beijing, _ := uint256.FromBig(chainConf.BeijingBlock)
    99  	number := header.Number64()
   100  	var rewards block.Rewards
   101  	var upayMap map[types.Address]*uint256.Int
   102  
   103  	if chainConf.IsBeijing(number.Uint64()) && new(uint256.Int).Mod(new(uint256.Int).Sub(number, beijing), uint256.NewInt(chainConf.Apos.RewardEpoch)).
   104  		Cmp(uint256.NewInt(0)) == 0 {
   105  		r := newReward(chainConf)
   106  		var (
   107  			err    error
   108  			payMap map[types.Address]*uint256.Int
   109  		)
   110  		payMap, upayMap, err = AccumulateRewards(r, number, chain)
   111  		if nil != err {
   112  			return nil, nil, err
   113  		}
   114  		for addr, value := range payMap {
   115  			if value.Cmp(uint256.NewInt(0)) > 0 {
   116  				if !state.Exist(addr) {
   117  					state.CreateAccount(addr, false)
   118  				}
   119  
   120  				log.Info("🔨 set account reward", "addr", addr, "amount", value.Uint64(), "blockNr", header.Number.Uint64())
   121  				state.AddBalance(addr, value)
   122  				rewards = append(rewards, &block.Reward{
   123  					Address: addr,
   124  					Amount:  value,
   125  				})
   126  			}
   127  		}
   128  		if !isWrongStateRootBlockNumber(header.Number64()) {
   129  			state.SoftFinalise()
   130  		}
   131  		sort.Sort(rewards)
   132  	}
   133  	return rewards, upayMap, nil
   134  }
   135  
   136  func isWrongStateRootBlockNumber(blockNr *uint256.Int) bool {
   137  	switch blockNr.Uint64() {
   138  	case 1288400, 1299200, 1310000, 1320800, 1331600, 1342400, 1353200, 1364000, 1374800, 1385600, 1396400, 1407200, 1418000, 1428800, 1439600, 1450400:
   139  		return true
   140  	default:
   141  		return false
   142  	}
   143  }