Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix economic system bugs. #1705

Merged
merged 17 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions protobuf/profit_contract.proto
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ message ReleaseProfitInput {
Hash profit_id = 1;
sint64 period = 2;
sint64 amount = 3;
sint64 total_weight = 4;
}

message ProfitDetails {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ private void TryToFindLastIrreversibleBlock()
Context.LogDebug(() => $"LIB found, offset is {offset}");
Context.Fire(new IrreversibleBlockFound()
{
Offset = offset.Mul(AElfConsensusContractConstants.TinyBlocksNumber)
Offset = offset.Mul(AEDPoSContractConstants.TinyBlocksNumber)
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace AElf.Contracts.Consensus.AEDPoS
{
public static class AElfConsensusContractConstants
public static class AEDPoSContractConstants
{
public const int TinyBlocksNumber = 8;
}
Expand Down
16 changes: 8 additions & 8 deletions src/AElf.Contracts.Consensus.AEDPoS/HelpMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private AElfConsensusBehaviour GetBehaviour(string publicKey, DateTime dateTime,

if (currentRound.ExtraBlockProducerOfPreviousRound == publicKey &&
dateTime < currentRound.GetStartTime() &&
minerInRound.ProducedTinyBlocks < AElfConsensusContractConstants.TinyBlocksNumber)
minerInRound.ProducedTinyBlocks < AEDPoSContractConstants.TinyBlocksNumber)
{
return AElfConsensusBehaviour.TinyBlock;
}
Expand All @@ -61,12 +61,12 @@ private AElfConsensusBehaviour GetBehaviour(string publicKey, DateTime dateTime,
return AElfConsensusBehaviour.UpdateValue;
}
}
else if (minerInRound.ProducedTinyBlocks < AElfConsensusContractConstants.TinyBlocksNumber)
else if (minerInRound.ProducedTinyBlocks < AEDPoSContractConstants.TinyBlocksNumber)
{
return AElfConsensusBehaviour.TinyBlock;
}
else if (currentRound.ExtraBlockProducerOfPreviousRound == publicKey &&
minerInRound.ProducedTinyBlocks < AElfConsensusContractConstants.TinyBlocksNumber.Mul(2))
minerInRound.ProducedTinyBlocks < AEDPoSContractConstants.TinyBlocksNumber.Mul(2))
{
return AElfConsensusBehaviour.TinyBlock;
}
Expand Down Expand Up @@ -143,22 +143,22 @@ private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, R
if (currentRound.ExtraBlockProducerOfPreviousRound != publicKey)
{
expectedMiningTime = expectedMiningTime.ToDateTime().AddMilliseconds(producedTinyBlocks
.Mul(miningInterval).Div(AElfConsensusContractConstants.TinyBlocksNumber))
.Mul(miningInterval).Div(AEDPoSContractConstants.TinyBlocksNumber))
.ToTimestamp();
}
else
{
// EBP of previous round will produce double tiny blocks. This is for normal time slot of current round.
expectedMiningTime = expectedMiningTime.ToDateTime().AddMilliseconds(producedTinyBlocks
.Sub(AElfConsensusContractConstants.TinyBlocksNumber)
.Mul(miningInterval).Div(AElfConsensusContractConstants.TinyBlocksNumber)).ToTimestamp();
.Sub(AEDPoSContractConstants.TinyBlocksNumber)
.Mul(miningInterval).Div(AEDPoSContractConstants.TinyBlocksNumber)).ToTimestamp();
}
}
else if (previousRound != null)
{
// EBP of previous round will produce double tiny blocks. This is for extra time slot of previous round.
expectedMiningTime = previousRound.GetExtraBlockMiningTime().AddMilliseconds(producedTinyBlocks
.Mul(miningInterval).Div(AElfConsensusContractConstants.TinyBlocksNumber)).ToTimestamp();
.Mul(miningInterval).Div(AEDPoSContractConstants.TinyBlocksNumber)).ToTimestamp();
}

nextBlockMiningLeftMilliseconds =
Expand Down Expand Up @@ -192,7 +192,7 @@ private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, R
{
ExpectedMiningTime = expectedMiningTime,
NextBlockMiningLeftMilliseconds = nextBlockMiningLeftMilliseconds,
LimitMillisecondsOfMiningBlock = miningInterval / AElfConsensusContractConstants.TinyBlocksNumber,
LimitMillisecondsOfMiningBlock = miningInterval / AEDPoSContractConstants.TinyBlocksNumber,
Hint = hint
};
}
Expand Down
12 changes: 10 additions & 2 deletions src/AElf.Contracts.Consensus.AEDPoS/ViewMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,16 @@ private string GetNextAvailableMinerPublicKey(Round round)

