Skip to content

Commit

Permalink
Merge pull request #2189 from longfin/feature/action-obsoletion
Browse files Browse the repository at this point in the history
  • Loading branch information
moreal authored Nov 20, 2023
2 parents 1b17361 + 0bb7aee commit dcb1338
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 6 deletions.
85 changes: 85 additions & 0 deletions .Lib9c.Tests/Policy/BlockPolicySourceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
namespace Lib9c.Tests.Policy
{
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.Loader;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Blocks;
using Libplanet.Types.Tx;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Action.Loader;
using Nekoyume.Blockchain.Policy;
using Xunit;

public class BlockPolicySourceTest
{
private static readonly BlockHash OdinGenesisHash = BlockHash.FromString(
"4582250d0da33b06779a8475d283d5dd210c683b9b999d74d03fac4f58fa6bce"
);

private static readonly BlockHash HeimdallGenesisHash = BlockHash.FromString(
"ade4c29773fe83c1a51da6a667a5a26f08848155674637d43fe636b94a320514"
);

[Fact]
public void IsObsolete()
{
var transferAsset0 = new TransferAsset0(default, default, Currencies.Crystal * 0);
var odinTx = Transaction.Create(
0,
new PrivateKey(),
OdinGenesisHash,
new[] { transferAsset0.PlainValue }
);
var heimdallTx = Transaction.Create(
0,
new PrivateKey(),
HeimdallGenesisHash,
new[] { transferAsset0.PlainValue }
);
var ncActionLoader = new NCActionLoader();

Assert.False(BlockPolicySource.IsObsolete(odinTx, ncActionLoader, 1));
Assert.True(BlockPolicySource.IsObsolete(odinTx, ncActionLoader, 7_000_700));
Assert.True(BlockPolicySource.IsObsolete(heimdallTx, ncActionLoader, 1));

var odinTx2 = Transaction.Create(
0,
new PrivateKey(),
OdinGenesisHash,
new[] { Dictionary.Empty }
);
var heimdallTx2 = Transaction.Create(
0,
new PrivateKey(),
HeimdallGenesisHash,
new[] { Dictionary.Empty }
);
var newActionLoader = new SingleActionLoader(typeof(NewAction));

Assert.False(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 1));
Assert.False(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 50));
Assert.True(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 103)); // Due to +2 offset for odin bug
Assert.False(BlockPolicySource.IsObsolete(heimdallTx2, newActionLoader, 1));
Assert.True(BlockPolicySource.IsObsolete(heimdallTx2, newActionLoader, 51));
}

[ActionObsolete(Planet.Odin, 100)]
[ActionObsolete(Planet.Heimdall, 50)]
private class NewAction : IAction
{
public IValue PlainValue => (Bencodex.Types.Integer)42;

public IAccount Execute(IActionContext context)
{
throw new System.NotImplementedException();
}

public void LoadPlainValue(IValue plainValue)
{
}
}
}
}
17 changes: 12 additions & 5 deletions Lib9c.Policy/Policy/BlockPolicySource.Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,23 @@ long blockIndex
}
else
{
Planet? planet = transaction.DeterminePlanet();
try
{
// Comparison with ObsoleteIndex + 2 is intended to have backward
// compatibility with a bugged original implementation.
return rawActions
.Select(rawAction => actionLoader.LoadAction(blockIndex, rawAction))
.Select(action => action.GetType())
.Any(actionType =>
actionType.GetCustomAttribute<ActionObsoleteAttribute>(false) is { } attribute &&
attribute.ObsoleteIndex + 2 <= blockIndex);
.Any(t =>
{
if (planet is { } planetNotNull)
{
return t.GetCustomAttributes<ActionObsoleteAttribute>(false)
.IsObsolete(planetNotNull, blockIndex);
}

// Exempt obsoleting check against unknown planet
return false;
});
}
catch (Exception)
{
Expand Down
15 changes: 14 additions & 1 deletion Lib9c/Action/ActionObsoleteAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,27 @@ namespace Nekoyume.Action
/// starting from <see cref="ActionObsoleteAttribute.ObsoleteIndex"/> + 2.
/// </para>
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ActionObsoleteAttribute : Attribute
{
public ActionObsoleteAttribute(long obsoleteIndex)
: this(null, obsoleteIndex)
{
}

public ActionObsoleteAttribute(Planet planet, long obsoleteIndex)
: this((Planet?)planet, obsoleteIndex)
{
}

private ActionObsoleteAttribute(Planet? planet, long obsoleteIndex)
{
AffectedPlanet = planet;
ObsoleteIndex = obsoleteIndex;
}

public readonly long ObsoleteIndex;

public readonly Planet? AffectedPlanet;
}
}
32 changes: 32 additions & 0 deletions Lib9c/Action/ActionObsoleteAttributeExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Linq;
using Nekoyume.Action;

namespace Nekoyume
{
public static class ActionObsoleteAttributeExtension
{
public static bool IsObsolete(
this IEnumerable<ActionObsoleteAttribute> attrs,
Planet planet,
long blockIndex
)
{
// it means that action had been obsoleted in the single planet era.
// in that case, check index in Odin only, rest should be obsoleted.
if (attrs.Count() == 1)
{
if (planet != Planet.Odin)
{
return true;
}

// Comparison with ObsoleteIndex + 2 is intended to have backward compatibility with
// a bugged original implementation.
return attrs.Single().ObsoleteIndex + 2 <= blockIndex;
}

return attrs.Any(attr => (attr.AffectedPlanet == Planet.Odin ? attr.ObsoleteIndex + 2 : attr.ObsoleteIndex) <= blockIndex && attr.AffectedPlanet == planet);
}
}
}
11 changes: 11 additions & 0 deletions Lib9c/Planet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace Nekoyume
{
public enum Planet : byte
{
Odin,
Heimdall,
Idun,
}
}
40 changes: 40 additions & 0 deletions Lib9c/PlanetExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Libplanet.Types.Blocks;
using Libplanet.Types.Tx;

namespace Nekoyume
{
public static class PlanetExtension
{
private static readonly BlockHash OdinGenesisHash = BlockHash.FromString(
"4582250d0da33b06779a8475d283d5dd210c683b9b999d74d03fac4f58fa6bce"
);

// FIXME should be changed after Heimdall/Idun mainnet launches
private static readonly BlockHash HeimdallGenesisHash = BlockHash.FromString(
"ade4c29773fe83c1a51da6a667a5a26f08848155674637d43fe636b94a320514"
);

private static readonly BlockHash IdunGenesisHash = BlockHash.FromString(
"209b22087045ec834f01249c8661c2734cea41ccc5d8c9a273a4c8c0521d22ec"
);

public static Planet? DeterminePlanet(this ITransaction tx)
{
// TODO Replace planet detection to using transaction payload instead.
if (tx.GenesisHash.Equals(OdinGenesisHash))
{
return Planet.Odin;
}
if (tx.GenesisHash.Equals(HeimdallGenesisHash))
{
return Planet.Heimdall;
}
if (tx.GenesisHash.Equals(IdunGenesisHash))
{
return Planet.Idun;
}

return null;
}
}
}

0 comments on commit dcb1338

Please sign in to comment.