Skip to content

Commit

Permalink
feat(nft): record DPoS 2.0 reward of memory by stake address
Browse files Browse the repository at this point in the history
  • Loading branch information
RainFallsSilent committed Mar 17, 2023
1 parent c582dc7 commit df14512
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 142 deletions.
2 changes: 1 addition & 1 deletion common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func GetDefaultParams() *Configuration {
HistoryStartHeight: uint32(0),
NeedSave: true,
},
MemoryPoolTxMaximumStayHeight: 10,
MemoryPoolTxMaximumStayHeight: 10, // todo complete me
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/transaction/dposv2claimrewardtransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (t *DPoSV2ClaimRewardTransaction) SpecialContextCheck() (elaerr.ELAError, b
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("invalid payload version")), true
}

addr, err := utils.GetAddressByCode(code)
addr, err := utils.GetStakeAddressByCode(code)
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("Programs code to address error")), true
}
Expand Down
8 changes: 6 additions & 2 deletions core/transaction/dposv2claimrewardtransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@ func (s *txValidatorTestSuite) TestCreateClaimDposV2Transaction() {
err, _ = tx.SpecialContextCheck()
s.EqualError(err.(errors.ELAError).InnerError(), "no reward to claim for such address")

addr, _ := common.Uint168FromAddress("ERyUmNH51roR9qfru37Kqkaok2NghR7L5U")
addr[0] = byte(contract.PrefixDPoSV2)
stakeAddr, _ := addr.ToAddress()

bc := s.Chain
bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 100
bc.GetState().DPoSV2RewardInfo[stakeAddr] = 100
tx.DefaultChecker.SetParameters(&TransactionParameters{
BlockChain: bc,
Config: param,
Expand All @@ -84,7 +88,7 @@ func (s *txValidatorTestSuite) TestCreateClaimDposV2Transaction() {
s.EqualError(err.(errors.ELAError).InnerError(), "claim reward exceeded , max claim reward 0.00000100")

bc = s.Chain
bc.GetState().DPoSV2RewardInfo["ERyUmNH51roR9qfru37Kqkaok2NghR7L5U"] = 10000000000
bc.GetState().DPoSV2RewardInfo[stakeAddr] = 10000000000
tx.DefaultChecker.SetParameters(&TransactionParameters{
BlockChain: bc,
Config: param,
Expand Down
1 change: 1 addition & 0 deletions core/transaction/inactivearbitratorstransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func checkCRCArbitratorsSignatures(program *program.Program) error {

code := program.Code
// Get N parameter
// todo check
n := int(code[len(code)-2]) - crypto.PUSH1 + 1
// Get M parameter
m := int(code[0]) - crypto.PUSH1 + 1
Expand Down
1 change: 1 addition & 0 deletions core/transaction/registercrtransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (t *RegisterCRTransaction) SpecialContextCheck() (elaerr.ELAError, bool) {
var pk []byte
if contract.IsSchnorr(code) {
pk = code[2:]
// todo check
} else if code[len(code)-1] == vm.CHECKSIG {
pk = code[1 : len(code)-1]
} else if code[len(code)-1] == vm.CHECKMULTISIG {
Expand Down
9 changes: 0 additions & 9 deletions core/transaction/registerproducertransaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,11 @@ func (t *RegisterProducerTransaction) SpecialContextCheck() (elaerr.ELAError, bo
if err != nil {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("invalid public key")), true
}
addr, _ := hash.ToAddress()
log.Debugf("#### hash.ToAddress", addr)

if t.PayloadVersion() == payload.ProducerInfoVersion {
// check deposit coin
var depositCount int
for _, output := range t.Outputs() {
if contract.GetPrefixType(output.ProgramHash) == contract.PrefixDeposit {
addr, _ := output.ProgramHash.ToAddress()

log.Debugf("#### register producer 1.0 ", addr)
depositCount++
if !output.ProgramHash.IsEqual(*hash) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("deposit"+
Expand All @@ -199,9 +193,6 @@ func (t *RegisterProducerTransaction) SpecialContextCheck() (elaerr.ELAError, bo
var depositCount int
for _, output := range t.Outputs() {
if contract.GetPrefixType(output.ProgramHash) == contract.PrefixDeposit {
addr, _ := output.ProgramHash.ToAddress()

log.Debugf("#### register producer 2.o ", addr)
depositCount++
if !output.ProgramHash.IsEqual(*hash) {
return elaerr.Simple(elaerr.ErrTxPayload, errors.New("deposit address does not match the public key in payload")), true
Expand Down
6 changes: 4 additions & 2 deletions core/types/payload/nftdestroyfromsidechain.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import (
const NFTDestroyFromSideChainVersion byte = 0x00

type NFTDestroyFromSideChain struct {
IDs []common.Uint256 //detail votes info referkey
OwnerStakeAddresses []common.Uint168 //owner OwnerStakeAddresses
//detail votes info referkey
IDs []common.Uint256
//owner OwnerStakeAddresses
OwnerStakeAddresses []common.Uint168
// genesis block hash of side chain.
GenesisBlockHash common.Uint256
}
Expand Down
8 changes: 0 additions & 8 deletions core/types/payload/voting.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ type DetailedVoteInfo struct {
PayloadVersion byte
VoteType outputpayload.VoteType
Info []VotesWithLockTime
PrefixType byte
}

func (v *DetailedVoteInfo) bytes() []byte {
Expand Down Expand Up @@ -343,9 +342,6 @@ func (v *DetailedVoteInfo) Serialize(w io.Writer) error {
return err
}
}
if err := common.WriteUint8(w, v.PrefixType); err != nil {
return err
}

return nil
}
Expand Down Expand Up @@ -390,9 +386,5 @@ func (v *DetailedVoteInfo) Deserialize(r io.Reader) error {
}
v.Info[i] = info
}
v.PrefixType, err = common.ReadUint8(r)
if err != nil {
return err
}
return nil
}
93 changes: 8 additions & 85 deletions dpos/state/arbitrators.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,9 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte,
for _, cr := range a.CurrentCRCArbitersMap {
if bytes.Equal(sponsor, cr.GetNodePublicKey()) {
ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(cr.GetOwnerPublicKey())
ownerAddr, _ := ownerProgramHash.ToAddress()
stakeProgramHash := common.Uint168FromCodeHash(
byte(contract.PrefixDPoSV2), ownerProgramHash.ToCodeHash())
ownerAddr, _ := stakeProgramHash.ToAddress()
rewards[ownerAddr] += dposReward
isCR = true
break
Expand All @@ -721,37 +723,32 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte,
return
}
ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(producer.OwnerPublicKey())
ownerAddr, _ := ownerProgramHash.ToAddress()
stakeProgramHash := common.Uint168FromCodeHash(
byte(contract.PrefixDPoSV2), ownerProgramHash.ToCodeHash())
ownerAddr, _ := stakeProgramHash.ToAddress()

producersN := make(map[common.Uint168]float64)
stakeAddrPreTypeMgr := make(map[common.Uint168]byte)

var totalNI float64
for sVoteAddr, sVoteDetail := range producer.detailedDPoSV2Votes {
if len(sVoteDetail) == 0 {
continue
}
prefixType := byte(contract.PrefixStandard)
var totalN float64
for _, votes := range sVoteDetail {
weightF := math.Log10(float64(votes.Info[0].LockTime-votes.BlockHeight) / 7200 * 10)
N := common.Fixed64(float64(votes.Info[0].Votes) * weightF)
totalN += float64(N)
prefixType = votes.PrefixType
}
if totalN == 0 {
continue
}
producersN[sVoteAddr] = totalN
stakeAddrPreTypeMgr[sVoteAddr] = prefixType
totalNI += totalN
}

for sVoteAddr, N := range producersN {
b := sVoteAddr.Bytes()
b[0] = stakeAddrPreTypeMgr[sVoteAddr]
standardUint168, _ := common.Uint168FromBytes(b)
addr, _ := standardUint168.ToAddress()
addr, _ := sVoteAddr.ToAddress()
p := N / totalNI * float64(votesReward)
rewards[addr] += common.Fixed64(p)
log.Debugf("getDPoSV2Rewards addr:%s, p:%s, reward:%s \n", addr, common.Fixed64(p), rewards[addr])
Expand All @@ -771,76 +768,6 @@ func (a *Arbiters) getDPoSV2RewardsV2(dposReward common.Fixed64, sponsor []byte,
return rewards
}

func (a *Arbiters) getDPoSV2RewardsV1(dposReward common.Fixed64, sponsor []byte) (rewards map[string]common.Fixed64) {
log.Debugf("accumulateReward dposReward %v", dposReward)
ownerPubKeyStr := a.getProducerKey(sponsor)
ownerPubKeyBytes, _ := hex.DecodeString(ownerPubKeyStr)
ownerProgramHash, _ := contract.PublicKeyToStandardProgramHash(ownerPubKeyBytes)
ownerAddr, _ := ownerProgramHash.ToAddress()

rewards = make(map[string]common.Fixed64)
if _, ok := a.CurrentCRCArbitersMap[*ownerProgramHash]; ok { // crc
// all reward to DPoS node owner
rewards[ownerAddr] += dposReward
} else {

// DPoS votes reward is: reward * 3 /4
votesReward := dposReward * 3 / 4

producer := a.getProducer(sponsor)
if producer == nil {
log.Error("v1 accumulateReward Sponsor not exist ", hex.EncodeToString(sponsor))
return
}
producersN := make(map[common.Uint168]float64)
stakeAddrPreTypeMgr := make(map[common.Uint168]byte)

var totalNI float64
for sVoteAddr, sVoteDetail := range producer.detailedDPoSV2Votes {
if len(sVoteDetail) == 0 {
continue
}
prefixType := byte(contract.PrefixStandard)
var totalN float64
for _, votes := range sVoteDetail {
weightF := math.Log10(float64(votes.Info[0].LockTime-votes.BlockHeight) / 7200 * 10)
N := common.Fixed64(float64(votes.Info[0].Votes) * weightF)
totalN += float64(N)
prefixType = votes.PrefixType
}
if totalN == 0 {
continue
}
producersN[sVoteAddr] = totalN
stakeAddrPreTypeMgr[sVoteAddr] = prefixType
totalNI += totalN
}

for sVoteAddr, N := range producersN {
b := sVoteAddr.Bytes()
b[0] = stakeAddrPreTypeMgr[sVoteAddr]
standardUint168, _ := common.Uint168FromBytes(b)
addr, _ := standardUint168.ToAddress()
p := N / totalNI * float64(votesReward)
rewards[addr] += common.Fixed64(p)
log.Debugf("getDPoSV2Rewards addr:%s, p:%s, reward:%s \n", addr, common.Fixed64(p), rewards[addr])
}

var totalUsedVotesReward common.Fixed64
for _, v := range rewards {
totalUsedVotesReward += v
}

// DPoS node reward is: reward - totalUsedVotesReward
dposNodeReward := dposReward - totalUsedVotesReward
rewards[ownerAddr] += dposNodeReward
log.Debugf("getDPoSV2Rewards totalUsedVotesReward %s dposNodeReward %s, \n", totalUsedVotesReward, dposNodeReward)

}

return rewards
}

func (a *Arbiters) accumulateReward(block *types.Block, confirm *payload.Confirm) {
if block.Height < a.ChainParams.PublicDPOSHeight {
oriDutyIndex := a.DutyIndex
Expand All @@ -867,11 +794,7 @@ func (a *Arbiters) accumulateReward(block *types.Block, confirm *payload.Confirm

var rewards map[string]common.Fixed64
if confirm != nil {
if block.Height > a.ChainParams.DPoSV2StartHeight {
rewards = a.getDPoSV2RewardsV2(dposReward, confirm.Proposal.Sponsor, block.Height)
} else {
rewards = a.getDPoSV2RewardsV1(dposReward, confirm.Proposal.Sponsor)
}
rewards = a.getDPoSV2RewardsV2(dposReward, confirm.Proposal.Sponsor, block.Height)
}

a.History.Append(block.Height, func() {
Expand Down
1 change: 0 additions & 1 deletion dpos/state/keyframe.go
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,6 @@ func copyReferKeyInfoMap(src map[common.Uint256]payload.DetailedVoteInfo) (dst m
PayloadVersion: a.PayloadVersion,
VoteType: a.VoteType,
Info: a.Info,
PrefixType: a.PrefixType,
}
}
return
Expand Down
23 changes: 2 additions & 21 deletions dpos/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ import (
"github.com/elastos/Elastos.ELA/core/types/outputpayload"
"github.com/elastos/Elastos.ELA/core/types/payload"
"github.com/elastos/Elastos.ELA/cr/state"
"github.com/elastos/Elastos.ELA/crypto"
msg2 "github.com/elastos/Elastos.ELA/dpos/p2p/msg"
elaerr "github.com/elastos/Elastos.ELA/errors"
"github.com/elastos/Elastos.ELA/events"
"github.com/elastos/Elastos.ELA/p2p"
"github.com/elastos/Elastos.ELA/p2p/msg"
"github.com/elastos/Elastos.ELA/utils"
"github.com/elastos/Elastos.ELA/vm"
)

// ProducerState represents the state of a producer.
Expand Down Expand Up @@ -1996,14 +1994,6 @@ func (s *State) processVoting(tx interfaces.Transaction, height uint32) {
func (s *State) processVotingContent(tx interfaces.Transaction, height uint32) {
// get stake address(program hash)
code := tx.Programs()[0].Code
signType, _ := crypto.GetScriptType(code)
var prefixType byte
if signType == vm.CHECKSIG {
prefixType = byte(contract.PrefixStandard)
} else if signType == vm.CHECKMULTISIG {
prefixType = byte(contract.PrefixMultiSig)
}

ct, _ := contract.CreateStakeContractByCode(code)
stakeAddress := ct.ToProgramHash()
pld := tx.Payload().(*payload.Voting)
Expand Down Expand Up @@ -2075,7 +2065,6 @@ func (s *State) processVotingContent(tx interfaces.Transaction, height uint32) {
PayloadVersion: tx.PayloadVersion(),
VoteType: content.VoteType,
Info: []payload.VotesWithLockTime{voteInfo},
PrefixType: prefixType,
}
s.History.Append(height, func() {
if producer.detailedDPoSV2Votes == nil {
Expand Down Expand Up @@ -2110,14 +2099,6 @@ func (s *State) processRenewalVotingContent(tx interfaces.Transaction, height ui
code := tx.Programs()[0].Code
ct, _ := contract.CreateStakeContractByCode(code)
stakeAddress := ct.ToProgramHash()
signType, _ := crypto.GetScriptType(code)
var prefixType byte
if signType == vm.CHECKSIG {
prefixType = byte(contract.PrefixStandard)
} else if signType == vm.CHECKMULTISIG {
prefixType = byte(contract.PrefixMultiSig)
}

pld := tx.Payload().(*payload.Voting)
for _, cont := range pld.RenewalContents {
content := cont
Expand All @@ -2137,7 +2118,6 @@ func (s *State) processRenewalVotingContent(tx interfaces.Transaction, height ui
PayloadVersion: voteInfo.PayloadVersion,
VoteType: outputpayload.DposV2,
Info: []payload.VotesWithLockTime{content.VotesInfo},
PrefixType: prefixType,
}

s.LastRenewalDPoSV2Votes[content.ReferKey] = struct{}{}
Expand Down Expand Up @@ -2555,7 +2535,8 @@ func (s *State) processDposV2ClaimReward(tx interfaces.Transaction, height uint3
}

programHash, _ := utils.GetProgramHashByCode(code)
addr, _ := programHash.ToAddress()
stakeProgramHash := common.Uint168FromCodeHash(byte(contract.PrefixDPoSV2), programHash.ToCodeHash())
addr, _ := stakeProgramHash.ToAddress()
s.History.Append(height, func() {
s.DPoSV2RewardInfo[addr] -= pld.Value
s.DposV2RewardClaimingInfo[addr] += pld.Value
Expand Down
4 changes: 2 additions & 2 deletions elanet/netsync/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -900,10 +900,10 @@ func (sm *SyncManager) handleBlockchainEvents(event *events.Event) {
iv := msg.NewInvVect(msg.InvTypeTx, &txHash)
sm.peerNotifier.RelayInventory(iv, tx)
}
case events.ETResendOutdatedTxToTxPool:
case events.ETOutdatedTxRelay:
txs, ok := event.Data.([]interfaces.Transaction)
if !ok {
log.Error("ETResendOutdatedTxToTxPool event is not a tx list")
log.Error("ETOutdatedTxRelay event is not a tx list")
}
for _, tx := range txs {
txHash := tx.Hash()
Expand Down
6 changes: 3 additions & 3 deletions events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const (
//chain transaction
ETSmallCrossChainNeedRelay

//ETResendOutdatedTxToTxPool indicates that need to resend outdate tx to tx pool
ETResendOutdatedTxToTxPool
//ETOutdatedTxRelay indicates that need to resend outdate tx to tx pool
ETOutdatedTxRelay
)

// notificationTypeStrings is a map of notification types back to their constant
Expand All @@ -92,7 +92,7 @@ var notificationTypeStrings = map[EventType]string{
ETAppendTxToTxPoolWithoutRelay: "ETAppendTxToTxPoolWithoutRelay",
ETCRCChangeCommittee: "ETCRCChangeCommittee",
ETSmallCrossChainNeedRelay: "ETSmallCrossChainNeedRelay",
ETResendOutdatedTxToTxPool: "ETResendOutdatedTxToTxPool",
ETOutdatedTxRelay: "ETOutdatedTxRelay",
}

// String returns the EventType in human-readable form.
Expand Down
2 changes: 1 addition & 1 deletion mempool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func (mp *TxPool) ResendOutdatedTransactions(block *Block) {
}

if len(txs) != 0 {
go events.Notify(events.ETResendOutdatedTxToTxPool, txs)
go events.Notify(events.ETOutdatedTxRelay, txs)
}
mp.Unlock()
}
Expand Down
Loading

0 comments on commit df14512

Please sign in to comment.