private int GetMinersCount()
{
return ((int) Context.CurrentBlockTime.Subtract(State.BlockchainStartTimestamp.Value.ToDateTime())
.TotalDays).Div(7);
if (TryToGetRoundInformation(1, out var firstRound))
{
// TODO: Maybe this should according to date, like every July 1st we increase 2 miners.
var initialMinersCount = firstRound.RealTimeMinersInformation.Count;
return initialMinersCount.Add(((int) Context.CurrentBlockTime
.Subtract(State.BlockchainStartTimestamp.Value.ToDateTime())
.TotalDays).Div(365).Mul(2));
}

return 0;
}
}
}
3 changes: 2 additions & 1 deletion src/AElf.Contracts.Election/ElectionContractState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public partial class ElectionContractState : ContractState
public SingletonState<int> TimeEachTerm { get; set; }

public SingletonState<Hash> MinerElectionVotingItemId { get; set; }


public SingletonState<long> CachedWelfareWeight { get; set; }
}
}
6 changes: 5 additions & 1 deletion src/AElf.Contracts.Election/ElectionContract_Treasury.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,12 @@ private void ReleaseTreasurySubProfitItems(long termNumber)
State.ProfitContract.ReleaseProfit.Send(new ReleaseProfitInput
{
ProfitId = State.WelfareHash.Value,
Period = termNumber > 1 ? termNumber - 1 : -1
Period = termNumber > 1 ? termNumber - 1 : -1,
TotalWeight = State.CachedWelfareWeight.Value
});

State.CachedWelfareWeight.Value =
State.ProfitContract.GetProfitItem.Call(State.WelfareHash.Value).TotalWeight;
}

private void UpdateTreasurySubItemsWeights(long termNumber)
Expand Down
51 changes: 33 additions & 18 deletions src/AElf.Contracts.Profit/ProfitContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public override Hash CreateProfitItem(CreateProfitItemInput input)
{
profitId = Hash.FromTwoHashes(profitId, createdProfitIds.Last());
}

State.ProfitItemsMap[profitId] = new ProfitItem
{
VirtualAddress = Context.ConvertVirtualAddressToContractAddress(profitId),
Expand All @@ -75,7 +76,7 @@ public override Hash CreateProfitItem(CreateProfitItemInput input)
}

State.CreatedProfitItemsMap[Context.Sender] = createdProfitItems;

Context.LogDebug(() => $"Created profit item {profitId}");
return profitId;
}
Expand Down Expand Up @@ -145,7 +146,7 @@ public override Empty AddWeight(AddWeightInput input)
{
return new Empty();
}

Assert(input.EndPeriod >= profitItem.CurrentPeriod, "Invalid end period.");

profitItem.TotalWeight += input.Weight;
Expand Down Expand Up @@ -181,6 +182,8 @@ public override Empty AddWeight(AddWeightInput input)
}

State.ProfitDetailsMap[profitId][input.Receiver] = currentProfitDetails;

Context.LogDebug(() => $"Add {input.Weight} weights to profit item {input.ProfitId.ToHex()}");

return new Empty();
}
Expand Down Expand Up @@ -277,6 +280,8 @@ public override Empty ReleaseProfit(ReleaseProfitInput input)
return new Empty();
}

var totalWeight = input.TotalWeight == 0 ? profitItem.TotalWeight : input.TotalWeight;

Assert(Context.Sender == profitItem.Creator, "Only creator can release profits.");

var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.ProfitId);
Expand All @@ -294,17 +299,17 @@ public override Empty ReleaseProfit(ReleaseProfitInput input)
input.Amount = balance;
}

if (input.Period < 0 || profitItem.TotalWeight <= 0)
if (input.Period < 0 || totalWeight <= 0)
{
profitItem.CurrentPeriod = input.Period > 0 ? input.Period.Add(1) : profitItem.CurrentPeriod;

// Release to an address no one can receive profits.

if (input.Amount <= 0)
{
State.ProfitItemsMap[input.ProfitId] = profitItem;
return new Empty();
}

profitItem.CurrentPeriod = input.Period > 0 ? input.Period.Add(1) : profitItem.CurrentPeriod;

if (input.Period >= 0)
{
input.Period = -1;
Expand All @@ -320,15 +325,16 @@ public override Empty ReleaseProfit(ReleaseProfitInput input)
Amount = input.Amount,
Symbol = profitItem.TokenSymbol
});
profitItem.TotalAmount -= input.Amount;
profitItem.TotalAmount = profitItem.TotalAmount.Sub(input.Amount);
State.ProfitItemsMap[input.ProfitId] = profitItem;
return new Empty();
}

