Skip to content

Commit

Permalink
Merge pull request #3039 from planetarium/fix/pos
Browse files Browse the repository at this point in the history
Fix PoS related features
  • Loading branch information
OnedgeLee authored Nov 26, 2024
2 parents 5946f1f + df449d9 commit 53b3165
Show file tree
Hide file tree
Showing 16 changed files with 488 additions and 24 deletions.
1 change: 1 addition & 0 deletions .Lib9c.Miner.Tests/Lib9c.Proposer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Lib9c.Policy\Lib9c.Policy.csproj" />
<ProjectReference Include="..\Lib9c.Proposer\Lib9c.Proposer.csproj" />
</ItemGroup>

Expand Down
145 changes: 145 additions & 0 deletions .Lib9c.Miner.Tests/ProposerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using System.Collections.Immutable;
using Lib9c.Renderers;
using Libplanet.Action;
using Libplanet.Blockchain.Policies;
using Libplanet.Blockchain;
using Libplanet.Crypto;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Assets;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
using Libplanet.Types.Tx;
using Nekoyume.Action;
using Nekoyume.Action.Loader;
using Nekoyume.Blockchain.Policy;
using Nekoyume.Model.State;
using System.Numerics;

namespace Lib9c.Proposer.Tests
{
public class ProposerTest
{
private readonly PrivateKey _admin;
private readonly PrivateKey _proposer;
private readonly BlockChain _blockChain;

public ProposerTest()
{
_admin = new PrivateKey();
_proposer = new PrivateKey();
var ncg = Currency.Uncapped("ncg", 2, null);
var policy = new DebugPolicy();
var actionTypeLoader = new NCActionLoader();
IStagePolicy stagePolicy = new VolatileStagePolicy();
var mint = new PrepareRewardAssets
{
RewardPoolAddress = _proposer.Address,
Assets = new List<FungibleAssetValue>
{
1 * Currencies.Mead,
},
};

var validatorSet = new ValidatorSet(
new List<Validator> { new(_proposer.PublicKey, 10_000_000_000_000_000_000) });

var initializeStates = new InitializeStates(
validatorSet,
new RankingState0(),
new ShopState(),
new Dictionary<string, string>(),
new GameConfigState(),
new RedeemCodeState(new Dictionary<PublicKey, RedeemCodeState.Reward>()),
new ActivatedAccountsState(),
new GoldCurrencyState(ncg),
new GoldDistribution[] { },
new PendingActivationState[] { });

List <ActionBase> actions = new List<ActionBase>
{
initializeStates,
};

var genesis = BlockChain.ProposeGenesisBlock(
privateKey: _proposer,
transactions: ImmutableList<Transaction>.Empty
.Add(Transaction.Create(
0, _proposer, null, actions.ToPlainValues())),
timestamp: DateTimeOffset.MinValue);

var store = new MemoryStore();
var stateStore = new TrieStateStore(new MemoryKeyValueStore());

_blockChain = BlockChain.Create(
policy,
stagePolicy,
store,
stateStore,
genesis,
new ActionEvaluator(
policy.PolicyActionsRegistry,
stateStore,
new NCActionLoader()
),
new[] { new BlockRenderer(), }
);
}

[Fact]
public void ProposeBlock()
{
Block block = _blockChain.ProposeBlock(_proposer);
_blockChain.Append(
block,
GenerateBlockCommit(
block,
_proposer,
10_000_000_000_000_000_000));
}

[Fact]
public void AssertInvalidProposer()
{
Block block = _blockChain.ProposeBlock(_proposer);
Assert.Throws<InvalidBlockCommitException>(() => _blockChain.Append(
block,
GenerateBlockCommit(
block,
new PrivateKey(),
10_000_000_000_000_000_000)));
}

[Fact]
public void AssertInvalidPower()
{
Block block = _blockChain.ProposeBlock(_proposer);
Assert.Throws<InvalidBlockCommitException>(() => _blockChain.Append(
block,
GenerateBlockCommit(
block,
_proposer,
10_000_000_000_000_000)));
}

private BlockCommit? GenerateBlockCommit(
Block block, PrivateKey privateKey, BigInteger power)
{
return block.Index != 0
? new BlockCommit(
block.Index,
0,
block.Hash,
ImmutableArray.Create(
new VoteMetadata(
block.Index,
0,
block.Hash,
DateTimeOffset.UtcNow,
privateKey.PublicKey,
power,
VoteFlag.PreCommit).Sign(privateKey)))
: null;
}
}
}
116 changes: 116 additions & 0 deletions .Lib9c.Tests/Action/Guild/Migration/MigratePlanetariumValidatorTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
namespace Lib9c.Tests.Action.Guild.Migration
{
using System;
using System.Collections.Generic;
using System.Numerics;
using Lib9c.Tests.Util;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Libplanet.Types.Consensus;
using Nekoyume.Action.Guild;
using Nekoyume.Action.Guild.Migration;
using Nekoyume.Action.Guild.Migration.LegacyModels;
using Nekoyume.Action.ValidatorDelegation;
using Nekoyume.Model.Guild;
using Nekoyume.Model.Stake;
using Nekoyume.TypedAddress;
using Nekoyume.ValidatorDelegation;
using Xunit;

// TODO: Remove this test class after the migration is completed.
public class MigratePlanetariumValidatorTest : GuildTestBase
{
[Fact]
public void Execute()
{
var guildAddress = AddressUtil.CreateGuildAddress();
var validatorKey = new PrivateKey().PublicKey;
var validatorAddress = validatorKey.Address;
var power = 10_000_000_000_000_000_000;
var guildGold = Currencies.GuildGold;
var delegated = FungibleAssetValue.FromRawValue(guildGold, power);

var world = EnsureLegacyPlanetariumValidator(
World, guildAddress, validatorKey, power);

var guildRepository = new GuildRepository(world, new ActionContext { });
var validatorRepository = new ValidatorRepository(world, new ActionContext { });
var guildDelegatee = guildRepository.GetGuildDelegatee(validatorAddress);
var validatorDelegatee = validatorRepository.GetValidatorDelegatee(validatorAddress);

Assert.False(validatorDelegatee.IsActive);
Assert.Equal(ValidatorDelegatee.InactiveDelegationPoolAddress, guildDelegatee.DelegationPoolAddress);
Assert.Equal(ValidatorDelegatee.InactiveDelegationPoolAddress, validatorDelegatee.DelegationPoolAddress);
Assert.Equal(delegated, world.GetBalance(ValidatorDelegatee.InactiveDelegationPoolAddress, Currencies.GuildGold));
Assert.Equal(guildGold * 0, world.GetBalance(ValidatorDelegatee.ActiveDelegationPoolAddress, Currencies.GuildGold));

var action = new MigratePlanetariumValidator();
var actionContext = new ActionContext
{
PreviousState = world,
Signer = new PrivateKey().Address,
};
world = action.Execute(actionContext);

guildRepository = new GuildRepository(world, new ActionContext { });
validatorRepository = new ValidatorRepository(world, new ActionContext { });
guildDelegatee = guildRepository.GetGuildDelegatee(validatorAddress);
validatorDelegatee = validatorRepository.GetValidatorDelegatee(validatorAddress);

Assert.True(validatorRepository.GetValidatorDelegatee(validatorAddress).IsActive);
Assert.Equal(ValidatorDelegatee.ActiveDelegationPoolAddress, guildDelegatee.DelegationPoolAddress);
Assert.Equal(ValidatorDelegatee.ActiveDelegationPoolAddress, validatorDelegatee.DelegationPoolAddress);
Assert.Equal(delegated, world.GetBalance(ValidatorDelegatee.ActiveDelegationPoolAddress, Currencies.GuildGold));
Assert.Equal(guildGold * 0, world.GetBalance(ValidatorDelegatee.InactiveDelegationPoolAddress, Currencies.GuildGold));

Assert.Throws<InvalidOperationException>(() =>
{
var actionContext = new ActionContext
{
PreviousState = world,
Signer = new PrivateKey().Address,
};
world = action.Execute(actionContext);
});
}

private static IWorld EnsureLegacyPlanetariumValidator(
IWorld world, GuildAddress guildAddress, PublicKey validatorKey, BigInteger power)
{
world = world.SetDelegationMigrationHeight(0L);

var toDelegate = FungibleAssetValue.FromRawValue(Currencies.GuildGold, power);
world = world
.MintAsset(
new ActionContext { },
StakeState.DeriveAddress(validatorKey.Address),
toDelegate)
.MintAsset(
new ActionContext { },
validatorKey.Address,
Currencies.Mead * 1);

world = new PromoteValidator(validatorKey, toDelegate).Execute(new ActionContext
{
PreviousState = world,
Signer = validatorKey.Address,
});

world = new MakeGuild(validatorKey.Address).Execute(new ActionContext
{
PreviousState = world,
Signer = GuildConfig.PlanetariumGuildOwner,
});

world = world.SetValidatorSet(new ValidatorSet(
new List<Validator>
{
new Validator(validatorKey, power),
}));

return world;
}
}
}
46 changes: 46 additions & 0 deletions .Lib9c.Tests/Action/ValidatorDelegation/SlashValidatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,50 @@ public void Execute_ToJailedValidator_ThenNothingHappens()

