From 5e53c2168a017ad62b301931684c4ff233749362 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:00:50 +0200 Subject: [PATCH 1/7] Check witness on isStandard --- .../ApplicationEngine.Contract.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index c537469da6..5b84938289 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -1,6 +1,7 @@ using Neo.Cryptography.ECC; using Neo.IO; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; using Neo.VM; @@ -164,7 +165,27 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg internal bool IsStandardContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); - return contract is null || contract.Script.IsStandardContract(); + + // It's a stored contract + + if (contract != null) return contract.Script.IsStandardContract(); + + // Try to find it in the transaction + + if (ScriptContainer is Transaction tx) + { + foreach (var witness in tx.Witnesses) + { + if (witness.ScriptHash == hash) + { + return witness.VerificationScript.IsStandardContract(); + } + } + } + + // It's not possible to determine if it's standard + + return false; } internal CallFlags GetCallFlags() From a16caca9980a1784965eaa8fae704330d2ca2097 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:03:30 +0200 Subject: [PATCH 2/7] Add IsDeployed --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 5b84938289..7ae97fd17f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -21,6 +21,7 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 0_01000000, TriggerType.System | TriggerType.Application, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_01000000, TriggerType.System | TriggerType.Application, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00030000, TriggerType.All, CallFlags.None, true); + public static readonly InteropDescriptor System_Contract_IsDeployed = Register("System.Contract.IsDeployed", nameof(IsDeployedContract), 0_00030000, TriggerType.All, CallFlags.None, true); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00030000, TriggerType.All, CallFlags.None, false); /// /// Calculate corresponding account scripthash for given public key @@ -162,6 +163,11 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg if (md != null) LoadClonedContext(md.Offset); } + internal bool IsDeployedContract(UInt160 hash) + { + return Snapshot.Contracts.TryGet(hash) != null; + } + internal bool IsStandardContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); From 67b5ff7052539094ec4dea6c0d4023cc2e5190b0 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:05:14 +0200 Subject: [PATCH 3/7] Add IsPayable --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 7ae97fd17f..e882e253d9 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -22,6 +22,7 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_01000000, TriggerType.System | TriggerType.Application, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00030000, TriggerType.All, CallFlags.None, true); public static readonly InteropDescriptor System_Contract_IsDeployed = Register("System.Contract.IsDeployed", nameof(IsDeployedContract), 0_00030000, TriggerType.All, CallFlags.None, true); + public static readonly InteropDescriptor System_Contract_IsPayable = Register("System.Contract.IsPayable", nameof(IsPayableContract), 0_00030000, TriggerType.All, CallFlags.None, true); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00030000, TriggerType.All, CallFlags.None, false); /// /// Calculate corresponding account scripthash for given public key @@ -168,6 +169,12 @@ internal bool IsDeployedContract(UInt160 hash) return Snapshot.Contracts.TryGet(hash) != null; } + internal bool IsPayableContract(UInt160 hash) + { + ContractState contract = Snapshot.Contracts.TryGet(hash); + return contract!=null && contract.Payable; + } + internal bool IsStandardContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); From c343ef6bd959dc207abd3f97704f0510b5ebd77f Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:09:51 +0200 Subject: [PATCH 4/7] Fix UT --- tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 283fdc1d3f..5d78c4ebd5 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -110,7 +110,7 @@ public void TestAccount_IsStandard() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; - engine.IsStandardContract(new UInt160(hash)).Should().BeTrue(); + engine.IsStandardContract(new UInt160(hash)).Should().BeFalse(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); @@ -118,6 +118,11 @@ public void TestAccount_IsStandard() engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(new byte[] { 0x01 }); engine.IsStandardContract(state.ScriptHash).Should().BeFalse(); + + state.Script = Contract.CreateSignatureRedeemScript(Blockchain.StandbyValidators[0]); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(new byte[] { 0x01 }); + engine.IsStandardContract(state.ScriptHash).Should().BeTrue(); } [TestMethod] From bae7f50371031723839ce4a6b58649a5a03d2b33 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:12:12 +0200 Subject: [PATCH 5/7] format --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index e882e253d9..9df674a78a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -172,7 +172,7 @@ internal bool IsDeployedContract(UInt160 hash) internal bool IsPayableContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); - return contract!=null && contract.Payable; + return contract != null && contract.Payable; } internal bool IsStandardContract(UInt160 hash) From 39849e09f9cc2e5034d0a2f7c9d0548b832b5f62 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 7 Jul 2020 11:14:37 +0200 Subject: [PATCH 6/7] Add coverage --- .../SmartContract/UT_InteropService.NEO.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 5d78c4ebd5..769c4c8be2 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -125,6 +125,42 @@ public void TestAccount_IsStandard() engine.IsStandardContract(state.ScriptHash).Should().BeTrue(); } + [TestMethod] + public void TestAccount_IsDeployed() + { + var engine = GetEngine(false, true); + var hash = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01 }; + engine.IsDeployedContract(new UInt160(hash)).Should().BeFalse(); + + var snapshot = Blockchain.Singleton.GetSnapshot(); + var state = TestUtils.GetContract(); + snapshot.Contracts.Add(state.ScriptHash, state); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(new byte[] { 0x01 }); + engine.IsDeployedContract(state.ScriptHash).Should().BeTrue(); + } + + [TestMethod] + public void TestAccount_IsPayable() + { + var engine = GetEngine(false, true); + var hash = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01 }; + engine.IsPayableContract(new UInt160(hash)).Should().BeFalse(); + + var snapshot = Blockchain.Singleton.GetSnapshot(); + var state = TestUtils.GetContract(); + snapshot.Contracts.Add(state.ScriptHash, state); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(new byte[] { 0x01 }); + engine.IsPayableContract(state.ScriptHash).Should().BeFalse(); + } + [TestMethod] public void TestContract_Create() { From 9df8e83983875566868de9f6a8d02b35f1f2267b Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 8 Jul 2020 10:08:14 +0200 Subject: [PATCH 7/7] Remove IsPayable, IsDeployed --- .../ApplicationEngine.Contract.cs | 13 ------- .../SmartContract/UT_InteropService.NEO.cs | 36 ------------------- 2 files changed, 49 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 9df674a78a..5b84938289 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -21,8 +21,6 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 0_01000000, TriggerType.System | TriggerType.Application, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_01000000, TriggerType.System | TriggerType.Application, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00030000, TriggerType.All, CallFlags.None, true); - public static readonly InteropDescriptor System_Contract_IsDeployed = Register("System.Contract.IsDeployed", nameof(IsDeployedContract), 0_00030000, TriggerType.All, CallFlags.None, true); - public static readonly InteropDescriptor System_Contract_IsPayable = Register("System.Contract.IsPayable", nameof(IsPayableContract), 0_00030000, TriggerType.All, CallFlags.None, true); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00030000, TriggerType.All, CallFlags.None, false); /// /// Calculate corresponding account scripthash for given public key @@ -164,17 +162,6 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg if (md != null) LoadClonedContext(md.Offset); } - internal bool IsDeployedContract(UInt160 hash) - { - return Snapshot.Contracts.TryGet(hash) != null; - } - - internal bool IsPayableContract(UInt160 hash) - { - ContractState contract = Snapshot.Contracts.TryGet(hash); - return contract != null && contract.Payable; - } - internal bool IsStandardContract(UInt160 hash) { ContractState contract = Snapshot.Contracts.TryGet(hash); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 769c4c8be2..5d78c4ebd5 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -125,42 +125,6 @@ public void TestAccount_IsStandard() engine.IsStandardContract(state.ScriptHash).Should().BeTrue(); } - [TestMethod] - public void TestAccount_IsDeployed() - { - var engine = GetEngine(false, true); - var hash = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01 }; - engine.IsDeployedContract(new UInt160(hash)).Should().BeFalse(); - - var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); - snapshot.Contracts.Add(state.ScriptHash, state); - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(new byte[] { 0x01 }); - engine.IsDeployedContract(state.ScriptHash).Should().BeTrue(); - } - - [TestMethod] - public void TestAccount_IsPayable() - { - var engine = GetEngine(false, true); - var hash = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01 }; - engine.IsPayableContract(new UInt160(hash)).Should().BeFalse(); - - var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); - snapshot.Contracts.Add(state.ScriptHash, state); - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(new byte[] { 0x01 }); - engine.IsPayableContract(state.ScriptHash).Should().BeFalse(); - } - [TestMethod] public void TestContract_Create() {