// Update current_period.
var releasingPeriod = profitItem.CurrentPeriod;

Assert(input.Period == releasingPeriod, $"Invalid period. When release profit item {input.ProfitId.ToHex()} of period {input.Period}");
Assert(input.Period == releasingPeriod,
$"Invalid period. When release profit item {input.ProfitId.ToHex()} of period {input.Period}. Current period is {releasingPeriod}");

var profitsReceivingVirtualAddress =
GetReleasedPeriodProfitsVirtualAddress(profitVirtualAddress, releasingPeriod);
Expand All @@ -338,29 +344,33 @@ public override Empty ReleaseProfit(ReleaseProfitInput input)
{
releasedProfitInformation = new ReleasedProfitsInformation
{
TotalWeight = profitItem.TotalWeight,
TotalWeight = totalWeight,
ProfitsAmount = input.Amount,
IsReleased = true
};
}
else
{
releasedProfitInformation.TotalWeight = profitItem.TotalWeight;
releasedProfitInformation.TotalWeight = totalWeight;
releasedProfitInformation.ProfitsAmount += input.Amount;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use safe plus

releasedProfitInformation.IsReleased = true;
}

State.ReleasedProfitsMap[profitsReceivingVirtualAddress] = releasedProfitInformation;

Context.LogDebug(() =>
$"Released profit information of {input.ProfitId.ToHex()} in period {input.Period}, " +
$"total weight {releasedProfitInformation.TotalWeight}, total amount {releasedProfitInformation.ProfitsAmount}");

// Start releasing.

var remainAmount = input.Amount;

foreach (var subProfitItem in profitItem.SubProfitItems)
{
var subItemVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subProfitItem.ProfitId);

