github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/core/state/statedb_reward.go (about)

     1  package state
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/intfoundation/intchain/common"
     7  	"github.com/intfoundation/intchain/rlp"
     8  	"github.com/intfoundation/intchain/trie"
     9  	"io"
    10  	"math/big"
    11  	"sort"
    12  )
    13  
    14  // ----- RewardBalance (Total)
    15  
    16  // GetTotalRewardBalance Retrieve the reward balance from the given address or 0 if object not found
    17  func (self *StateDB) GetTotalRewardBalance(addr common.Address) *big.Int {
    18  	stateObject := self.getStateObject(addr)
    19  	if stateObject != nil {
    20  		return stateObject.RewardBalance()
    21  	}
    22  	return common.Big0
    23  }
    24  
    25  func (self *StateDB) AddRewardBalance(addr common.Address, amount *big.Int) {
    26  	stateObject := self.GetOrNewStateObject(addr)
    27  	if stateObject != nil {
    28  		// Add amount to Total Reward Balance
    29  		stateObject.AddRewardBalance(amount)
    30  	}
    31  }
    32  
    33  func (self *StateDB) SubRewardBalance(addr common.Address, amount *big.Int) {
    34  	stateObject := self.GetOrNewStateObject(addr)
    35  	if stateObject != nil {
    36  		// Sub amount to Total Reward Balance
    37  		stateObject.SubRewardBalance(amount)
    38  	}
    39  }
    40  
    41  // ----- AvailableRewardBalance (Total)
    42  
    43  // GetTotalAvailableRewardBalance retrieve the available reward balance from the given address or 0 if object not found
    44  //func (self *StateDB) GetTotalAvailableRewardBalance(addr common.Address) *big.Int {
    45  //	stateObject := self.getStateObject(addr)
    46  //	if stateObject != nil {
    47  //		return stateObject.AvailableRewardBalance()
    48  //	}
    49  //	return common.Big0
    50  //}
    51  //
    52  //func (self *StateDB) AddAvailableRewardBalance(addr common.Address, amount *big.Int) {
    53  //	stateObject := self.getStateObject(addr)
    54  //	if stateObject != nil {
    55  //		stateObject.AddAvailableRewardBalance(amount)
    56  //	}
    57  //}
    58  //
    59  //func (self *StateDB) SubAvailableRewardBalance(addr common.Address, amount *big.Int) {
    60  //	stateObject := self.getStateObject(addr)
    61  //	if stateObject != nil {
    62  //		stateObject.SubAvailableRewardBalance(amount)
    63  //	}
    64  //}
    65  
    66  // ----- Reward Trie
    67  
    68  func (self *StateDB) GetDelegateRewardAddress(addr common.Address) map[common.Address]struct{} {
    69  	var deleAddr map[common.Address]struct{}
    70  	reward := Reward{}
    71  
    72  	so := self.getStateObject(addr)
    73  	if so == nil {
    74  		return deleAddr
    75  	}
    76  
    77  	it := trie.NewIterator(so.getRewardTrie(self.db).NodeIterator(nil))
    78  	for it.Next() {
    79  		var key common.Address
    80  		rlp.DecodeBytes(self.trie.GetKey(it.Key), &key)
    81  		deleAddr[key] = struct{}{}
    82  	}
    83  
    84  	if len(so.dirtyReward) > len(deleAddr) {
    85  		reward = so.dirtyReward
    86  		for key := range reward {
    87  			deleAddr[key] = struct{}{}
    88  		}
    89  	}
    90  
    91  	if len(so.originReward) > len(deleAddr) {
    92  		reward = so.originReward
    93  		for key := range reward {
    94  			deleAddr[key] = struct{}{}
    95  		}
    96  	}
    97  
    98  	return deleAddr
    99  }
   100  
   101  // GetRewardBalanceByDelegateAddress
   102  func (self *StateDB) GetRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address) *big.Int {
   103  	stateObject := self.getStateObject(addr)
   104  	if stateObject != nil {
   105  		rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress)
   106  		if rewardBalance == nil {
   107  			return common.Big0
   108  		} else {
   109  			return rewardBalance
   110  		}
   111  	}
   112  	return common.Big0
   113  }
   114  
   115  // AddRewardBalanceByDelegateAddress adds reward amount to the account associated with delegate address
   116  func (self *StateDB) AddRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address, amount *big.Int) {
   117  	stateObject := self.GetOrNewStateObject(addr)
   118  	if stateObject != nil {
   119  		// Get EpochRewardBalance and update EpochRewardBalance
   120  		rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress)
   121  		var dirtyRewardBalance *big.Int
   122  		if rewardBalance == nil {
   123  			dirtyRewardBalance = amount
   124  		} else {
   125  			dirtyRewardBalance = new(big.Int).Add(rewardBalance, amount)
   126  		}
   127  		stateObject.SetDelegateRewardBalance(self.db, deleAddress, dirtyRewardBalance)
   128  
   129  		// Add amount to Total Reward Balance
   130  		stateObject.AddRewardBalance(amount)
   131  	}
   132  }
   133  
   134  // AddRewardBalanceByDelegateAddress subtracts reward amount from the account associated with delegate address
   135  func (self *StateDB) SubRewardBalanceByDelegateAddress(addr common.Address, deleAddress common.Address, amount *big.Int) {
   136  	stateObject := self.GetOrNewStateObject(addr)
   137  	if stateObject != nil {
   138  		// Get EpochRewardBalance and update EpochRewardBalance
   139  		rewardBalance := stateObject.GetDelegateRewardBalance(self.db, deleAddress)
   140  		var dirtyRewardBalance *big.Int
   141  		if rewardBalance == nil {
   142  			panic("you can't subtract the amount from nil balance, check the code, this should not happen")
   143  		} else {
   144  			dirtyRewardBalance = new(big.Int).Sub(rewardBalance, amount)
   145  		}
   146  		stateObject.SetDelegateRewardBalance(self.db, deleAddress, dirtyRewardBalance)
   147  
   148  		// Sub amount from Total Reward Balance
   149  		stateObject.SubRewardBalance(amount)
   150  	}
   151  }
   152  
   153  func (db *StateDB) ForEachReward(addr common.Address, cb func(key common.Address, rewardBalance *big.Int) bool) {
   154  	so := db.getStateObject(addr)
   155  	if so == nil {
   156  		return
   157  	}
   158  	it := trie.NewIterator(so.getRewardTrie(db.db).NodeIterator(nil))
   159  	for it.Next() {
   160  		var key common.Address
   161  		rlp.DecodeBytes(db.trie.GetKey(it.Key), &key)
   162  		if value, dirty := so.dirtyReward[key]; dirty {
   163  			cb(key, value)
   164  			continue
   165  		}
   166  		var value big.Int
   167  		rlp.DecodeBytes(it.Value, &value)
   168  		cb(key, &value)
   169  	}
   170  }
   171  
   172  // ----- Reward Set
   173  
   174  // MarkAddressReward adds the specified object to the dirty map to avoid
   175  func (self *StateDB) MarkAddressReward(addr common.Address) {
   176  	if _, exist := self.GetRewardSet()[addr]; !exist {
   177  		self.rewardSet[addr] = struct{}{}
   178  		self.rewardSetDirty = true
   179  	}
   180  }
   181  
   182  func (self *StateDB) GetRewardSet() RewardSet {
   183  	if len(self.rewardSet) != 0 {
   184  		return self.rewardSet
   185  	}
   186  	// Try to get from Trie
   187  	enc, err := self.trie.TryGet(rewardSetKey)
   188  	if err != nil {
   189  		self.setError(err)
   190  		return nil
   191  	}
   192  	var value RewardSet
   193  	if len(enc) > 0 {
   194  		err := rlp.DecodeBytes(enc, &value)
   195  		if err != nil {
   196  			self.setError(err)
   197  		}
   198  		self.rewardSet = value
   199  	}
   200  	return value
   201  }
   202  
   203  func (self *StateDB) commitRewardSet() {
   204  	data, err := rlp.EncodeToBytes(self.rewardSet)
   205  	if err != nil {
   206  		panic(fmt.Errorf("can't encode reward set : %v", err))
   207  	}
   208  	self.setError(self.trie.TryUpdate(rewardSetKey, data))
   209  }
   210  
   211  func (self *StateDB) ClearRewardSetByAddress(addr common.Address) {
   212  	delete(self.rewardSet, addr)
   213  	self.rewardSetDirty = true
   214  }
   215  
   216  // Store the Reward Address Set
   217  
   218  var rewardSetKey = []byte("RewardSet")
   219  
   220  type RewardSet map[common.Address]struct{}
   221  
   222  func (set RewardSet) EncodeRLP(w io.Writer) error {
   223  	var list []common.Address
   224  	for addr := range set {
   225  		list = append(list, addr)
   226  	}
   227  	sort.Slice(list, func(i, j int) bool {
   228  		return bytes.Compare(list[i].Bytes(), list[j].Bytes()) == 1
   229  	})
   230  	return rlp.Encode(w, list)
   231  }
   232  
   233  func (set *RewardSet) DecodeRLP(s *rlp.Stream) error {
   234  	var list []common.Address
   235  	if err := s.Decode(&list); err != nil {
   236  		return err
   237  	}
   238  	rewardSet := make(RewardSet, len(list))
   239  	for _, addr := range list {
   240  		rewardSet[addr] = struct{}{}
   241  	}
   242  	*set = rewardSet
   243  	return nil
   244  }
   245  
   246  // ----- Child Chain Reward Per Block
   247  
   248  func (self *StateDB) SetChildChainRewardPerBlock(rewardPerBlock *big.Int) {
   249  	self.childChainRewardPerBlock = rewardPerBlock
   250  	self.childChainRewardPerBlockDirty = true
   251  }
   252  
   253  func (self *StateDB) GetChildChainRewardPerBlock() *big.Int {
   254  	if self.childChainRewardPerBlock != nil {
   255  		return self.childChainRewardPerBlock
   256  	}
   257  	// Try to get from Trie
   258  	enc, err := self.trie.TryGet(childChainRewardPerBlockKey)
   259  	if err != nil {
   260  		self.setError(err)
   261  		return nil
   262  	}
   263  	value := new(big.Int)
   264  	if len(enc) > 0 {
   265  		err := rlp.DecodeBytes(enc, value)
   266  		if err != nil {
   267  			self.setError(err)
   268  		}
   269  		self.childChainRewardPerBlock = value
   270  	}
   271  	return value
   272  }
   273  
   274  func (self *StateDB) commitChildChainRewardPerBlock() {
   275  	data, err := rlp.EncodeToBytes(self.childChainRewardPerBlock)
   276  	if err != nil {
   277  		panic(fmt.Errorf("can't encode child chain reward per block : %v", err))
   278  	}
   279  	self.setError(self.trie.TryUpdate(childChainRewardPerBlockKey, data))
   280  }
   281  
   282  // Child Chain Reward Per Block
   283  
   284  var childChainRewardPerBlockKey = []byte("RewardPerBlock")
   285  
   286  func (self *StateDB) MarkProposedInEpoch(address common.Address, epoch uint64) error {
   287  
   288  	return self.db.TrieDB().MarkProposedInEpoch(address, epoch)
   289  }
   290  
   291  func (self *StateDB) CheckProposedInEpoch(address common.Address, epoch uint64) bool {
   292  
   293  	return self.db.TrieDB().CheckProposedInEpoch(address, epoch)
   294  }