diff --git a/src/neo/Network/P2P/Payloads/Conditions/AndCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/AndCondition.cs index d141443eac..a2a6045d83 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/AndCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/AndCondition.cs @@ -11,6 +11,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.IO; using System.Linq; @@ -58,5 +60,12 @@ public override JObject ToJson() json["expressions"] = Expressions.Select(p => p.ToJson()).ToArray(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + result.Add(new VM.Types.Array(referenceCounter, Expressions.Select(p => p.ToStackItem(referenceCounter)))); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs index 3ae6c336e6..5339a50109 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs @@ -10,6 +10,8 @@ using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System.IO; namespace Neo.Network.P2P.Payloads.Conditions @@ -50,5 +52,12 @@ public override JObject ToJson() json["expression"] = Expression; return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (Array)base.ToStackItem(referenceCounter); + result.Add(Expression); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs index 836aa40117..f190585091 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs @@ -11,6 +11,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System.IO; namespace Neo.Network.P2P.Payloads.Conditions @@ -51,5 +53,12 @@ public override JObject ToJson() json["hash"] = Hash.ToString(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (Array)base.ToStackItem(referenceCounter); + result.Add(Hash.ToArray()); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs index a7e9754566..6a6e15d83a 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs @@ -13,6 +13,8 @@ using Neo.IO.Json; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; using System.IO; using System.Linq; @@ -56,5 +58,12 @@ public override JObject ToJson() json["group"] = Group.ToString(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (Array)base.ToStackItem(referenceCounter); + result.Add(Group.ToArray()); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/GroupCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/GroupCondition.cs index b94773fb9e..3b1d53242e 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/GroupCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/GroupCondition.cs @@ -13,6 +13,8 @@ using Neo.IO.Json; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; using System.IO; using System.Linq; @@ -56,5 +58,12 @@ public override JObject ToJson() json["group"] = Group.ToString(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (Array)base.ToStackItem(referenceCounter); + result.Add(Group.ToArray()); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/NotCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/NotCondition.cs index d71c2c03d2..ade2e03b24 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/NotCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/NotCondition.cs @@ -11,6 +11,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.IO; @@ -56,5 +58,12 @@ public override JObject ToJson() json["expression"] = Expression.ToJson(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + result.Add(Expression.ToStackItem(referenceCounter)); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/OrCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/OrCondition.cs index 7fb150a9b6..7c6b85d49f 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/OrCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/OrCondition.cs @@ -11,6 +11,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.IO; using System.Linq; @@ -58,5 +60,12 @@ public override JObject ToJson() json["expressions"] = Expressions.Select(p => p.ToJson()).ToArray(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + result.Add(new VM.Types.Array(referenceCounter, Expressions.Select(p => p.ToStackItem(referenceCounter)))); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs index 6c43c3a10d..b5d26fb1e4 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs @@ -11,6 +11,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System.IO; namespace Neo.Network.P2P.Payloads.Conditions @@ -51,5 +53,12 @@ public override JObject ToJson() json["hash"] = Hash.ToString(); return json; } + + public override StackItem ToStackItem(ReferenceCounter referenceCounter) + { + var result = (Array)base.ToStackItem(referenceCounter); + result.Add(Hash.ToArray()); + return result; + } } } diff --git a/src/neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs b/src/neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs index 324d081d0f..76285f0348 100644 --- a/src/neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs +++ b/src/neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs @@ -12,12 +12,14 @@ using Neo.IO.Caching; using Neo.IO.Json; using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.IO; namespace Neo.Network.P2P.Payloads.Conditions { - public abstract class WitnessCondition : ISerializable + public abstract class WitnessCondition : IInteroperable, ISerializable { private const int MaxSubitems = 16; internal const int MaxNestingDepth = 2; @@ -119,5 +121,15 @@ public virtual JObject ToJson() ["type"] = Type }; } + + void IInteroperable.FromStackItem(StackItem stackItem) + { + throw new NotSupportedException(); + } + + public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + { + return new VM.Types.Array(referenceCounter, new StackItem[] { (byte)Type }); + } } } diff --git a/src/neo/Network/P2P/Payloads/Signer.cs b/src/neo/Network/P2P/Payloads/Signer.cs index d9a0d422b8..c5fd4e3288 100644 --- a/src/neo/Network/P2P/Payloads/Signer.cs +++ b/src/neo/Network/P2P/Payloads/Signer.cs @@ -12,6 +12,8 @@ using Neo.IO; using Neo.IO.Json; using Neo.Network.P2P.Payloads.Conditions; +using Neo.SmartContract; +using Neo.VM; using System; using System.Collections.Generic; using System.IO; @@ -22,7 +24,7 @@ namespace Neo.Network.P2P.Payloads /// /// Represents a signer of a . /// - public class Signer : ISerializable + public class Signer : IInteroperable, ISerializable { // This limits maximum number of AllowedContracts or AllowedGroups here private const int MaxSubitems = 16; @@ -176,5 +178,23 @@ public JObject ToJson() json["rules"] = Rules.Select(p => p.ToJson()).ToArray(); return json; } + + void IInteroperable.FromStackItem(VM.Types.StackItem stackItem) + { + throw new NotSupportedException(); + } + + VM.Types.StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + { + return new VM.Types.Array(referenceCounter, new VM.Types.StackItem[] + { + this.ToArray(), + Account.ToArray(), + (byte)Scopes, + new VM.Types.Array(AllowedContracts.Select(u => new VM.Types.ByteString(u.ToArray()))), + new VM.Types.Array(AllowedGroups.Select(u => new VM.Types.ByteString(u.ToArray()))), + new VM.Types.Array(Rules.Select(u => u.ToStackItem(referenceCounter))) + }); + } } } diff --git a/src/neo/Network/P2P/Payloads/WitnessRule.cs b/src/neo/Network/P2P/Payloads/WitnessRule.cs index acd40d5700..6436edc11a 100644 --- a/src/neo/Network/P2P/Payloads/WitnessRule.cs +++ b/src/neo/Network/P2P/Payloads/WitnessRule.cs @@ -11,6 +11,9 @@ using Neo.IO; using Neo.IO.Json; using Neo.Network.P2P.Payloads.Conditions; +using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.IO; @@ -19,7 +22,7 @@ namespace Neo.Network.P2P.Payloads /// /// The rule used to describe the scope of the witness. /// - public class WitnessRule : ISerializable + public class WitnessRule : IInteroperable, ISerializable { /// /// Indicates the action to be taken if the current context meets with the rule. @@ -73,5 +76,19 @@ public JObject ToJson() ["condition"] = Condition.ToJson() }; } + + void IInteroperable.FromStackItem(StackItem stackItem) + { + throw new NotSupportedException(); + } + + public StackItem ToStackItem(ReferenceCounter referenceCounter) + { + return new VM.Types.Array(referenceCounter, new StackItem[] + { + (byte)Action, + Condition.ToStackItem(referenceCounter) + }); + } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Crypto.cs b/src/neo/SmartContract/ApplicationEngine.Crypto.cs index f4d26d6046..e2eba2fd15 100644 --- a/src/neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/neo/SmartContract/ApplicationEngine.Crypto.cs @@ -65,7 +65,7 @@ protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); - AddGas(CheckSigPrice * n * exec_fee_factor); + AddGas(CheckSigPrice * n * ExecFeeFactor); try { for (int i = 0, j = 0; i < m && j < n;) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 877343bdd5..61bfa1a18b 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -46,6 +46,12 @@ partial class ApplicationEngine /// public static readonly InteropDescriptor System_Runtime_GetNetwork = Register("System.Runtime.GetNetwork", nameof(GetNetwork), 1 << 3, CallFlags.None); + /// + /// The of System.Runtime.GetAddressVersion. + /// Gets the address version of the current network. + /// + public static readonly InteropDescriptor System_Runtime_GetAddressVersion = Register("System.Runtime.GetAddressVersion", nameof(GetAddressVersion), 1 << 3, CallFlags.None); + /// /// The of System.Runtime.GetTrigger. /// Gets the trigger of the execution. @@ -150,6 +156,16 @@ internal protected uint GetNetwork() return ProtocolSettings.Network; } + /// + /// The implementation of System.Runtime.GetAddressVersion. + /// Gets the address version of the current network. + /// + /// The address version of the current network. + internal protected byte GetAddressVersion() + { + return ProtocolSettings.AddressVersion; + } + /// /// The implementation of System.Runtime.GetTime. /// Gets the timestamp of the current block. diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 79c48c1a44..cd07184f02 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -58,7 +58,7 @@ public partial class ApplicationEngine : ExecutionEngine private List disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); - private readonly uint exec_fee_factor; + internal readonly uint ExecFeeFactor; internal readonly uint StoragePrice; private byte[] nonceData; @@ -153,7 +153,7 @@ protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, D this.ProtocolSettings = settings; this.gas_amount = gas; this.Diagnostic = diagnostic; - this.exec_fee_factor = snapshot is null || persistingBlock?.Index == 0 ? PolicyContract.DefaultExecFeeFactor : NativeContract.Policy.GetExecFeeFactor(Snapshot); + this.ExecFeeFactor = snapshot is null || persistingBlock?.Index == 0 ? PolicyContract.DefaultExecFeeFactor : NativeContract.Policy.GetExecFeeFactor(Snapshot); this.StoragePrice = snapshot is null || persistingBlock?.Index == 0 ? PolicyContract.DefaultStoragePrice : NativeContract.Policy.GetStoragePrice(Snapshot); this.nonceData = container is Transaction tx ? tx.Hash.ToArray()[..16] : new byte[16]; if (persistingBlock is not null) @@ -479,7 +479,7 @@ protected override void OnSysCall(uint method) protected virtual void OnSysCall(InteropDescriptor descriptor) { ValidateCallFlags(descriptor.RequiredCallFlags); - AddGas(descriptor.FixedPrice * exec_fee_factor); + AddGas(descriptor.FixedPrice * ExecFeeFactor); object[] parameters = new object[descriptor.Parameters.Count]; for (int i = 0; i < parameters.Length; i++) @@ -493,7 +493,7 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) protected override void PreExecuteInstruction() { if (CurrentContext.InstructionPointer < CurrentContext.Script.Length) - AddGas(exec_fee_factor * OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); + AddGas(ExecFeeFactor * OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); } private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) diff --git a/src/neo/SmartContract/Native/LedgerContract.cs b/src/neo/SmartContract/Native/LedgerContract.cs index c3900709d6..6c3a7c8655 100644 --- a/src/neo/SmartContract/Native/LedgerContract.cs +++ b/src/neo/SmartContract/Native/LedgerContract.cs @@ -242,6 +242,12 @@ private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256 return state.Transaction; } + [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] + private Signer[] GetTransactionSigners(DataCache snapshot, UInt256 hash) + { + return GetTransactionState(snapshot, hash)?.Transaction.Signers; + } + [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash) { diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index b19e5fe349..846eda81eb 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -198,7 +198,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); - engine.AddGas(method.CpuFee * Policy.GetExecFeeFactor(engine.Snapshot) + method.StorageFee * Policy.GetStoragePrice(engine.Snapshot)); + engine.AddGas(method.CpuFee * engine.ExecFeeFactor + method.StorageFee * engine.StoragePrice); List parameters = new(); if (method.NeedApplicationEngine) parameters.Add(engine); if (method.NeedSnapshot) parameters.Add(engine.Snapshot); diff --git a/src/neo/SmartContract/Native/NeoToken.cs b/src/neo/SmartContract/Native/NeoToken.cs index 31a44a117d..f47a37637b 100644 --- a/src/neo/SmartContract/Native/NeoToken.cs +++ b/src/neo/SmartContract/Native/NeoToken.cs @@ -404,7 +404,11 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings var candidates = GetCandidates(snapshot); if (voterTurnout < EffectiveVoterTurnout || candidates.Length < settings.CommitteeMembersCount) return settings.StandbyCommittee.Select(p => (p, candidates.FirstOrDefault(k => k.PublicKey.Equals(p)).Votes)); - return candidates.OrderByDescending(p => p.Votes).ThenBy(p => p.PublicKey).Take(settings.CommitteeMembersCount); + return candidates + .OrderByDescending(p => p.Votes) + .ThenBy(p => p.PublicKey) + .Where(p => !Policy.IsBlocked(snapshot, Contract.CreateSignatureRedeemScript(p.PublicKey).ToScriptHash())) + .Take(settings.CommitteeMembersCount); } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index e377320734..3d1cd975f2 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -3,7 +3,7 @@ 2015-2022 The Neo Project Neo - 3.2.0 + 3.2.1 The Neo Project net6.0 true @@ -25,10 +25,10 @@ - + - + diff --git a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs index 4d0a65fb12..c5f4ec44d0 100644 --- a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs +++ b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.Runtime.cs @@ -9,6 +9,16 @@ namespace Neo.UnitTests.SmartContract { public partial class UT_ApplicationEngine { + [TestMethod] + public void TestGetNetworkAndAddressVersion() + { + var tx = TestUtils.GetTransaction(UInt160.Zero); + using var engine = ApplicationEngine.Create(TriggerType.Application, tx, null, TestBlockchain.TheNeoSystem.GenesisBlock, settings: TestBlockchain.TheNeoSystem.Settings, gas: 1100_00000000); + + engine.GetNetwork().Should().Be(TestBlockchain.TheNeoSystem.Settings.Network); + engine.GetAddressVersion().Should().Be(TestBlockchain.TheNeoSystem.Settings.AddressVersion); + } + [TestMethod] public void TestGetRandomSameBlock() { diff --git a/tests/neo.UnitTests/neo.UnitTests.csproj b/tests/neo.UnitTests/neo.UnitTests.csproj index c769e172b4..49ae3ecde5 100644 --- a/tests/neo.UnitTests/neo.UnitTests.csproj +++ b/tests/neo.UnitTests/neo.UnitTests.csproj @@ -9,13 +9,13 @@ - - + + - - + +