var amount = subProfitItem.Weight.Mul(input.Amount).Div(profitItem.TotalWeight);
var amount = subProfitItem.Weight.Mul(input.Amount).Div(totalWeight);
if (amount != 0)
{
State.TokenContract.TransferFrom.Send(new TransferFromInput
Expand Down Expand Up @@ -468,6 +478,8 @@ public override Empty AddProfits(AddProfitsInput input)

public override Empty Profit(ProfitInput input)
{
Context.LogDebug(() => $"{Context.Sender} is trying to profit from {input.ProfitId.ToHex()}.");

var profitItem = State.ProfitItemsMap[input.ProfitId];
Assert(profitItem != null, "Profit item not found.");

Expand All @@ -482,7 +494,8 @@ public override Empty Profit(ProfitInput input)

var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.ProfitId);

var availableDetails = profitDetails.Details.Where(d => d.LastProfitPeriod != profitItem.CurrentPeriod).ToList();
var availableDetails = profitDetails.Details.Where(d => d.LastProfitPeriod != profitItem.CurrentPeriod)
.ToList();

for (var i = 0; i < Math.Min(ProfitContractConsts.ProfitLimit, availableDetails.Count); i++)
{
Expand All @@ -502,15 +515,18 @@ public override Empty Profit(ProfitInput input)
var releasedProfitsVirtualAddress =
GetReleasedPeriodProfitsVirtualAddress(profitVirtualAddress, period);
var releasedProfitsInformation = State.ReleasedProfitsMap[releasedProfitsVirtualAddress];
if (releasedProfitsInformation.IsReleased)
var amount = profitDetail.Weight.Mul(releasedProfitsInformation.ProfitsAmount)
.Div(releasedProfitsInformation.TotalWeight);
var period1 = period;
Context.LogDebug(() => $"{Context.Sender} is profiting {amount} tokens from {input.ProfitId.ToHex()} in period {period1}");
if (releasedProfitsInformation.IsReleased && amount > 0)
{
State.TokenContract.TransferFrom.Send(new TransferFromInput
{
From = releasedProfitsVirtualAddress,
To = Context.Sender,
Symbol = profitItem.TokenSymbol,
Amount = profitDetail.Weight.Mul(releasedProfitsInformation.ProfitsAmount)
.Div(releasedProfitsInformation.TotalWeight)
Amount = amount
});
}

Expand All @@ -524,6 +540,5 @@ public override Empty Profit(ProfitInput input)

return new Empty();
}

}
}
}
3 changes: 2 additions & 1 deletion src/AElf.Contracts.Profit/ViewMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public override ReleasedProfitsInformation GetReleasedProfitsInformation(
{
var virtualAddress = Context.ConvertVirtualAddressToContractAddress(input.ProfitId);
var releasedProfitsVirtualAddress = GetReleasedPeriodProfitsVirtualAddress(virtualAddress, input.Period);
return State.ReleasedProfitsMap[releasedProfitsVirtualAddress];
return State.ReleasedProfitsMap[releasedProfitsVirtualAddress] ?? new ReleasedProfitsInformation
{ProfitsAmount = -1, TotalWeight = -1};
}

public override ProfitDetails GetProfitDetails(GetProfitDetailsInput input)
Expand Down
4 changes: 1 addition & 3 deletions src/AElf.OS/Jobs/BlockSyncJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class BlockSyncJob
{
private const long InitialSyncLimit = 10;
private const int BlockSyncJobLimit = 200;
private const int BlockSyncWaitTime = 5000;

private readonly IBlockchainService _blockchainService;
private readonly INetworkService _networkService;
Expand Down Expand Up @@ -84,8 +83,7 @@ public async Task ExecuteAsync(BlockSyncJobArgs args)
if (chain.LongestChainHeight < blockHeight - BlockSyncJobLimit)
{
Logger.LogWarning($"Pause sync task and wait for synced block to be processed, best chain height: {chain.BestChainHeight}");
await Task.Delay(BlockSyncWaitTime);
continue;
break;
}

Logger.LogDebug($"Request blocks start with {blockHash}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class AElfConsensusContractTestBase : ContractTestBase<AEDPoSContractTest

protected const int MiningInterval = 4000;

protected const int SmallBlockMiningInterval = 500;
protected static int SmallBlockMiningInterval = MiningInterval.Div(AEDPoSContractConstants.TinyBlocksNumber);

protected const long DaysEachTerm = 7;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public async Task AElfConsensusContract_UpdateValueInFirstRound()
var command = await BootMiner.GetConsensusCommand.CallAsync(new CommandInput
{PublicKey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey)});
command.NextBlockMiningLeftMilliseconds.ShouldBe(MiningInterval);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AElfConsensusContractConstants.TinyBlocksNumber);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AEDPoSContractConstants.TinyBlocksNumber);
command.Hint.ShouldBe(new AElfConsensusHint
{Behaviour = AElfConsensusBehaviour.UpdateValueWithoutPreviousInValue}
.ToByteArray());
Expand All @@ -52,7 +52,7 @@ public async Task AElfConsensusContract_UpdateValueInFirstRound()
{PublicKey = ByteString.CopyFrom(otherMinerKeyPair.PublicKey)});
command.NextBlockMiningLeftMilliseconds.ShouldBe(
MiningInterval * InitialMinersCount + MiningInterval * order);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AElfConsensusContractConstants.TinyBlocksNumber);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AEDPoSContractConstants.TinyBlocksNumber);
command.Hint.ShouldBe(new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.NextRound}
.ToByteArray());
}
Expand Down Expand Up @@ -89,7 +89,7 @@ public async Task AElfConsensusContract_Process()
var command = await miner.GetConsensusCommand.CallAsync(new CommandInput
{PublicKey = ByteString.CopyFrom(minerKeyPair.PublicKey)});
command.NextBlockMiningLeftMilliseconds.ShouldBe(leftMilliseconds);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AElfConsensusContractConstants.TinyBlocksNumber);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AEDPoSContractConstants.TinyBlocksNumber);
command.Hint.ShouldBe(new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.UpdateValue}
.ToByteArray());
}
Expand Down Expand Up @@ -117,7 +117,7 @@ public async Task AElfConsensusContract_Process()
command.NextBlockMiningLeftMilliseconds.ShouldBe(leftMilliseconds);
}

command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AElfConsensusContractConstants.TinyBlocksNumber);
command.LimitMillisecondsOfMiningBlock.ShouldBe(MiningInterval / AEDPoSContractConstants.TinyBlocksNumber);
command.Hint.ShouldBe(new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.NextRound}
.ToByteArray());
}
Expand Down
Loading