Skip to content

Commit

Permalink
Merge pull request #3302 from AElfProject/fix/all-tob-issues
Browse files Browse the repository at this point in the history
[WIP] Fix all TOB issues.
  • Loading branch information
jason-aelf authored Aug 30, 2021
2 parents 02a52fb + 4d21e0d commit 91eed51
Show file tree
Hide file tree
Showing 72 changed files with 1,376 additions and 719 deletions.
Binary file removed audits/AElf Audit Report - SlowMist.pdf
Binary file not shown.
Binary file removed audits/AElf Audit Report - Trail of Bits.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ private bool DonateMiningReward(Round previousRound)
}

var miningRewardPerBlock = GetMiningRewardPerBlock();
var amount = previousRound.GetMinedBlocks().Mul(miningRewardPerBlock);
var minedBlocks = previousRound.GetMinedBlocks();
var amount = minedBlocks.Mul(miningRewardPerBlock);
State.TreasuryContract.UpdateMiningReward.Send(new Int64Value {Value = miningRewardPerBlock});

if (amount > 0)
Expand Down
4 changes: 2 additions & 2 deletions contract/AElf.Contracts.Economic/EconomicContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ private void SetTreasurySchemeIdsToElectionContract()
State.ElectionContract.SetTreasurySchemeIds.Send(new SetTreasurySchemeIdsInput
{
TreasuryHash = schemeIdsManagingByTreasuryContract[0],
VotesRewardHash = schemeIdsManagingByTreasuryContract[3],
ReElectionRewardHash = schemeIdsManagingByTreasuryContract[4],
WelcomeHash = schemeIdsManagingByTreasuryContract[3],
FlexibleHash = schemeIdsManagingByTreasuryContract[4],
SubsidyHash = schemeIdsManagingByElectionContract[0],
WelfareHash = schemeIdsManagingByElectionContract[1]
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public partial class ElectionContractState
internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; }
internal AEDPoSContractContainer.AEDPoSContractReferenceState AEDPoSContract { get; set; }
internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; }
internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract{ get; set; }
internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; }
}
}
6 changes: 4 additions & 2 deletions contract/AElf.Contracts.Election/ElectionContractState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public partial class ElectionContractState : ContractState
public SingletonState<Hash> TreasuryHash { get; set; }
public SingletonState<Hash> WelfareHash { get; set; }
public SingletonState<Hash> SubsidyHash { get; set; }
public SingletonState<Hash> VotesRewardHash { get; set; }
public SingletonState<Hash> ReElectionRewardHash { get; set; }
public SingletonState<Hash> FlexibleHash { get; set; }
public SingletonState<Hash> WelcomeHash { get; set; }

public MappedState<string, ElectorVote> ElectorVotes { get; set; }

Expand Down Expand Up @@ -81,5 +81,7 @@ public partial class ElectionContractState : ContractState
/// Initial pubkey -> Newest pubkey
/// </summary>
public MappedState<string, string> InitialToNewestPubkeyMap { get; set; }

public SingletonState<Address> EmergencyResponseOrganizationAddress { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public override Empty QuitElection(StringValue input)
if (dataCenterList.DataCenters.ContainsKey(pubkey))
{
dataCenterList.DataCenters[pubkey] = 0;
IsUpdateDataCenterAfterMemberVoteAmountChange(dataCenterList, pubkey, true);
UpdateDataCenterAfterMemberVoteAmountChanged(dataCenterList, pubkey, true);
State.DataCentersRankingList.Value = dataCenterList;
}

Expand Down
35 changes: 16 additions & 19 deletions contract/AElf.Contracts.Election/ElectionContract_Elector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,13 @@ public override Empty ChangeVotingOption(ChangeVotingOptionInput input)
});
}
else
IsCandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate);
CandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate);

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

State.DataCentersRankingList.Value = dataCenterList;
Expand Down Expand Up @@ -373,22 +373,21 @@ public override Empty Withdraw(Hash input)
if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty();
rankingList.DataCenters[newestPubkey] =
rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount);
IsUpdateDataCenterAfterMemberVoteAmountChange(rankingList, newestPubkey);
UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, newestPubkey);
State.DataCentersRankingList.Value = rankingList;

return new Empty();
}