Assert.Equal(expectedJailed, actualJailed);
}

[Fact]
public void Execute_ByAbstain_ToJailedValidator_ThenNothingHappens()
{
// Given
var world = World;
var validatorKey = new PrivateKey();
var height = 1L;
var actionContext = new ActionContext();
world = EnsureToMintAsset(world, validatorKey, DelegationCurrency * 10, height++);
world = EnsurePromotedValidator(world, validatorKey, DelegationCurrency * 10, height++);
world = EnsureJailedValidator(world, validatorKey, ref height);

var expectedRepository = new ValidatorRepository(world, actionContext);
var expectedDelegatee = expectedRepository.GetValidatorDelegatee(validatorKey.Address);
var expectedTotalDelegated = expectedDelegatee.TotalDelegated;

// When
for (var i = 0L; i <= AbstainHistory.MaxAbstainAllowance; i++)
{
var vote = CreateNullVote(validatorKey, height - 1);
var lastCommit = new BlockCommit(
height: height - 1,
round: 0,
blockHash: vote.BlockHash,
ImmutableArray.Create(vote));
var slashValidator = new SlashValidator();
actionContext = new ActionContext
{
PreviousState = world,
Signer = validatorKey.Address,
BlockIndex = height++,
LastCommit = lastCommit,
};
world = slashValidator.Execute(actionContext);
}

// Then
var actualRepisitory = new ValidatorRepository(world, actionContext);
var actualDelegatee = actualRepisitory.GetValidatorDelegatee(validatorKey.Address);
var actualTotalDelegated = actualDelegatee.TotalDelegated;

Assert.True(actualDelegatee.Jailed);
Assert.False(actualDelegatee.Tombstoned);
Assert.Equal(expectedTotalDelegated, actualTotalDelegated);
}
}
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<LibplanetVersion>5.4.0</LibplanetVersion>
<LibplanetVersion>5.4.1</LibplanetVersion>

