From 1c051c989694494c9495e7228130cf48dff6a606 Mon Sep 17 00:00:00 2001 From: Swen Mun Date: Tue, 14 Nov 2023 18:08:21 +0900 Subject: [PATCH 1/2] Introduce Planet concept to ActionObsoleteAttribute --- .Lib9c.Tests/Policy/BlockPolicySourceTest.cs | 85 +++++++++++++++++++ .../Policy/BlockPolicySource.Utils.cs | 17 ++-- Lib9c/Action/ActionObsoleteAttribute.cs | 15 +++- .../ActionObsoleteAttributeExtension.cs | 32 +++++++ Lib9c/Planet.cs | 11 +++ Lib9c/PlanetExtension.cs | 40 +++++++++ 6 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 .Lib9c.Tests/Policy/BlockPolicySourceTest.cs create mode 100644 Lib9c/Action/ActionObsoleteAttributeExtension.cs create mode 100644 Lib9c/Planet.cs create mode 100644 Lib9c/PlanetExtension.cs diff --git a/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs b/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs new file mode 100644 index 0000000000..e9714d8d18 --- /dev/null +++ b/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs @@ -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, 101)); + 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) + { + } + } + } +} diff --git a/Lib9c.Policy/Policy/BlockPolicySource.Utils.cs b/Lib9c.Policy/Policy/BlockPolicySource.Utils.cs index a39e43934f..c48e4151dc 100644 --- a/Lib9c.Policy/Policy/BlockPolicySource.Utils.cs +++ b/Lib9c.Policy/Policy/BlockPolicySource.Utils.cs @@ -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(false) is { } attribute && - attribute.ObsoleteIndex + 2 <= blockIndex); + .Any(t => + { + if (planet is { } planetNotNull) + { + return t.GetCustomAttributes(false) + .IsObsolete(planetNotNull, blockIndex); + } + + // Exempt obsoleting check against unknown planet + return false; + }); } catch (Exception) { diff --git a/Lib9c/Action/ActionObsoleteAttribute.cs b/Lib9c/Action/ActionObsoleteAttribute.cs index 53990e9dd7..5aaa4d3d42 100644 --- a/Lib9c/Action/ActionObsoleteAttribute.cs +++ b/Lib9c/Action/ActionObsoleteAttribute.cs @@ -14,14 +14,27 @@ namespace Nekoyume.Action /// starting from + 2. /// /// - [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; } } diff --git a/Lib9c/Action/ActionObsoleteAttributeExtension.cs b/Lib9c/Action/ActionObsoleteAttributeExtension.cs new file mode 100644 index 0000000000..6faca3f121 --- /dev/null +++ b/Lib9c/Action/ActionObsoleteAttributeExtension.cs @@ -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 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.ObsoleteIndex <= blockIndex && attr.AffectedPlanet == planet); + } + } +} diff --git a/Lib9c/Planet.cs b/Lib9c/Planet.cs new file mode 100644 index 0000000000..edb994ba25 --- /dev/null +++ b/Lib9c/Planet.cs @@ -0,0 +1,11 @@ +using System; + +namespace Nekoyume +{ + public enum Planet : byte + { + Odin, + Heimdall, + Idun, + } +} diff --git a/Lib9c/PlanetExtension.cs b/Lib9c/PlanetExtension.cs new file mode 100644 index 0000000000..55c1fa8885 --- /dev/null +++ b/Lib9c/PlanetExtension.cs @@ -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; + } + } +} From 0bb7aeeb9bfb1853ff5edc6aa8816d719fcd4e82 Mon Sep 17 00:00:00 2001 From: Lee Dogeon Date: Mon, 20 Nov 2023 17:17:26 +0900 Subject: [PATCH 2/2] Update Lib9c/Action/ActionObsoleteAttributeExtension.cs Co-authored-by: Swen Mun --- .Lib9c.Tests/Policy/BlockPolicySourceTest.cs | 2 +- Lib9c/Action/ActionObsoleteAttributeExtension.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs b/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs index e9714d8d18..e9e039ba63 100644 --- a/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs +++ b/.Lib9c.Tests/Policy/BlockPolicySourceTest.cs @@ -61,7 +61,7 @@ public void IsObsolete() Assert.False(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 1)); Assert.False(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 50)); - Assert.True(BlockPolicySource.IsObsolete(odinTx2, newActionLoader, 101)); + 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)); } diff --git a/Lib9c/Action/ActionObsoleteAttributeExtension.cs b/Lib9c/Action/ActionObsoleteAttributeExtension.cs index 6faca3f121..44e3de0739 100644 --- a/Lib9c/Action/ActionObsoleteAttributeExtension.cs +++ b/Lib9c/Action/ActionObsoleteAttributeExtension.cs @@ -26,7 +26,7 @@ long blockIndex return attrs.Single().ObsoleteIndex + 2 <= blockIndex; } - return attrs.Any(attr => attr.ObsoleteIndex <= blockIndex && attr.AffectedPlanet == planet); + return attrs.Any(attr => (attr.AffectedPlanet == Planet.Odin ? attr.ObsoleteIndex + 2 : attr.ObsoleteIndex) <= blockIndex && attr.AffectedPlanet == planet); } } }