private bool IsUpdateDataCenterAfterMemberVoteAmountChange(DataCenterRankingList rankingList, string member,
private void UpdateDataCenterAfterMemberVoteAmountChanged(DataCenterRankingList rankingList, string targetMember,
bool isForceReplace = false)
{
var amountAfterWithdraw = rankingList.DataCenters[member];
var amountAfterWithdraw = rankingList.DataCenters[targetMember];
if(isForceReplace)
Assert(amountAfterWithdraw == 0, "should update vote amount in data center firstly");
else
if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw))
return false;

else if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw))
return;

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);
Expand All @@ -404,7 +403,7 @@ private bool IsUpdateDataCenterAfterMemberVoteAmountChange(DataCenterRankingList

if (isForceReplace)
{
rankingList.DataCenters.Remove(member);
rankingList.DataCenters.Remove(targetMember);
if (maxVoteCandidateOutDataCenter == null)
{
maxVoteCandidateOutDataCenter = State.Candidates.Value.Value.Select(x => x.ToHex())
Expand All @@ -419,33 +418,31 @@ private bool IsUpdateDataCenterAfterMemberVoteAmountChange(DataCenterRankingList
else
{
if (maxVoteAmountOutOfDataCenter <= amountAfterWithdraw)
return false;
rankingList.DataCenters.Remove(member);
return;
rankingList.DataCenters.Remove(targetMember);
}
if (maxVoterPublicKeyStringOutOfDataCenter != null)
{
rankingList.DataCenters[maxVoterPublicKeyStringOutOfDataCenter] = maxVoteAmountOutOfDataCenter;
}

NotifyProfitReplaceCandidateInDataCenter(member, maxVoterPublicKeyStringOutOfDataCenter);
return true;
NotifyProfitReplaceCandidateInDataCenter(targetMember, maxVoterPublicKeyStringOutOfDataCenter);
}

private bool IsCandidateReplaceMemberInDataCenter(DataCenterRankingList rankingList, string candidate,
private void CandidateReplaceMemberInDataCenter(DataCenterRankingList rankingList, string candidate,
long voteAmount)
{
var dateCenter = rankingList.DataCenters;
if (dateCenter.Count < GetValidationDataCenterCount())
return false;
return;
if (dateCenter.ContainsKey(candidate))
return false;
return;
var list = dateCenter.ToList();
var minimumVoteCandidateInDataCenter = list.OrderBy(x => x.Value).First();
if (voteAmount <= minimumVoteCandidateInDataCenter.Value) return false;
if (voteAmount <= minimumVoteCandidateInDataCenter.Value) return;
dateCenter.Remove(minimumVoteCandidateInDataCenter.Key);
dateCenter[candidate] = voteAmount;
NotifyProfitReplaceCandidateInDataCenter(minimumVoteCandidateInDataCenter.Key, candidate);
return true;
}

private void NotifyProfitReplaceCandidateInDataCenter(string oldCandidateInDataCenter,
Expand Down
72 changes: 59 additions & 13 deletions contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public override Empty InitialElectionContract(InitialElectionContractInput input
State.MinersCount.Value = input.MinerList.Count;
State.InitialMiners.Value = new PubkeyList
{
Value = {input.MinerList.Select(ByteStringHelper.FromHexString)}
Value = { input.MinerList.Select(ByteStringHelper.FromHexString) }
};
foreach (var pubkey in input.MinerList)
{
Expand All @@ -47,6 +47,7 @@ public override Empty InitialElectionContract(InitialElectionContractInput input
State.DataCentersRankingList.Value = new DataCenterRankingList();

State.Initialized.Value = true;

return new Empty();
}

Expand Down Expand Up @@ -126,14 +127,14 @@ public override Empty TakeSnapshot(TakeElectionSnapshotInput input)
{
SchemeId = State.SubsidyHash.Value,
Period = input.TermNumber,
AmountsMap = {amountsMap}
AmountsMap = { amountsMap }
});

State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput
{
SchemeId = State.WelfareHash.Value,
Period = input.TermNumber,
AmountsMap = {amountsMap}
AmountsMap = { amountsMap }
});

return new Empty();
Expand Down Expand Up @@ -187,7 +188,8 @@ private void UpdateCandidateInformation(string pubkey, long lastTermNumber,
public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput input)
{
Assert(
Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender,
Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) ==
Context.Sender || Context.Sender == GetEmergencyResponseOrganizationAddress(),
"Only consensus contract can update candidate information.");

var candidateInformation = State.CandidateInformationMap[input.Pubkey];
Expand All @@ -204,15 +206,21 @@ public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput
if (rankingList.DataCenters.ContainsKey(input.Pubkey))
{
rankingList.DataCenters[input.Pubkey] = 0;
IsUpdateDataCenterAfterMemberVoteAmountChange(rankingList, input.Pubkey, true);
UpdateDataCenterAfterMemberVoteAmountChanged(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});
Context.Fire(new EvilMinerDetected { Pubkey = input.Pubkey });
State.CandidateInformationMap.Remove(input.Pubkey);
var candidates = State.Candidates.Value;
candidates.Value.Remove(ByteString.CopyFrom(publicKeyByte));
State.Candidates.Value = candidates;
State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput
{
SchemeId = State.SubsidyHash.Value,
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey))
});
return new Empty();
}

Expand All @@ -223,6 +231,25 @@ public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput
return new Empty();
}