<!-- Fill with Libplanet's absolute path to debug with local Libplanet.
Example: $(MSBuildThisFileDirectory).Libplanet -->
Expand Down
21 changes: 20 additions & 1 deletion Lib9c.Policy/Policy/DebugPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Libplanet.Types.Blocks;
using Libplanet.Types.Tx;
using Nekoyume.Action;
using Nekoyume.Action.ValidatorDelegation;

namespace Nekoyume.Blockchain.Policy
{
Expand All @@ -14,7 +15,25 @@ public DebugPolicy()
{
}

public IPolicyActionsRegistry PolicyActionsRegistry { get; } = new PolicyActionsRegistry();
public IPolicyActionsRegistry PolicyActionsRegistry { get; } =
new PolicyActionsRegistry(
beginBlockActions: new IAction[] {
new SlashValidator(),
new AllocateGuildReward(),
new AllocateReward(),
}.ToImmutableArray(),
endBlockActions: new IAction[] {
new UpdateValidators(),
new RecordProposer(),
new RewardGold(),
new ReleaseValidatorUnbondings(),
}.ToImmutableArray(),
beginTxActions: new IAction[] {
new Mortgage(),
}.ToImmutableArray(),
endTxActions: new IAction[] {
new Reward(), new Refund(),
}.ToImmutableArray());

public TxPolicyViolationException ValidateNextBlockTx(
BlockChain blockChain, Transaction transaction)
Expand Down
13 changes: 12 additions & 1 deletion Lib9c.Proposer/Proposer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Immutable;
using System.Threading;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Blockchain;
using Libplanet.Crypto;
using Libplanet.Types.Blocks;
Expand Down Expand Up @@ -33,6 +34,16 @@ public class Proposer
block = _chain.ProposeBlock(
_privateKey,
lastCommit: lastCommit);

if (!(_chain.GetNextWorldState() is IWorldState worldState))
{
throw new InvalidOperationException(
"Failed to get next world state. Appending is not completed.");
}

var proposerPower = worldState.GetValidatorSet().GetValidatorsPower(
new List<PublicKey> { _privateKey.PublicKey });

BlockCommit? commit = block.Index > 0
? new BlockCommit(
block.Index,
Expand All @@ -45,7 +56,7 @@ public class Proposer
block.Hash,
DateTimeOffset.UtcNow,
_privateKey.PublicKey,
null,
proposerPower,
VoteFlag.PreCommit).Sign(_privateKey)))
: null;
_chain.Append(block, commit);
Expand Down
Loading

0 comments on commit 53b3165

Please sign in to comment.