Skip to content

Commit

Permalink
Merge pull request #3134 from AElfProject/syn-subsidy-dividend
Browse files Browse the repository at this point in the history
Synchronize Subsidy Dividend Information
  • Loading branch information
shiwk authored Dec 8, 2020
2 parents 96d4dc6 + a30cfc0 commit b2e7f3e
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ public override Empty SetMaximumMinersCount(Int32Value input)
RequiredMaximumMinersCountControllerSet();
Assert(Context.Sender == State.MaximumMinersCountController.Value.OwnerAddress,
"No permission to set max miners count.");
// Only update miners count if 1) Max Miners Count is decreased; 2) Input value is less than auto Increasing miners count
if (State.MaximumMinersCount.Value > input.Value && GetAutoIncreasedMinersCount() > input.Value)
{
State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput
{
MinersCount = input.Value
});
}

TryToGetCurrentRoundInformation(out Round round);

State.MaximumMinersCount.Value = input.Value;
State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput
{
MinersCount = GetMinersCount(round)
});

return new Empty();
}

Expand Down
11 changes: 1 addition & 10 deletions contract/AElf.Contracts.Election/ElectionContract_Candidate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,7 @@ public override Empty QuitElection(StringValue input)
if (dataCenterList.DataCenters.ContainsKey(pubkey))
{
dataCenterList.DataCenters[pubkey] = 0;
if (!IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, pubkey))
{
State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Context.Sender
});
dataCenterList.DataCenters.Remove(pubkey);
}

IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, pubkey, true);
State.DataCentersRankingList.Value = dataCenterList;
}

Expand Down
138 changes: 98 additions & 40 deletions contract/AElf.Contracts.Election/ElectionContract_Elector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,34 @@ public override Hash Vote(VoteMinerInput input)
AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds);

var rankingList = State.DataCentersRankingList.Value;
if (State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
if (rankingList.DataCenters.ContainsKey(input.CandidatePubkey))
{
rankingList.DataCenters[input.CandidatePubkey] =
rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount);
State.DataCentersRankingList.Value = rankingList;
}

if (State.Candidates.Value.Value.Count > GetValidationDataCenterCount() &&
!State.DataCentersRankingList.Value.DataCenters.ContainsKey(input.CandidatePubkey))
else
{
TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList);
if (rankingList.DataCenters.Count < GetValidationDataCenterCount())
{
State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey,
candidateVotesAmount);
State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
BeneficiaryShare = new BeneficiaryShare
{
Beneficiary =
Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)),
Shares = 1
}
});
}
else
{
TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList);
}
}

return voteId;
}

Expand Down Expand Up @@ -236,14 +251,14 @@ public override Empty ChangeVotingOption(ChangeVotingOptionInput input)
});

// Update related candidate
var newestPubkey = GetNewestPubkey(votingRecord.Option);
var oldCandidateVotes = State.CandidateVotes[newestPubkey];
var oldVoteOptionPublicKey = GetNewestPubkey(votingRecord.Option);
var oldCandidateVotes = State.CandidateVotes[oldVoteOptionPublicKey];
oldCandidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId);
oldCandidateVotes.ObtainedActiveVotedVotesAmount =
oldCandidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount);
oldCandidateVotes.AllObtainedVotedVotesAmount =
oldCandidateVotes.AllObtainedVotedVotesAmount.Sub(votingRecord.Amount);
State.CandidateVotes[newestPubkey] = oldCandidateVotes;
State.CandidateVotes[oldVoteOptionPublicKey] = oldCandidateVotes;

long voteAmountOfNewCandidate;
var newCandidateVotes = State.CandidateVotes[input.CandidatePubkey];
Expand Down Expand Up @@ -273,13 +288,31 @@ public override Empty ChangeVotingOption(ChangeVotingOptionInput input)
if (dataCenterList.DataCenters.ContainsKey(input.CandidatePubkey))
dataCenterList.DataCenters[input.CandidatePubkey] =
dataCenterList.DataCenters[input.CandidatePubkey].Add(votingRecord.Amount);
else if (dataCenterList.DataCenters.Count < GetValidationDataCenterCount())
{
// add data center
dataCenterList.DataCenters.Add(input.CandidatePubkey,
State.CandidateVotes[input.CandidatePubkey].ObtainedActiveVotedVotesAmount);

State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
BeneficiaryShare = new BeneficiaryShare
{
Beneficiary =
Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)),
Shares = 1
}
});
}
else
IsCandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate);
if (dataCenterList.DataCenters.ContainsKey(newestPubkey))