private Address GetEmergencyResponseOrganizationAddress()
{
if (State.EmergencyResponseOrganizationAddress.Value != null)
{
return State.EmergencyResponseOrganizationAddress.Value;
}

if (State.ParliamentContract.Value == null)
{
State.ParliamentContract.Value =
Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName);
}

State.EmergencyResponseOrganizationAddress.Value =
State.ParliamentContract.GetEmergencyResponseOrganizationAddress.Call(new Empty());

return State.EmergencyResponseOrganizationAddress.Value;
}

public override Empty UpdateMultipleCandidateInformation(UpdateMultipleCandidateInformationInput input)
{
Assert(
Expand Down Expand Up @@ -256,8 +283,8 @@ public override Empty SetTreasurySchemeIds(SetTreasurySchemeIdsInput input)
State.TreasuryHash.Value = input.TreasuryHash;
State.WelfareHash.Value = input.WelfareHash;
State.SubsidyHash.Value = input.SubsidyHash;
State.ReElectionRewardHash.Value = input.ReElectionRewardHash;
State.VotesRewardHash.Value = input.VotesRewardHash;
State.WelcomeHash.Value = input.WelcomeHash;
State.FlexibleHash.Value = input.FlexibleHash;
return new Empty();
}

Expand All @@ -269,7 +296,7 @@ public override Empty ReplaceCandidatePubkey(ReplaceCandidatePubkeyInput input)
"Pubkey is in already banned.");

// Permission check.
Assert(Context.Sender == GetCandidateAdmin(new StringValue {Value = input.OldPubkey}), "No permission.");
Assert(Context.Sender == GetCandidateAdmin(new StringValue { Value = input.OldPubkey }), "No permission.");

// Record the replacement.
PerformReplacement(input.OldPubkey, input.NewPubkey);
Expand All @@ -293,14 +320,14 @@ 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,
Expand Down Expand Up @@ -373,6 +400,7 @@ private void PerformReplacement(string oldPubkey, string newPubkey)
State.AEDPoSContract.Value =
Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName);
}

State.AEDPoSContract.RecordCandidateReplacement.Send(new RecordCandidateReplacementInput
{
OldPubkey = oldPubkey,
Expand Down Expand Up @@ -400,15 +428,32 @@ private void PerformReplacement(string oldPubkey, string newPubkey)

public override StringValue GetNewestPubkey(StringValue input)
{
return new StringValue {Value = GetNewestPubkey(input.Value)};
return new StringValue { Value = GetNewestPubkey(input.Value) };
}

public override Empty RemoveEvilNode(StringValue input)
{
Assert(Context.Sender == GetEmergencyResponseOrganizationAddress(), "No permission.");
var address = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value));
Assert(
State.Candidates.Value.Value.Select(p => p.ToHex()).Contains(input.Value) ||
State.InitialMiners.Value.Value.Select(p => p.ToHex()).Contains(input.Value),
"Cannot remove normal node.");
Assert(!State.BannedPubkeyMap[input.Value], $"{input.Value} already banned.");
UpdateCandidateInformation(new UpdateCandidateInformationInput
{
Pubkey = input.Value,
IsEvilNode = true
});
return new Empty();
}

private string GetNewestPubkey(string pubkey)
{
var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey;
return State.InitialToNewestPubkeyMap[initialPubkey] ?? initialPubkey;
}

private void SyncSubsidyInfoAfterReduceMiner()
{
var rankingList = State.DataCentersRankingList.Value;
Expand All @@ -429,6 +474,7 @@ private void SyncSubsidyInfoAfterReduceMiner()
Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(kv.Key))
});
}

State.DataCentersRankingList.Value = rankingList;
}
}
Expand Down
Loading

0 comments on commit 91eed51

Please sign in to comment.