Skip to content

Commit

Permalink
Merge pull request #2853 from s2quake/test/improve-readability-pos
Browse files Browse the repository at this point in the history
Improve code readability for PoS test
  • Loading branch information
OnedgeLee authored Oct 2, 2024
2 parents fa9256d + 7a56ae7 commit b300492
Show file tree
Hide file tree
Showing 12 changed files with 1,686 additions and 1,829 deletions.
237 changes: 115 additions & 122 deletions .Lib9c.Tests/Action/ValidatorDelegation/AllocateRewardTest.cs
Original file line number Diff line number Diff line change
@@ -1,143 +1,136 @@
#nullable enable
namespace Lib9c.Tests.Action.ValidatorDelegation
namespace Lib9c.Tests.Action.ValidatorDelegation;

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
using Nekoyume;
using Nekoyume.Action.ValidatorDelegation;
using Nekoyume.Model.State;
using Nekoyume.Module.ValidatorDelegation;
using Nekoyume.ValidatorDelegation;
using Xunit;

public class AllocateRewardTest : ValidatorDelegationTestBase
{
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
using Nekoyume;
using Nekoyume.Action.ValidatorDelegation;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Nekoyume.Module.ValidatorDelegation;
using Nekoyume.ValidatorDelegation;
using Xunit;

public class AllocateRewardTest
[Fact]
public void Serialization()
{
[Fact]
public void Serialization()
{
var action = new AllocateReward();
var plainValue = action.PlainValue;
var action = new AllocateReward();
var plainValue = action.PlainValue;

var deserialized = new AllocateReward();
deserialized.LoadPlainValue(plainValue);
}
var deserialized = new AllocateReward();
deserialized.LoadPlainValue(plainValue);
}

[Fact]
public void Execute()
[Fact]
public void Execute()
{
IWorld world = World;
var context = new ActionContext { };
var privateKeys = Enumerable.Range(0, 200).Select(_ => new PrivateKey()).ToArray();
var favs = Enumerable.Range(0, 200).Select(i => NCG * (i + 1)).ToArray();

for (int i = 0; i < 200; i++)
{
IWorld world = new World(MockUtil.MockModernWorldState);
var context = new ActionContext { };
var ncg = Currency.Uncapped("NCG", 2, null);
// TODO: Use Currencies.GuildGold when it's available.
// var gg = Currencies.GuildGold;
var gg = ncg;
var goldCurrencyState = new GoldCurrencyState(ncg);
world = world
.SetLegacyState(Addresses.GoldCurrency, goldCurrencyState.Serialize());
var privateKeys = Enumerable.Range(0, 200).Select(_ => new PrivateKey()).ToArray();
var favs = Enumerable.Range(0, 200).Select(i => gg * (i + 1)).ToArray();

for (int i = 0; i < 200; i++)
var signer = privateKeys[i];
world = world.MintAsset(context, signer.Address, NCG * 1000);
world = new PromoteValidator(signer.PublicKey, favs[i]).Execute(new ActionContext
{
var signer = privateKeys[i];
world = world.MintAsset(context, signer.Address, gg * 1000);
world = new PromoteValidator(signer.PublicKey, favs[i]).Execute(new ActionContext
{
PreviousState = world,
Signer = signer.Address,
BlockIndex = 10L,
});
}

var blockHash = new BlockHash(Enumerable.Repeat((byte)0x01, BlockHash.Size).ToArray());
var timestamp = DateTimeOffset.UtcNow;
var voteFlags = Enumerable.Range(0, 100).Select(i => i % 2 == 0 ? VoteFlag.PreCommit : VoteFlag.Null).ToArray();
var repository = new ValidatorRepository(world, context);
var bondedSet = repository.GetValidatorList().GetBonded();

var proposer = bondedSet.First();
repository.SetProposerInfo(new ProposerInfo(9L, proposer.OperatorAddress));
var votes = bondedSet.Select(
(v, i) => new VoteMetadata(
9L, 0, blockHash, timestamp, v.PublicKey, v.Power, i % 2 == 0 ? VoteFlag.PreCommit : VoteFlag.Null)
.Sign(i % 2 == 0 ? privateKeys.First(k => k.PublicKey.Equals(v.PublicKey)) : null)).ToImmutableArray();

var totalReward = ncg * 1000;
world = repository.World.MintAsset(context, Addresses.RewardPool, totalReward);
PreviousState = world,
Signer = signer.Address,
BlockIndex = 10L,
});
}

// TODO: Remove this after delegation currency has been changed into GuildGold.
var initialFAVs = votes.Select(vote => world.GetBalance(vote.ValidatorPublicKey.Address, ncg)).ToArray();
var blockHash = new BlockHash(Enumerable.Repeat((byte)0x01, BlockHash.Size).ToArray());
var timestamp = DateTimeOffset.UtcNow;
var voteFlags = Enumerable.Range(0, 100).Select(i => i % 2 == 0 ? VoteFlag.PreCommit : VoteFlag.Null).ToArray();
var repository = new ValidatorRepository(world, context);
var bondedSet = repository.GetValidatorList().GetBonded();

context = new ActionContext
{
BlockIndex = 10L,
PreviousState = world,
Signer = privateKeys[199].Address,
LastCommit = new BlockCommit(9L, 0, blockHash, votes),
};
var proposer = bondedSet.First();
repository.SetProposerInfo(new ProposerInfo(9L, proposer.OperatorAddress));
var votes = bondedSet.Select(
(v, i) => new VoteMetadata(
9L, 0, blockHash, timestamp, v.PublicKey, v.Power, i % 2 == 0 ? VoteFlag.PreCommit : VoteFlag.Null)
.Sign(i % 2 == 0 ? privateKeys.First(k => k.PublicKey.Equals(v.PublicKey)) : null)).ToImmutableArray();

var action = new AllocateReward();
world = action.Execute(context);
var totalReward = NCG * 1000;
world = repository.World.MintAsset(context, Addresses.RewardPool, totalReward);

BigInteger totalPower = votes.Aggregate(
BigInteger.Zero,
(accum, next) => accum + (BigInteger)next.ValidatorPower!);
// TODO: Remove this after delegation currency has been changed into GuildGold.
var initialFAVs = votes.Select(vote => world.GetBalance(vote.ValidatorPublicKey.Address, NCG)).ToArray();

BigInteger preCommitPower = votes.Aggregate(
BigInteger.Zero,
(accum, next) => accum + (BigInteger)next.ValidatorPower! * (next.Flag == VoteFlag.PreCommit ? 1 : 0));
context = new ActionContext
{
BlockIndex = 10L,
PreviousState = world,
Signer = privateKeys[199].Address,
LastCommit = new BlockCommit(9L, 0, blockHash, votes),
};

var action = new AllocateReward();
world = action.Execute(context);

BigInteger totalPower = votes.Aggregate(
BigInteger.Zero,
(accum, next) => accum + (BigInteger)next.ValidatorPower!);

BigInteger preCommitPower = votes.Aggregate(
BigInteger.Zero,
(accum, next) => accum + (BigInteger)next.ValidatorPower! * (next.Flag == VoteFlag.PreCommit ? 1 : 0));

var baseProposerReward
= (totalReward * ValidatorDelegatee.BaseProposerRewardPercentage)
.DivRem(100).Quotient;
var bonusProposerReward
= (totalReward * preCommitPower * ValidatorDelegatee.BonusProposerRewardPercentage)
.DivRem(totalPower * 100).Quotient;

var proposerReward = baseProposerReward + bonusProposerReward;
var remains = totalReward - proposerReward;
repository.UpdateWorld(world);

foreach (var (vote, index) in votes.Select((v, i) => (v, i)))
{
var initialFAV = initialFAVs[index];
var validator = repository.GetValidatorDelegatee(vote.ValidatorPublicKey.Address);

var baseProposerReward
= (totalReward * ValidatorDelegatee.BaseProposerRewardPercentage)
FungibleAssetValue rewardAllocated
= (remains * vote.ValidatorPower!.Value).DivRem(totalPower).Quotient;
FungibleAssetValue commission
= (rewardAllocated * validator.CommissionPercentage)
.DivRem(100).Quotient;
var bonusProposerReward
= (totalReward * preCommitPower * ValidatorDelegatee.BonusProposerRewardPercentage)
.DivRem(totalPower * 100).Quotient;

var proposerReward = baseProposerReward + bonusProposerReward;
var remains = totalReward - proposerReward;
repository.UpdateWorld(world);
if (vote.Flag == VoteFlag.Null)
{
Assert.Equal(initialFAV, world.GetBalance(vote.ValidatorPublicKey.Address, NCG));
Assert.Equal(
NCG * 0, world.GetBalance(validator.CurrentLumpSumRewardsRecordAddress(), NCG));
continue;
}

foreach (var (vote, index) in votes.Select((v, i) => (v, i)))
if (vote.ValidatorPublicKey.Equals(proposer.PublicKey))
{
var initialFAV = initialFAVs[index];
var validator = repository.GetValidatorDelegatee(vote.ValidatorPublicKey.Address);

FungibleAssetValue rewardAllocated
= (remains * vote.ValidatorPower!.Value).DivRem(totalPower).Quotient;
FungibleAssetValue commission
= (rewardAllocated * validator.CommissionPercentage)
.DivRem(100).Quotient;

if (vote.Flag == VoteFlag.Null)
{
Assert.Equal(initialFAV, world.GetBalance(vote.ValidatorPublicKey.Address, ncg));
Assert.Equal(ncg * 0, world.GetBalance(validator.CurrentLumpSumRewardsRecordAddress(), ncg));
continue;
}

if (vote.ValidatorPublicKey.Equals(proposer.PublicKey))
{
Assert.Equal(
proposerReward + commission + initialFAV,
world.GetBalance(vote.ValidatorPublicKey.Address, ncg));
}
else
{
Assert.Equal(commission + initialFAV, world.GetBalance(vote.ValidatorPublicKey.Address, ncg));
}

Assert.Equal(rewardAllocated - commission, world.GetBalance(validator.CurrentLumpSumRewardsRecordAddress(), ncg));
Assert.Equal(
proposerReward + commission + initialFAV,
world.GetBalance(vote.ValidatorPublicKey.Address, NCG));
}
else
{
Assert.Equal(commission + initialFAV, world.GetBalance(vote.ValidatorPublicKey.Address, NCG));
}

Assert.Equal(
rewardAllocated - commission,
world.GetBalance(validator.CurrentLumpSumRewardsRecordAddress(), NCG));
}
}
}
Loading

0 comments on commit b300492

Please sign in to comment.