if (dataCenterList.DataCenters.ContainsKey(oldVoteOptionPublicKey))
{
dataCenterList.DataCenters[newestPubkey] =
dataCenterList.DataCenters[newestPubkey].Sub(votingRecord.Amount);
IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, newestPubkey);
dataCenterList.DataCenters[oldVoteOptionPublicKey] =
dataCenterList.DataCenters[oldVoteOptionPublicKey].Sub(votingRecord.Amount);
IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, oldVoteOptionPublicKey);
}

State.DataCentersRankingList.Value = dataCenterList;
Expand Down Expand Up @@ -337,41 +370,64 @@ public override Empty Withdraw(Hash input)
RemoveBeneficiaryOfVoter();

var rankingList = State.DataCentersRankingList.Value;
if (State.DataCentersRankingList.Value.DataCenters.ContainsKey(newestPubkey))
{
rankingList.DataCenters[newestPubkey] =
rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount);
IsUpdateDataCenterAfterMemberVoteAmountChange(rankingList, newestPubkey);
State.DataCentersRankingList.Value = rankingList;
}
if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty();
rankingList.DataCenters[newestPubkey] =
rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount);
IsUpdateDataCenterAfterMemberVoteAmountChange(rankingList, newestPubkey);
State.DataCentersRankingList.Value = rankingList;

return new Empty();
}

private bool IsUpdateDataCenterAfterMemberVoteAmountChange(DataCenterRankingList rankingList, string member)
private bool IsUpdateDataCenterAfterMemberVoteAmountChange(DataCenterRankingList rankingList, string member,
bool isForceReplace = false)
{
var amountAfterWithdraw = rankingList.DataCenters[member];
if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw))
return false;
long maxVoteAmountOutDataCenter = 0;
string maxVoteOptionOutDataCenter = null;
foreach (var candidateByteString in State.Candidates.Value.Value)
{
var candidatePublicKeyString = candidateByteString.ToHex();
if (rankingList.DataCenters.ContainsKey(candidatePublicKeyString) ||
!State.CandidateInformationMap[candidatePublicKeyString].IsCurrentCandidate) continue;
var candidateVoteAmount = State.CandidateVotes[candidatePublicKeyString].ObtainedActiveVotedVotesAmount;
if (maxVoteAmountOutDataCenter > candidateVoteAmount)
continue;
maxVoteOptionOutDataCenter = candidatePublicKeyString;
maxVoteAmountOutDataCenter = candidateVoteAmount;
if(isForceReplace)
Assert(amountAfterWithdraw == 0, "should update vote amount in data center firstly");
else
if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw))
return false;

var validCandidates = State.Candidates.Value.Value.Select(x => x.ToHex())
.Where(c => !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] != null)
.OrderByDescending(x => State.CandidateVotes[x].ObtainedActiveVotedVotesAmount);
string maxVoterPublicKeyStringOutOfDataCenter = null;
long maxVoteAmountOutOfDataCenter = 0;
var maxVoteCandidateOutDataCenter = validCandidates.FirstOrDefault();
if (maxVoteCandidateOutDataCenter != null)
{
maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter;
maxVoteAmountOutOfDataCenter = State.CandidateVotes[maxVoteCandidateOutDataCenter]
.ObtainedActiveVotedVotesAmount;
}

if (maxVoteAmountOutDataCenter <= amountAfterWithdraw || maxVoteOptionOutDataCenter == null)
return false;
rankingList.DataCenters.Remove(member);
rankingList.DataCenters[maxVoteOptionOutDataCenter] = maxVoteAmountOutDataCenter;
NotifyProfitReplaceCandidateInDataCenter(member, maxVoteOptionOutDataCenter);
if (isForceReplace)
{
rankingList.DataCenters.Remove(member);
if (maxVoteCandidateOutDataCenter == null)
{
maxVoteCandidateOutDataCenter = State.Candidates.Value.Value.Select(x => x.ToHex())
.FirstOrDefault(c => !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] == null);
if (maxVoteCandidateOutDataCenter != null)
{
maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter;
maxVoteAmountOutOfDataCenter = 0;
}
}
}
else
{
if (maxVoteAmountOutOfDataCenter <= amountAfterWithdraw)
return false;
rankingList.DataCenters.Remove(member);
}
if (maxVoterPublicKeyStringOutOfDataCenter != null)
{
rankingList.DataCenters[maxVoterPublicKeyStringOutOfDataCenter] = maxVoteAmountOutOfDataCenter;
}

NotifyProfitReplaceCandidateInDataCenter(member, maxVoterPublicKeyStringOutOfDataCenter);
return true;
}

Expand Down Expand Up @@ -400,6 +456,8 @@ private void NotifyProfitReplaceCandidateInDataCenter(string oldCandidateInDataC
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(oldCandidateInDataCenter))
});
if (newCandidateDataCenter == null)
return;
State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Expand Down
80 changes: 52 additions & 28 deletions contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,13 @@ public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput
{
var publicKeyByte = ByteArrayHelper.HexStringToByteArray(input.Pubkey);
State.BannedPubkeyMap[input.Pubkey] = true;
if (State.ProfitContract.Value == null)
State.ProfitContract.Value =
Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName);
State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
var rankingList = State.DataCentersRankingList.Value;
if (rankingList.DataCenters.ContainsKey(input.Pubkey))
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(publicKeyByte)
});
rankingList.DataCenters[input.Pubkey] = 0;
IsUpdateDataCenterAfterMemberVoteAmountChange(rankingList, input.Pubkey, true);
State.DataCentersRankingList.Value = rankingList;
}
Context.LogDebug(() => $"Marked {input.Pubkey.Substring(0, 10)} as an evil node.");
Context.Fire(new EvilMinerDetected {Pubkey = input.Pubkey});
State.CandidateInformationMap.Remove(input.Pubkey);
Expand Down Expand Up @@ -247,6 +246,7 @@ public override Empty UpdateMinersCount(UpdateMinersCountInput input)
Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender,
"Only consensus contract can update miners count.");
State.MinersCount.Value = input.MinersCount;
SyncSubsidyInfoAfterReduceMiner();
return new Empty();
}

Expand Down Expand Up @@ -293,6 +293,28 @@ public override Empty ReplaceCandidatePubkey(ReplaceCandidatePubkeyInput input)
rankingList.DataCenters.Add(input.NewPubkey, rankingList.DataCenters[input.OldPubkey]);
rankingList.DataCenters.Remove(input.OldPubkey);
State.DataCentersRankingList.Value = rankingList;

// Notify Profit Contract to update backup subsidy profiting item.
if (State.ProfitContract.Value == null)
{
State.ProfitContract.Value =
Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName);
}

State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(oldPubkeyBytes.ToByteArray())
});
State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
BeneficiaryShare = new BeneficiaryShare
{
Beneficiary = Address.FromPublicKey(newPubkeyBytes.ToByteArray()),
Shares = 1
}
});
}

var initialMiners = State.InitialMiners.Value;
Expand Down Expand Up @@ -357,27 +379,6 @@ private void PerformReplacement(string oldPubkey, string newPubkey)
NewPubkey = newPubkey
});

// Notify Profit Contract to update backup subsidy profiting item.
if (State.ProfitContract.Value == null)
{
State.ProfitContract.Value =
Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName);
}
State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(oldPubkey))
});
State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
BeneficiaryShare = new BeneficiaryShare
{
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(newPubkey)),
Shares = 1
}
});

// Notify Vote Contract to replace option if this is not the initial miner case.
if (!State.InitialMiners.Value.Value.Contains(
ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(oldPubkey))))
Expand Down Expand Up @@ -407,5 +408,28 @@ private string GetNewestPubkey(string pubkey)
var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey;
return State.InitialToNewestPubkeyMap[initialPubkey] ?? initialPubkey;
}

private void SyncSubsidyInfoAfterReduceMiner()
{
var rankingList = State.DataCentersRankingList.Value;
if (rankingList == null)
return;
var validDataCenterCount = GetValidationDataCenterCount();
if (rankingList.DataCenters.Count <= validDataCenterCount) return;
Context.LogDebug(() => "sync DataCenter after reduce bp");
var diffCount = rankingList.DataCenters.Count.Sub(validDataCenterCount);
var toRemoveList = rankingList.DataCenters.OrderBy(x => x.Value)
.Take(diffCount).ToList();
foreach (var kv in toRemoveList)
{
rankingList.DataCenters.Remove(kv.Key);
State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(kv.Key))
});
}
State.DataCentersRankingList.Value = rankingList;
}
}
}
1 change: 0 additions & 1 deletion protobuf/election_contract.proto
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,6 @@ message SetTreasurySchemeIdsInput {
message DataCenterRankingList {
// The top n * 5 candidates with vote amount, candidate public key -> vote amount.
map<string, int64> data_centers = 1;
int64 minimum_votes = 2;
}

message VoteWeightInterest{
Expand Down
4 changes: 2 additions & 2 deletions src/AElf.OS.Network.Grpc/Connection/ConnectionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private async Task<GrpcPeer> GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint
}
else
{
Logger.LogWarning($"Peer with endpoint {endpoint} is already in the pool.");
Logger.LogDebug($"Peer with endpoint {endpoint} is already in the pool.");
return null;
}
}
Expand All @@ -202,7 +202,7 @@ private async Task<GrpcPeer> GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint

if (_peerPool.IsOverIpLimit(endpoint.Host))
{
Logger.LogWarning($"{endpoint.Host} - peer pool is full.");
Logger.LogDebug($"{endpoint.Host} is over ip limit.");
return null;
}

Expand Down
Loading

0 comments on commit b2e7f3e

Please sign in to comment.