From 074fc9ad9d50cadbc71ebe84cebe2525137666ec Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 13 Feb 2020 18:08:09 +0800 Subject: [PATCH 01/44] first commit --- src/neo/Oracle/OraclePolicyContract.cs | 182 ++++++++++++++++++ .../SmartContract/Native/NativeContract.cs | 2 + src/neo/neo.csproj | 4 + tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 116 +++++++++++ tests/neo.UnitTests/neo.UnitTests.csproj | 4 + 5 files changed, 308 insertions(+) create mode 100644 src/neo/Oracle/OraclePolicyContract.cs create mode 100644 tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs new file mode 100644 index 0000000000..b1eef9a050 --- /dev/null +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -0,0 +1,182 @@ +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Array = Neo.VM.Types.Array; + +namespace Neo.Oracle +{ + public sealed class OraclePolicyContract : NativeContract + { + public override string ServiceName => "Neo.Native.Oracle.Policy"; + + public override int Id => -4; + + private const byte Prefix_Validator = 24; + private const byte Prefix_TimeOutMilliSeconds = 25; + private const byte Prefix_PerRequestFee = 26; + + public OraclePolicyContract() + { + Manifest.Features = ContractFeatures.HasStorage; + } + + [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })] + private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) + { + UInt160 account = new UInt160(args[0].GetSpan()); + if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; + ECPoint[] pubkeys = ((Array)args[1]).Select(p => p.GetSpan().AsSerializable()).ToArray(); + if (pubkeys.Length != 2) return false; + StoreView snapshot = engine.Snapshot; + StorageKey key = CreateStorageKey(Prefix_Validator, pubkeys[0]); + if (snapshot.Storages.TryGet(key) != null) { + StorageItem value = snapshot.Storages.GetAndChange(key); + value.Value = pubkeys[1].ToArray(); + } + else + { + snapshot.Storages.Add(key, new StorageItem + { + Value = pubkeys[1].ToArray() + }); + } + return true; + } + + public ECPoint[] GetOracleValidators(StoreView snapshot) + { + ECPoint[] consensusPublicKey = PolicyContract.NEO.GetValidators(snapshot); + IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> hasDelegateOracleValidators=GetDelegateOracleValidators(snapshot).Where(p => consensusPublicKey.Contains(p.ConsensusPublicKey)); + hasDelegateOracleValidators.ToList().ForEach(p=>{ + var index = System.Array.IndexOf(consensusPublicKey, p.ConsensusPublicKey); + if (index >= 0) consensusPublicKey[index] = p.OraclePublicKey; + }); + return consensusPublicKey; + } + + public BigInteger GetOracleValidatorsCount(StoreView snapshot) + { + return GetOracleValidators(snapshot).Length; + } + + internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetDelegateOracleValidators(StoreView snapshot) + { + byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); + return snapshot.Storages.Find(prefix_key).Select(p => + ( + p.Key.Key.AsSerializable(1), + p.Value.Value.AsSerializable(1) + )); + } + + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })] + private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) + { + StoreView snapshot = engine.Snapshot; + Transaction tx = (Transaction)engine.ScriptContainer; + Array signatures = new Array(tx.Witnesses.ToList().Select(p => StackItem.FromInterface(p.VerificationScript))); + Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p=> StackItem.FromInterface(p))); + engine.CurrentContext.EvaluationStack.Push(signatures); + engine.CurrentContext.EvaluationStack.Push(pubkeys); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + + if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; + int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); + if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) + { + return false; + } + StorageKey key = CreateStorageKey(Prefix_TimeOutMilliSeconds); + if (snapshot.Storages.TryGet(key) != null) + { + StorageItem value = snapshot.Storages.GetAndChange(key); + value.Value = BitConverter.GetBytes(timeOutMilliSeconds); + return true; + } + else + { + snapshot.Storages.Add(key, new StorageItem + { + Value = BitConverter.GetBytes(timeOutMilliSeconds) + }); + return true; + } + } + + public int GetTimeOutMilliSeconds(StoreView snapshot) + { + StorageKey key = CreateStorageKey(Prefix_TimeOutMilliSeconds); + if (snapshot.Storages.TryGet(key) != null) { + return BitConverter.ToInt32(snapshot.Storages.TryGet(key).Value, 0); + } + else + { + snapshot.Storages.Add(key, new StorageItem + { + Value = BitConverter.GetBytes(1000) + }); + return 1000; + } + } + + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })] + private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) + { + StoreView snapshot = engine.Snapshot; + Transaction tx = (Transaction)engine.ScriptContainer; + Array signatures = new Array(tx.Witnesses.ToList().Select(p => StackItem.FromInterface(p.VerificationScript))); + Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p => StackItem.FromInterface(p))); + engine.CurrentContext.EvaluationStack.Push(signatures); + engine.CurrentContext.EvaluationStack.Push(pubkeys); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; + int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); + if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) { + return false; + } + StorageKey key = CreateStorageKey(Prefix_PerRequestFee); + if (snapshot.Storages.TryGet(key) != null) + { + StorageItem value = snapshot.Storages.GetAndChange(key); + value.Value = BitConverter.GetBytes(perRequestFee); + return true; + } + else + { + snapshot.Storages.Add(key, new StorageItem + { + Value = BitConverter.GetBytes(perRequestFee) + }); + return true; + } + } + + public int GetPerRequestFee(SnapshotView snapshot) + { + StorageKey key = CreateStorageKey(Prefix_PerRequestFee); + if (snapshot.Storages.TryGet(key) != null) + { + return BitConverter.ToInt32(snapshot.Storages.TryGet(key).Value, 0); + } + else + { + snapshot.Storages.Add(key, new StorageItem + { + Value = BitConverter.GetBytes(1000) + }); + return 1000; + } + } + } +} diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index b7c7f85251..7335d66dc5 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -2,6 +2,7 @@ using Neo.IO; using Neo.Ledger; +using Neo.Oracle; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native.Tokens; using Neo.VM; @@ -23,6 +24,7 @@ public abstract class NativeContract public static NeoToken NEO { get; } = new NeoToken(); public static GasToken GAS { get; } = new GasToken(); public static PolicyContract Policy { get; } = new PolicyContract(); + public static OraclePolicyContract OraclePolicy { get; } = new OraclePolicyContract(); public abstract string ServiceName { get; } public uint ServiceHash { get; } diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index 075d17fb7f..5806831c25 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -30,4 +30,8 @@ + + + + diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs new file mode 100644 index 0000000000..f51dec7598 --- /dev/null +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -0,0 +1,116 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Oracle; +using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.UnitTests.Extensions; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using System.Linq; +using System.Numerics; + +namespace Neo.UnitTests.Oracle +{ + [TestClass] + public class UT_OraclePolicy + { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + + [TestMethod] + public void Check_GetPerRequestFee() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + // Fake blockchain + OraclePolicyContract contract = NativeContract.OraclePolicy; + Assert.AreEqual(contract.GetPerRequestFee(snapshot), 1000); + } + + [TestMethod] + public void Check_GetTimeOutMilliSeconds() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + // Fake blockchain + OraclePolicyContract contract = NativeContract.OraclePolicy; + Assert.AreEqual(contract.GetPerRequestFee(snapshot), 1000); + } + + [TestMethod] + public void Check_GetOracleValidators() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + // Fake blockchain + OraclePolicyContract contract = NativeContract.OraclePolicy; + ECPoint[] obj = contract.GetOracleValidators(snapshot); + Assert.AreEqual(obj.Length, 7); + } + + [TestMethod] + public void Test_DelegateOracleValidator() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + // Fake blockchain + OraclePolicyContract contract = NativeContract.OraclePolicy; + ECPoint[] obj = contract.GetOracleValidators(snapshot); + Assert.AreEqual(obj.Length, 7); + + // Without signature + byte[] privateKey1 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair1 = new KeyPair(privateKey1); + ECPoint pubkey1 = keyPair1.PublicKey; + + byte[] privateKey2 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair2 = new KeyPair(privateKey2); + ECPoint pubkey2 = keyPair2.PublicKey; + + Array array = new Array(); + array.Add(StackItem.FromInterface(privateKey1)); + array.Add(StackItem.FromInterface(privateKey2)); + +/* var ret = NativeContract.OraclePolicy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), + "DelegateOracleValidator", new ContractParameter(ContractParameterType.Hash160) { Value = 1 }, new ContractParameter(ContractParameterType.Array) { Value = array }); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeFalse();*/ + } + internal static (bool State, bool Result) Check_DelegateOracleValidator(StoreView snapshot, byte[] account, byte[][] pubkeys, bool signAccount) + { + var engine = new ApplicationEngine(TriggerType.Application, + new Nep5NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot, 0, true); + + engine.LoadScript(NativeContract.OraclePolicy.Script); + + var script = new ScriptBuilder(); + + foreach (var ec in pubkeys) script.EmitPush(ec); + script.EmitPush(pubkeys.Length); + script.Emit(OpCode.PACK); + + script.EmitPush(account.ToArray()); + script.EmitPush(2); + script.Emit(OpCode.PACK); + script.EmitPush("DelegateOracleValidator"); + engine.LoadScript(script.ToArray()); + + if (engine.Execute() == VMState.FAULT) + { + return (false, false); + } + + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + + return (true, result.ToBoolean()); + } + } +} diff --git a/tests/neo.UnitTests/neo.UnitTests.csproj b/tests/neo.UnitTests/neo.UnitTests.csproj index 5857ea504f..8deecdb7aa 100644 --- a/tests/neo.UnitTests/neo.UnitTests.csproj +++ b/tests/neo.UnitTests/neo.UnitTests.csproj @@ -31,4 +31,8 @@ + + + + From 25b82cd64b27870350702f20a9b652e4c8e6c63b Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 13 Feb 2020 18:19:40 +0800 Subject: [PATCH 02/44] format --- src/neo/Oracle/OraclePolicyContract.cs | 16 ++++++++++------ tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 8 ++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index b1eef9a050..ed25d82773 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -40,7 +40,8 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) if (pubkeys.Length != 2) return false; StoreView snapshot = engine.Snapshot; StorageKey key = CreateStorageKey(Prefix_Validator, pubkeys[0]); - if (snapshot.Storages.TryGet(key) != null) { + if (snapshot.Storages.TryGet(key) != null) + { StorageItem value = snapshot.Storages.GetAndChange(key); value.Value = pubkeys[1].ToArray(); } @@ -57,8 +58,9 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) public ECPoint[] GetOracleValidators(StoreView snapshot) { ECPoint[] consensusPublicKey = PolicyContract.NEO.GetValidators(snapshot); - IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> hasDelegateOracleValidators=GetDelegateOracleValidators(snapshot).Where(p => consensusPublicKey.Contains(p.ConsensusPublicKey)); - hasDelegateOracleValidators.ToList().ForEach(p=>{ + IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> hasDelegateOracleValidators = GetDelegateOracleValidators(snapshot).Where(p => consensusPublicKey.Contains(p.ConsensusPublicKey)); + hasDelegateOracleValidators.ToList().ForEach(p => + { var index = System.Array.IndexOf(consensusPublicKey, p.ConsensusPublicKey); if (index >= 0) consensusPublicKey[index] = p.OraclePublicKey; }); @@ -86,7 +88,7 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) StoreView snapshot = engine.Snapshot; Transaction tx = (Transaction)engine.ScriptContainer; Array signatures = new Array(tx.Witnesses.ToList().Select(p => StackItem.FromInterface(p.VerificationScript))); - Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p=> StackItem.FromInterface(p))); + Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p => StackItem.FromInterface(p))); engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); @@ -117,7 +119,8 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) public int GetTimeOutMilliSeconds(StoreView snapshot) { StorageKey key = CreateStorageKey(Prefix_TimeOutMilliSeconds); - if (snapshot.Storages.TryGet(key) != null) { + if (snapshot.Storages.TryGet(key) != null) + { return BitConverter.ToInt32(snapshot.Storages.TryGet(key).Value, 0); } else @@ -142,7 +145,8 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) engine.CurrentContext.EvaluationStack.Push(StackItem.Null); if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); - if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) { + if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) + { return false; } StorageKey key = CreateStorageKey(Prefix_PerRequestFee); diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index f51dec7598..10efd11944 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -78,10 +78,10 @@ public void Test_DelegateOracleValidator() array.Add(StackItem.FromInterface(privateKey1)); array.Add(StackItem.FromInterface(privateKey2)); -/* var ret = NativeContract.OraclePolicy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), - "DelegateOracleValidator", new ContractParameter(ContractParameterType.Hash160) { Value = 1 }, new ContractParameter(ContractParameterType.Array) { Value = array }); - ret.Should().BeOfType(); - ret.ToBoolean().Should().BeFalse();*/ + /* var ret = NativeContract.OraclePolicy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), + "DelegateOracleValidator", new ContractParameter(ContractParameterType.Hash160) { Value = 1 }, new ContractParameter(ContractParameterType.Array) { Value = array }); + ret.Should().BeOfType(); + ret.ToBoolean().Should().BeFalse();*/ } internal static (bool State, bool Result) Check_DelegateOracleValidator(StoreView snapshot, byte[] account, byte[][] pubkeys, bool signAccount) { From 04fdf94aa672863bf7f4abb0652d279ed539e5bd Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 14 Feb 2020 16:39:02 +0800 Subject: [PATCH 03/44] Simplify code --- src/neo/Oracle/OraclePolicyContract.cs | 102 +++++++++---------------- src/neo/neo.csproj | 6 +- 2 files changed, 38 insertions(+), 70 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index ed25d82773..dcc436d079 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -31,6 +31,20 @@ public OraclePolicyContract() Manifest.Features = ContractFeatures.HasStorage; } + internal override bool Initialize(ApplicationEngine engine) + { + if (!base.Initialize(engine)) return false; + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_TimeOutMilliSeconds), new StorageItem + { + Value = BitConverter.GetBytes(1000) + }); + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem + { + Value = BitConverter.GetBytes(1000) + }); + return true; + } + [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })] private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { @@ -95,42 +109,21 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); - if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) - { - return false; - } - StorageKey key = CreateStorageKey(Prefix_TimeOutMilliSeconds); - if (snapshot.Storages.TryGet(key) != null) - { - StorageItem value = snapshot.Storages.GetAndChange(key); - value.Value = BitConverter.GetBytes(timeOutMilliSeconds); - return true; - } - else - { - snapshot.Storages.Add(key, new StorageItem - { - Value = BitConverter.GetBytes(timeOutMilliSeconds) - }); - return true; - } + if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) return false; + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); + storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); + return true; + } + + [ContractMethod(1_00000000, ContractParameterType.Array, SafeMethod = true)] + private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) + { + return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); } public int GetTimeOutMilliSeconds(StoreView snapshot) { - StorageKey key = CreateStorageKey(Prefix_TimeOutMilliSeconds); - if (snapshot.Storages.TryGet(key) != null) - { - return BitConverter.ToInt32(snapshot.Storages.TryGet(key).Value, 0); - } - else - { - snapshot.Storages.Add(key, new StorageItem - { - Value = BitConverter.GetBytes(1000) - }); - return 1000; - } + return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_TimeOutMilliSeconds)].Value, 0); } [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })] @@ -145,42 +138,21 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) engine.CurrentContext.EvaluationStack.Push(StackItem.Null); if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); - if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) - { - return false; - } - StorageKey key = CreateStorageKey(Prefix_PerRequestFee); - if (snapshot.Storages.TryGet(key) != null) - { - StorageItem value = snapshot.Storages.GetAndChange(key); - value.Value = BitConverter.GetBytes(perRequestFee); - return true; - } - else - { - snapshot.Storages.Add(key, new StorageItem - { - Value = BitConverter.GetBytes(perRequestFee) - }); - return true; - } + if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) return false; + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_PerRequestFee)); + storage.Value = BitConverter.GetBytes(perRequestFee); + return true; } - public int GetPerRequestFee(SnapshotView snapshot) + [ContractMethod(1_00000000, ContractParameterType.Array, SafeMethod = true)] + private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) { - StorageKey key = CreateStorageKey(Prefix_PerRequestFee); - if (snapshot.Storages.TryGet(key) != null) - { - return BitConverter.ToInt32(snapshot.Storages.TryGet(key).Value, 0); - } - else - { - snapshot.Storages.Add(key, new StorageItem - { - Value = BitConverter.GetBytes(1000) - }); - return 1000; - } + return new Integer(GetPerRequestFee(engine.Snapshot)); + } + + public int GetPerRequestFee(StoreView snapshot) + { + return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_PerRequestFee)].Value, 0); } } } diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index 5806831c25..7892d3f5ec 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -1,4 +1,4 @@ - + 2015-2019 The Neo Project @@ -30,8 +30,4 @@ - - - - From e4dc1ac53835035cb0ec51a59b092aefe63b48a9 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sat, 15 Feb 2020 00:04:16 +0800 Subject: [PATCH 04/44] add UT and add some feature --- src/neo/Oracle/OraclePolicyContract.cs | 24 ++- tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 158 ++++++++++++------ 2 files changed, 126 insertions(+), 56 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index dcc436d079..617a75c402 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -69,18 +69,30 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) return true; } + [ContractMethod(0_03000000, ContractParameterType.Array)] + private StackItem GetOracleValidators(ApplicationEngine engine, Array args) + { + return new Array(engine.ReferenceCounter, GetOracleValidators(engine.Snapshot).Select(p => (StackItem)p.ToArray())); + } + public ECPoint[] GetOracleValidators(StoreView snapshot) { ECPoint[] consensusPublicKey = PolicyContract.NEO.GetValidators(snapshot); IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> hasDelegateOracleValidators = GetDelegateOracleValidators(snapshot).Where(p => consensusPublicKey.Contains(p.ConsensusPublicKey)); - hasDelegateOracleValidators.ToList().ForEach(p => + foreach (var item in hasDelegateOracleValidators) { - var index = System.Array.IndexOf(consensusPublicKey, p.ConsensusPublicKey); - if (index >= 0) consensusPublicKey[index] = p.OraclePublicKey; - }); + var index = System.Array.IndexOf(consensusPublicKey, item.ConsensusPublicKey); + if (index >= 0) consensusPublicKey[index] = item.OraclePublicKey; + } return consensusPublicKey; } + [ContractMethod(0_03000000, ContractParameterType.Integer)] + private StackItem GetOracleValidatorsCount(ApplicationEngine engine, Array args) + { + return GetOracleValidatorsCount(engine.Snapshot); + } + public BigInteger GetOracleValidatorsCount(StoreView snapshot) { return GetOracleValidators(snapshot).Length; @@ -115,7 +127,7 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) return true; } - [ContractMethod(1_00000000, ContractParameterType.Array, SafeMethod = true)] + [ContractMethod(1_00000000, ContractParameterType.Integer)] private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); @@ -144,7 +156,7 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) return true; } - [ContractMethod(1_00000000, ContractParameterType.Array, SafeMethod = true)] + [ContractMethod(1_00000000, ContractParameterType.Integer, SafeMethod = true)] private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) { return new Integer(GetPerRequestFee(engine.Snapshot)); diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index 10efd11944..a9b4150dae 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -8,10 +8,13 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.SmartContract.Native.Tokens; using Neo.UnitTests.Extensions; +using Neo.UnitTests.Wallets; using Neo.VM; using Neo.VM.Types; using Neo.Wallets; +using System; using System.Linq; using System.Numerics; @@ -27,43 +30,91 @@ public void TestSetup() } [TestMethod] - public void Check_GetPerRequestFee() + public void TestInitialize() { var snapshot = Blockchain.Singleton.GetSnapshot(); - // Fake blockchain - OraclePolicyContract contract = NativeContract.OraclePolicy; - Assert.AreEqual(contract.GetPerRequestFee(snapshot), 1000); + var engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true); + + snapshot.Storages.Delete(CreateStorageKey(11)); + snapshot.PersistingBlock = Blockchain.GenesisBlock; + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); + } + internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) + { + StorageKey storageKey = new StorageKey + { + Id = NativeContract.OraclePolicy.Id, + Key = new byte[sizeof(byte) + (key?.Length ?? 0)] + }; + storageKey.Key[0] = prefix; + key?.CopyTo(storageKey.Key.AsSpan(1)); + return storageKey; } [TestMethod] - public void Check_GetTimeOutMilliSeconds() + public void Test_GetPerRequestFee() { var snapshot = Blockchain.Singleton.GetSnapshot(); - // Fake blockchain - OraclePolicyContract contract = NativeContract.OraclePolicy; - Assert.AreEqual(contract.GetPerRequestFee(snapshot), 1000); + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getPerRequestFee"); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Integer)); + Assert.AreEqual(result, 1000); } [TestMethod] - public void Check_GetOracleValidators() + public void Test_GetTimeOutMilliSeconds() { var snapshot = Blockchain.Singleton.GetSnapshot(); - // Fake blockchain - OraclePolicyContract contract = NativeContract.OraclePolicy; - ECPoint[] obj = contract.GetOracleValidators(snapshot); - Assert.AreEqual(obj.Length, 7); + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getTimeOutMilliSeconds"); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Integer)); + Assert.AreEqual(result, 1000); } [TestMethod] - public void Test_DelegateOracleValidator() + public void Test_GetOracleValidators() { var snapshot = Blockchain.Singleton.GetSnapshot(); - // Fake blockchain - OraclePolicyContract contract = NativeContract.OraclePolicy; - ECPoint[] obj = contract.GetOracleValidators(snapshot); - Assert.AreEqual(obj.Length, 7); + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getOracleValidators"); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); - // Without signature + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Array)); + Assert.AreEqual(((VM.Types.Array)result).Count, 7); + } + + [TestMethod] + public void Test_GetOracleValidatorsCount() + { + var snapshot = Blockchain.Singleton.GetSnapshot(); + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getOracleValidatorsCount"); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Integer)); + Assert.AreEqual(result, 7); + } + + [TestMethod] + public void Test_DelegateOracleValidator() + { byte[] privateKey1 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair keyPair1 = new KeyPair(privateKey1); @@ -74,43 +125,50 @@ public void Test_DelegateOracleValidator() KeyPair keyPair2 = new KeyPair(privateKey2); ECPoint pubkey2 = keyPair2.PublicKey; - Array array = new Array(); - array.Add(StackItem.FromInterface(privateKey1)); - array.Add(StackItem.FromInterface(privateKey2)); - - /* var ret = NativeContract.OraclePolicy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), - "DelegateOracleValidator", new ContractParameter(ContractParameterType.Hash160) { Value = 1 }, new ContractParameter(ContractParameterType.Array) { Value = array }); - ret.Should().BeOfType(); - ret.ToBoolean().Should().BeFalse();*/ - } - internal static (bool State, bool Result) Check_DelegateOracleValidator(StoreView snapshot, byte[] account, byte[][] pubkeys, bool signAccount) - { - var engine = new ApplicationEngine(TriggerType.Application, - new Nep5NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot, 0, true); + ECPoint[] pubkeys = new ECPoint[2]; + pubkeys[0] = pubkey1; + pubkeys[1] = pubkey2; - engine.LoadScript(NativeContract.OraclePolicy.Script); - - var script = new ScriptBuilder(); - - foreach (var ec in pubkeys) script.EmitPush(ec); - script.EmitPush(pubkeys.Length); - script.Emit(OpCode.PACK); - - script.EmitPush(account.ToArray()); - script.EmitPush(2); - script.Emit(OpCode.PACK); - script.EmitPush("DelegateOracleValidator"); - engine.LoadScript(script.ToArray()); + var snapshot = Blockchain.Singleton.GetSnapshot(); - if (engine.Execute() == VMState.FAULT) + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter + { + Type = ContractParameterType.Hash160, + Value = Contract.CreateSignatureRedeemScript(pubkey1).ToScriptHash() + }, new ContractParameter + { + Type = ContractParameterType.Array, + Value = pubkeys.Select(p => new ContractParameter + { + Type = ContractParameterType.PublicKey, + Value = p + }).ToArray() + }); + + MyWallet wallet = new MyWallet(); + WalletAccount account = wallet.CreateAccount(privateKey1); + + // Fake balance + var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem { - return (false, false); + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new Nep5AccountState() + { + Balance = 1000000 * NativeContract.GAS.Factor } + .ToByteArray(); + snapshot.Commit(); - var result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.Boolean)); + var tx = wallet.MakeTransaction(sb.ToArray(), account.ScriptHash, new TransactionAttribute[] { }); + ContractParametersContext context = new ContractParametersContext(tx); + wallet.Sign(context); + tx.Witnesses = context.GetWitnesses(); - return (true, result.ToBoolean()); + var engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); + engine.Execute().Should().Be(VMState.HALT); } } } From 80bc65f824a345302eacbd54f1846ac8746d8efd Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sat, 15 Feb 2020 23:18:28 +0800 Subject: [PATCH 05/44] Fix bug --- src/neo/Oracle/OraclePolicyContract.cs | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index 617a75c402..8be4f5148d 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -36,7 +36,7 @@ internal override bool Initialize(ApplicationEngine engine) if (!base.Initialize(engine)) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_TimeOutMilliSeconds), new StorageItem { - Value = BitConverter.GetBytes(1000) + Value = BitConverter.GetBytes(5000) }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem { @@ -108,17 +108,18 @@ internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetD )); } - [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })] + internal UInt160 GetOracleMultiSigAddress(ECPoint[] validators) + { + return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); + } + + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "TimeOutMilliSeconds" })] private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; - Transaction tx = (Transaction)engine.ScriptContainer; - Array signatures = new Array(tx.Witnesses.ToList().Select(p => StackItem.FromInterface(p.VerificationScript))); - Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p => StackItem.FromInterface(p))); - engine.CurrentContext.EvaluationStack.Push(signatures); - engine.CurrentContext.EvaluationStack.Push(pubkeys); - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - + ECPoint[] oracleValidators = GetOracleValidators(snapshot); + UInt160 account = GetOracleMultiSigAddress(oracleValidators); + if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) return false; @@ -142,15 +143,11 @@ public int GetTimeOutMilliSeconds(StoreView snapshot) private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; - Transaction tx = (Transaction)engine.ScriptContainer; - Array signatures = new Array(tx.Witnesses.ToList().Select(p => StackItem.FromInterface(p.VerificationScript))); - Array pubkeys = new Array(GetOracleValidators(snapshot).ToList().Select(p => StackItem.FromInterface(p))); - engine.CurrentContext.EvaluationStack.Push(signatures); - engine.CurrentContext.EvaluationStack.Push(pubkeys); - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + ECPoint[] oracleValidators = GetOracleValidators(snapshot); + UInt160 account = GetOracleMultiSigAddress(oracleValidators); + if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); - if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) return false; StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_PerRequestFee)); storage.Value = BitConverter.GetBytes(perRequestFee); return true; From aadf1971f3797b47814b926d88974d3b492d7f8c Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sun, 16 Feb 2020 00:36:33 +0800 Subject: [PATCH 06/44] Add summary and fix bug --- src/neo/Oracle/OraclePolicyContract.cs | 105 ++++++++++++++---- tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 2 +- 2 files changed, 85 insertions(+), 22 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index 8be4f5148d..afd0e95118 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -25,12 +25,18 @@ public sealed class OraclePolicyContract : NativeContract private const byte Prefix_Validator = 24; private const byte Prefix_TimeOutMilliSeconds = 25; private const byte Prefix_PerRequestFee = 26; - + /// + /// Constructor + /// public OraclePolicyContract() { Manifest.Features = ContractFeatures.HasStorage; } - + /// + /// Initialization.Set default parameter value. + /// + /// VM + /// Returns true if the execution is successful, otherwise returns false internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; @@ -44,7 +50,12 @@ internal override bool Initialize(ApplicationEngine engine) }); return true; } - + /// + /// Oracle validator can delegate third party to operate Oracle nodes + /// + /// VM + /// Parameter Array + /// Returns true if the execution is successful, otherwise returns false [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })] private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { @@ -68,13 +79,22 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) } return true; } - + /// + /// Get current authorized Oracle validator. + /// + /// VM + /// Parameter Array + /// Authorized Oracle validator [ContractMethod(0_03000000, ContractParameterType.Array)] private StackItem GetOracleValidators(ApplicationEngine engine, Array args) { return new Array(engine.ReferenceCounter, GetOracleValidators(engine.Snapshot).Select(p => (StackItem)p.ToArray())); } - + /// + /// Get current authorized Oracle validator + /// + /// snapshot + /// Authorized Oracle validator public ECPoint[] GetOracleValidators(StoreView snapshot) { ECPoint[] consensusPublicKey = PolicyContract.NEO.GetValidators(snapshot); @@ -86,18 +106,31 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) } return consensusPublicKey; } - + /// + /// Get number of current authorized Oracle validator + /// + /// VM + /// Parameter Array + /// The number of authorized Oracle validator [ContractMethod(0_03000000, ContractParameterType.Integer)] private StackItem GetOracleValidatorsCount(ApplicationEngine engine, Array args) { return GetOracleValidatorsCount(engine.Snapshot); } - + /// + /// Get number of current authorized Oracle validator + /// + /// snapshot + /// The number of authorized Oracle validator public BigInteger GetOracleValidatorsCount(StoreView snapshot) { return GetOracleValidators(snapshot).Length; } - + /// + /// A collection of delegated Oracle validator + /// + /// snapshot + /// internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetDelegateOracleValidators(StoreView snapshot) { byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); @@ -107,44 +140,65 @@ internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetD p.Value.Value.AsSerializable(1) )); } - - internal UInt160 GetOracleMultiSigAddress(ECPoint[] validators) + /// + /// Create a Oracle multisignature address + /// + /// snapshot + /// Oracle multisignature address + public UInt160 GetOracleMultiSigAddress(StoreView snapshot) { + ECPoint[] validators = GetOracleValidators(snapshot); return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); } - + /// + /// Set timeout + /// + /// VM + /// Parameter Array + /// Returns true if the execution is successful, otherwise returns false [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "TimeOutMilliSeconds" })] private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; - ECPoint[] oracleValidators = GetOracleValidators(snapshot); - UInt160 account = GetOracleMultiSigAddress(oracleValidators); + UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); - if (!InteropService.Crypto.ECDsaCheckMultiSig.Handler.Invoke(engine)) return false; StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); return true; } - + /// + /// Get timeout + /// + /// VM + /// Parameter Array + /// value [ContractMethod(1_00000000, ContractParameterType.Integer)] private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); } - + /// + /// Get timeout + /// + /// snapshot + /// value public int GetTimeOutMilliSeconds(StoreView snapshot) { return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_TimeOutMilliSeconds)].Value, 0); } - + /// + /// Set PerRequestFee + /// + /// VM + /// Parameter Array + /// Returns true if the execution is successful, otherwise returns false [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })] private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; - ECPoint[] oracleValidators = GetOracleValidators(snapshot); - UInt160 account = GetOracleMultiSigAddress(oracleValidators); + UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); @@ -152,13 +206,22 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) storage.Value = BitConverter.GetBytes(perRequestFee); return true; } - + /// + /// Get PerRequestFee + /// + /// VM + /// Parameter Array + /// Value [ContractMethod(1_00000000, ContractParameterType.Integer, SafeMethod = true)] private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) { return new Integer(GetPerRequestFee(engine.Snapshot)); } - + /// + /// Get PerRequestFee + /// + /// VM + /// Value public int GetPerRequestFee(StoreView snapshot) { return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_PerRequestFee)].Value, 0); diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index a9b4150dae..c4d3d1512c 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -79,7 +79,7 @@ public void Test_GetTimeOutMilliSeconds() engine.Execute().Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Integer)); - Assert.AreEqual(result, 1000); + Assert.AreEqual(result, 5000); } [TestMethod] From 748a3afc02d222a93c4b37993351056dd3e36406 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sun, 16 Feb 2020 18:56:49 +0800 Subject: [PATCH 07/44] format --- src/neo/Oracle/OraclePolicyContract.cs | 34 +++++++++++++------ tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 16 +++------ tests/neo.UnitTests/neo.UnitTests.csproj | 5 +-- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index afd0e95118..b0e3f7de4a 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -25,6 +25,7 @@ public sealed class OraclePolicyContract : NativeContract private const byte Prefix_Validator = 24; private const byte Prefix_TimeOutMilliSeconds = 25; private const byte Prefix_PerRequestFee = 26; + /// /// Constructor /// @@ -32,6 +33,7 @@ public OraclePolicyContract() { Manifest.Features = ContractFeatures.HasStorage; } + /// /// Initialization.Set default parameter value. /// @@ -50,35 +52,37 @@ internal override bool Initialize(ApplicationEngine engine) }); return true; } + /// /// Oracle validator can delegate third party to operate Oracle nodes /// /// VM /// Parameter Array /// Returns true if the execution is successful, otherwise returns false - [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })] + [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.ByteArray, ContractParameterType.ByteArray }, ParameterNames = new[] { "consignorPubKey", "consigneePubKey" })] private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { - UInt160 account = new UInt160(args[0].GetSpan()); + ECPoint consignorPubKey = args[0].GetSpan().AsSerializable(); + ECPoint consigneePubKey = args[1].GetSpan().AsSerializable(); + UInt160 account = Contract.CreateSignatureRedeemScript(consignorPubKey).ToScriptHash(); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - ECPoint[] pubkeys = ((Array)args[1]).Select(p => p.GetSpan().AsSerializable()).ToArray(); - if (pubkeys.Length != 2) return false; StoreView snapshot = engine.Snapshot; - StorageKey key = CreateStorageKey(Prefix_Validator, pubkeys[0]); + StorageKey key = CreateStorageKey(Prefix_Validator, consignorPubKey); if (snapshot.Storages.TryGet(key) != null) { StorageItem value = snapshot.Storages.GetAndChange(key); - value.Value = pubkeys[1].ToArray(); + value.Value = consigneePubKey.ToArray(); } else { snapshot.Storages.Add(key, new StorageItem { - Value = pubkeys[1].ToArray() + Value = consigneePubKey.ToArray() }); } return true; } + /// /// Get current authorized Oracle validator. /// @@ -90,6 +94,7 @@ private StackItem GetOracleValidators(ApplicationEngine engine, Array args) { return new Array(engine.ReferenceCounter, GetOracleValidators(engine.Snapshot).Select(p => (StackItem)p.ToArray())); } + /// /// Get current authorized Oracle validator /// @@ -106,6 +111,7 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) } return consensusPublicKey; } + /// /// Get number of current authorized Oracle validator /// @@ -117,6 +123,7 @@ private StackItem GetOracleValidatorsCount(ApplicationEngine engine, Array args) { return GetOracleValidatorsCount(engine.Snapshot); } + /// /// Get number of current authorized Oracle validator /// @@ -126,11 +133,12 @@ public BigInteger GetOracleValidatorsCount(StoreView snapshot) { return GetOracleValidators(snapshot).Length; } + /// /// A collection of delegated Oracle validator /// /// snapshot - /// + /// delegated Oracle validator internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetDelegateOracleValidators(StoreView snapshot) { byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); @@ -140,6 +148,7 @@ internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetD p.Value.Value.AsSerializable(1) )); } + /// /// Create a Oracle multisignature address /// @@ -150,6 +159,7 @@ public UInt160 GetOracleMultiSigAddress(StoreView snapshot) ECPoint[] validators = GetOracleValidators(snapshot); return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); } + /// /// Set timeout /// @@ -168,17 +178,18 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); return true; } + /// /// Get timeout /// /// VM - /// Parameter Array /// value [ContractMethod(1_00000000, ContractParameterType.Integer)] private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); } + /// /// Get timeout /// @@ -188,6 +199,7 @@ public int GetTimeOutMilliSeconds(StoreView snapshot) { return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_TimeOutMilliSeconds)].Value, 0); } + /// /// Set PerRequestFee /// @@ -206,6 +218,7 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) storage.Value = BitConverter.GetBytes(perRequestFee); return true; } + /// /// Get PerRequestFee /// @@ -217,10 +230,11 @@ private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) { return new Integer(GetPerRequestFee(engine.Snapshot)); } + /// /// Get PerRequestFee /// - /// VM + /// snapshot /// Value public int GetPerRequestFee(StoreView snapshot) { diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index c4d3d1512c..99254cf36b 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -125,25 +125,17 @@ public void Test_DelegateOracleValidator() KeyPair keyPair2 = new KeyPair(privateKey2); ECPoint pubkey2 = keyPair2.PublicKey; - ECPoint[] pubkeys = new ECPoint[2]; - pubkeys[0] = pubkey1; - pubkeys[1] = pubkey2; - var snapshot = Blockchain.Singleton.GetSnapshot(); using ScriptBuilder sb = new ScriptBuilder(); sb.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter { - Type = ContractParameterType.Hash160, - Value = Contract.CreateSignatureRedeemScript(pubkey1).ToScriptHash() + Type = ContractParameterType.ByteArray, + Value = pubkey1.ToArray() }, new ContractParameter { - Type = ContractParameterType.Array, - Value = pubkeys.Select(p => new ContractParameter - { - Type = ContractParameterType.PublicKey, - Value = p - }).ToArray() + Type = ContractParameterType.ByteArray, + Value = pubkey2.ToArray() }); MyWallet wallet = new MyWallet(); diff --git a/tests/neo.UnitTests/neo.UnitTests.csproj b/tests/neo.UnitTests/neo.UnitTests.csproj index 8deecdb7aa..1e40bfea79 100644 --- a/tests/neo.UnitTests/neo.UnitTests.csproj +++ b/tests/neo.UnitTests/neo.UnitTests.csproj @@ -1,4 +1,4 @@ - + Exe @@ -32,7 +32,4 @@ - - - From 3c4065505ef01085092a2813b4e7cc10815e2e92 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 17 Feb 2020 10:16:28 +0800 Subject: [PATCH 08/44] format --- src/neo/Oracle/OraclePolicyContract.cs | 4 ++-- src/neo/neo.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index b0e3f7de4a..0fcd26c3c4 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -174,7 +174,7 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); return true; } @@ -214,7 +214,7 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); - StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_PerRequestFee)); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_PerRequestFee)); storage.Value = BitConverter.GetBytes(perRequestFee); return true; } diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index 7892d3f5ec..7bc96cce8c 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -30,4 +30,4 @@ - + \ No newline at end of file From 6bf9c865d3a69313c7a5969d9a151e6d265d137f Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 17 Feb 2020 10:51:03 +0800 Subject: [PATCH 09/44] little change --- src/neo/Oracle/OraclePolicyContract.cs | 35 +++++++++++--------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index 0fcd26c3c4..38af0008f0 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -102,14 +102,22 @@ private StackItem GetOracleValidators(ApplicationEngine engine, Array args) /// Authorized Oracle validator public ECPoint[] GetOracleValidators(StoreView snapshot) { - ECPoint[] consensusPublicKey = PolicyContract.NEO.GetValidators(snapshot); - IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> hasDelegateOracleValidators = GetDelegateOracleValidators(snapshot).Where(p => consensusPublicKey.Contains(p.ConsensusPublicKey)); - foreach (var item in hasDelegateOracleValidators) + ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + for (int index = 0; index < oraclePubKeys.Length; index++) { - var index = System.Array.IndexOf(consensusPublicKey, item.ConsensusPublicKey); - if (index >= 0) consensusPublicKey[index] = item.OraclePublicKey; + var item1 = oraclePubKeys[index]; + byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, Helper.Concat(new[] { Prefix_Validator }, item1.ToArray())); + IEnumerable<(ECPoint oraclePubKey, ECPoint delegatePubKeys)> hasDelegateOracleValidators = snapshot.Storages.Find(prefix_key).Select(p => + ( + p.Key.Key.AsSerializable(1), + p.Value.Value.AsSerializable(1) + )); + foreach (var item2 in hasDelegateOracleValidators) + { + oraclePubKeys[index] = item2.delegatePubKeys; + } } - return consensusPublicKey; + return oraclePubKeys; } /// @@ -134,21 +142,6 @@ public BigInteger GetOracleValidatorsCount(StoreView snapshot) return GetOracleValidators(snapshot).Length; } - /// - /// A collection of delegated Oracle validator - /// - /// snapshot - /// delegated Oracle validator - internal IEnumerable<(ECPoint ConsensusPublicKey, ECPoint OraclePublicKey)> GetDelegateOracleValidators(StoreView snapshot) - { - byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); - return snapshot.Storages.Find(prefix_key).Select(p => - ( - p.Key.Key.AsSerializable(1), - p.Value.Value.AsSerializable(1) - )); - } - /// /// Create a Oracle multisignature address /// From 6e3369a62402fad9a3e2cd50ccee459673d78d1f Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 17 Feb 2020 11:00:23 +0800 Subject: [PATCH 10/44] little change --- src/neo/Oracle/OraclePolicyContract.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index 38af0008f0..d29939cb09 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -105,17 +105,10 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); for (int index = 0; index < oraclePubKeys.Length; index++) { - var item1 = oraclePubKeys[index]; - byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, Helper.Concat(new[] { Prefix_Validator }, item1.ToArray())); - IEnumerable<(ECPoint oraclePubKey, ECPoint delegatePubKeys)> hasDelegateOracleValidators = snapshot.Storages.Find(prefix_key).Select(p => - ( - p.Key.Key.AsSerializable(1), - p.Value.Value.AsSerializable(1) - )); - foreach (var item2 in hasDelegateOracleValidators) - { - oraclePubKeys[index] = item2.delegatePubKeys; - } + var oraclePubKey = oraclePubKeys[index]; + StorageKey key = CreateStorageKey(Prefix_Validator, oraclePubKey); + ECPoint delegatePubKey = snapshot.Storages.TryGet(key).Value.AsSerializable(1); + if (delegatePubKey != null) oraclePubKeys[index] = delegatePubKey; } return oraclePubKeys; } From 846d19574a8d927c091baf6017e7482858b01264 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 17 Feb 2020 11:08:34 +0800 Subject: [PATCH 11/44] little change --- src/neo/Oracle/OraclePolicyContract.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/Oracle/OraclePolicyContract.cs index d29939cb09..19cc0a54f6 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/Oracle/OraclePolicyContract.cs @@ -107,8 +107,8 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) { var oraclePubKey = oraclePubKeys[index]; StorageKey key = CreateStorageKey(Prefix_Validator, oraclePubKey); - ECPoint delegatePubKey = snapshot.Storages.TryGet(key).Value.AsSerializable(1); - if (delegatePubKey != null) oraclePubKeys[index] = delegatePubKey; + ECPoint delegatePubKey = snapshot.Storages.TryGet(key)?.Value.AsSerializable(1); + if (delegatePubKey != null) { oraclePubKeys[index] = delegatePubKey; } } return oraclePubKeys; } From 8b118c081e1f44f8a4c792e675c2844b152390c1 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Tue, 18 Feb 2020 14:27:48 +0800 Subject: [PATCH 12/44] change Fee & Fix bug --- .../Native}/Oracle/OraclePolicyContract.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) rename src/neo/{ => SmartContract/Native}/Oracle/OraclePolicyContract.cs (95%) diff --git a/src/neo/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs similarity index 95% rename from src/neo/Oracle/OraclePolicyContract.cs rename to src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 19cc0a54f6..f41ad887b7 100644 --- a/src/neo/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -1,7 +1,6 @@ using Neo.Cryptography.ECC; using Neo.IO; using Neo.Ledger; -using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Manifest; @@ -9,7 +8,6 @@ using Neo.VM; using Neo.VM.Types; using System; -using System.Collections.Generic; using System.Linq; using System.Numerics; using Array = Neo.VM.Types.Array; @@ -59,7 +57,7 @@ internal override bool Initialize(ApplicationEngine engine) /// VM /// Parameter Array /// Returns true if the execution is successful, otherwise returns false - [ContractMethod(0_01000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.ByteArray, ContractParameterType.ByteArray }, ParameterNames = new[] { "consignorPubKey", "consigneePubKey" })] + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.ByteArray, ContractParameterType.ByteArray }, ParameterNames = new[] { "consignorPubKey", "consigneePubKey" })] private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { ECPoint consignorPubKey = args[0].GetSpan().AsSerializable(); @@ -89,7 +87,7 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) /// VM /// Parameter Array /// Authorized Oracle validator - [ContractMethod(0_03000000, ContractParameterType.Array)] + [ContractMethod(0_01000000, ContractParameterType.Array)] private StackItem GetOracleValidators(ApplicationEngine engine, Array args) { return new Array(engine.ReferenceCounter, GetOracleValidators(engine.Snapshot).Select(p => (StackItem)p.ToArray())); @@ -107,7 +105,7 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) { var oraclePubKey = oraclePubKeys[index]; StorageKey key = CreateStorageKey(Prefix_Validator, oraclePubKey); - ECPoint delegatePubKey = snapshot.Storages.TryGet(key)?.Value.AsSerializable(1); + ECPoint delegatePubKey = snapshot.Storages.TryGet(key)?.Value.AsSerializable(); if (delegatePubKey != null) { oraclePubKeys[index] = delegatePubKey; } } return oraclePubKeys; @@ -119,7 +117,7 @@ public ECPoint[] GetOracleValidators(StoreView snapshot) /// VM /// Parameter Array /// The number of authorized Oracle validator - [ContractMethod(0_03000000, ContractParameterType.Integer)] + [ContractMethod(0_01000000, ContractParameterType.Integer)] private StackItem GetOracleValidatorsCount(ApplicationEngine engine, Array args) { return GetOracleValidatorsCount(engine.Snapshot); @@ -170,7 +168,7 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) /// /// VM /// value - [ContractMethod(1_00000000, ContractParameterType.Integer)] + [ContractMethod(0_01000000, ContractParameterType.Integer)] private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) { return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); @@ -211,7 +209,7 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) /// VM /// Parameter Array /// Value - [ContractMethod(1_00000000, ContractParameterType.Integer, SafeMethod = true)] + [ContractMethod(0_01000000, ContractParameterType.Integer, SafeMethod = true)] private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) { return new Integer(GetPerRequestFee(engine.Snapshot)); From 5d375c87bba03ab09d668e88a86a0818b5a965da Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 18 Feb 2020 09:16:22 +0100 Subject: [PATCH 13/44] Optimize --- .../SmartContract/Native/Oracle/OraclePolicyContract.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index f41ad887b7..7a7131a0e9 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -156,8 +156,8 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; - int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); + int timeOutMilliSeconds = (int)args[0].GetBigInteger(); + if (timeOutMilliSeconds <= 0) return false; StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); return true; @@ -196,8 +196,8 @@ private StackItem SetPerRequestFee(ApplicationEngine engine, Array args) StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; - int perRequestFee = BitConverter.ToInt32(args[0].GetSpan()); + int perRequestFee = (int)args[0].GetBigInteger(); + if (perRequestFee <= 0) return false; StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_PerRequestFee)); storage.Value = BitConverter.GetBytes(perRequestFee); return true; From 71e6add6071f4d7f159fd727e8d47e6ebfe98e8b Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 10:36:54 +0800 Subject: [PATCH 14/44] add config class --- .../Native/Oracle/OraclePolicyContract.cs | 49 +++++++++++++------ .../Native/Oracle/OraclePolicyHttpConfig.cs | 25 ++++++++++ tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 9 ++-- 3 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index f41ad887b7..26a09a4bae 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -5,9 +5,11 @@ using Neo.SmartContract; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; +using Neo.SmartContract.Native.Oracle; using Neo.VM; using Neo.VM.Types; using System; +using System.Collections.Generic; using System.Linq; using System.Numerics; using Array = Neo.VM.Types.Array; @@ -21,7 +23,7 @@ public sealed class OraclePolicyContract : NativeContract public override int Id => -4; private const byte Prefix_Validator = 24; - private const byte Prefix_TimeOutMilliSeconds = 25; + private const byte Prefix_HttpConfig = 25; private const byte Prefix_PerRequestFee = 26; /// @@ -40,9 +42,9 @@ public OraclePolicyContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_TimeOutMilliSeconds), new StorageItem + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem { - Value = BitConverter.GetBytes(5000) + Value = new OraclePolicyHttpConfig().ToArray() }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem { @@ -78,6 +80,23 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) Value = consigneePubKey.ToArray() }); } + byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); + List hasDelegateOracleValidators = snapshot.Storages.Find(prefix_key).Select(p => + ( + p.Key.Key.AsSerializable() + )).ToList(); + ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + foreach (var item in oraclePubKeys) + { + if (hasDelegateOracleValidators.Contains(item)) + { + hasDelegateOracleValidators.Remove(item); + } + } + foreach (var item in hasDelegateOracleValidators) + { + snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, item)); + } return true; } @@ -145,21 +164,21 @@ public UInt160 GetOracleMultiSigAddress(StoreView snapshot) } /// - /// Set timeout + /// Set HttpConfig /// /// VM /// Parameter Array /// Returns true if the execution is successful, otherwise returns false [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "TimeOutMilliSeconds" })] - private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) + private StackItem SetHttpConfig(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - if (BitConverter.ToInt32(args[0].GetSpan()) <= 0) return false; - int timeOutMilliSeconds = BitConverter.ToInt32(args[0].GetSpan()); - StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); - storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); + OraclePolicyHttpConfig httpConfig = args[0].GetSpan().AsSerializable(); + if (httpConfig.Timeout <= 0) return false; + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig)); + storage.Value = httpConfig.ToArray(); return true; } @@ -168,20 +187,20 @@ private StackItem SetTimeOutMilliSeconds(ApplicationEngine engine, Array args) /// /// VM /// value - [ContractMethod(0_01000000, ContractParameterType.Integer)] - private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) + [ContractMethod(0_01000000, ContractParameterType.ByteArray)] + private StackItem GetHttpConfig(ApplicationEngine engine, Array args) { - return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); + return GetHttpConfig(engine.Snapshot).ToArray(); } /// - /// Get timeout + /// Get HttpConfig /// /// snapshot /// value - public int GetTimeOutMilliSeconds(StoreView snapshot) + public OraclePolicyHttpConfig GetHttpConfig(StoreView snapshot) { - return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_TimeOutMilliSeconds)].Value, 0); + return snapshot.Storages[CreateStorageKey(Prefix_HttpConfig)].Value.AsSerializable(); } /// diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs new file mode 100644 index 0000000000..e45f51a0cb --- /dev/null +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs @@ -0,0 +1,25 @@ +using Neo.IO; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Neo.SmartContract.Native.Oracle +{ + public class OraclePolicyHttpConfig : ISerializable + { + public int Timeout { get; set; } + + public int Size => sizeof(int); + + public void Deserialize(BinaryReader reader) + { + Timeout = reader.ReadInt32(); + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(Timeout); + } + } +} diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index 99254cf36b..bffab99dd1 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -8,6 +8,7 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.SmartContract.Native.Oracle; using Neo.SmartContract.Native.Tokens; using Neo.UnitTests.Extensions; using Neo.UnitTests.Wallets; @@ -68,18 +69,18 @@ public void Test_GetPerRequestFee() } [TestMethod] - public void Test_GetTimeOutMilliSeconds() + public void Test_GetHttpConfig() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getTimeOutMilliSeconds"); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getHttpConfig"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); engine.Execute().Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.Integer)); - Assert.AreEqual(result, 5000); + result.Should().BeOfType(typeof(VM.Types.ByteArray)); + Assert.AreEqual(result, new OraclePolicyHttpConfig().ToArray()); } [TestMethod] From bbdf3f9c9b4d477615928ab422dcd3a91f4284dc Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 11:39:44 +0800 Subject: [PATCH 15/44] FiX UT --- ...PolicyHttpConfig.cs => OracleHttpConfig.cs} | 9 ++++++++- .../Native/Oracle/OraclePolicyContract.cs | 18 ++++++++++-------- tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 4 ++-- 3 files changed, 20 insertions(+), 11 deletions(-) rename src/neo/SmartContract/Native/Oracle/{OraclePolicyHttpConfig.cs => OracleHttpConfig.cs} (62%) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs b/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs similarity index 62% rename from src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs rename to src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs index e45f51a0cb..85b645b567 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyHttpConfig.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs @@ -1,4 +1,6 @@ using Neo.IO; +using Neo.VM; +using Neo.VM.Types; using System; using System.Collections.Generic; using System.IO; @@ -6,7 +8,7 @@ namespace Neo.SmartContract.Native.Oracle { - public class OraclePolicyHttpConfig : ISerializable + public class OracleHttpConfig : ISerializable, IInteroperable { public int Timeout { get; set; } @@ -21,5 +23,10 @@ public void Serialize(BinaryWriter writer) { writer.Write(Timeout); } + + public StackItem ToStackItem(ReferenceCounter referenceCounter) + { + return new VM.Types.Array(referenceCounter, new StackItem[]{Timeout}); + } } } diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index eb0e563bba..a4ef87506a 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -44,7 +44,7 @@ internal override bool Initialize(ApplicationEngine engine) if (!base.Initialize(engine)) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem { - Value = new OraclePolicyHttpConfig().ToArray() + Value = new OracleHttpConfig().ToArray() }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem { @@ -169,28 +169,30 @@ public UInt160 GetOracleMultiSigAddress(StoreView snapshot) /// VM /// Parameter Array /// Returns true if the execution is successful, otherwise returns false - [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "TimeOutMilliSeconds" })] + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "httpConfig" })] private StackItem SetHttpConfig(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - OraclePolicyHttpConfig httpConfig = args[0].GetSpan().AsSerializable(); - if (httpConfig.Timeout <= 0) return false; + int timeOutMilliSeconds = (int)args[0].GetBigInteger(); + if (timeOutMilliSeconds < 0) return false; + OracleHttpConfig httpConfig = new OracleHttpConfig(); + httpConfig.Timeout = timeOutMilliSeconds; StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig)); storage.Value = httpConfig.ToArray(); return true; } /// - /// Get timeout + /// Get HttpConfig /// /// VM /// value [ContractMethod(0_01000000, ContractParameterType.ByteArray)] private StackItem GetHttpConfig(ApplicationEngine engine, Array args) { - return GetHttpConfig(engine.Snapshot).ToArray(); + return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter); ; } /// @@ -198,9 +200,9 @@ private StackItem GetHttpConfig(ApplicationEngine engine, Array args) /// /// snapshot /// value - public OraclePolicyHttpConfig GetHttpConfig(StoreView snapshot) + public OracleHttpConfig GetHttpConfig(StoreView snapshot) { - return snapshot.Storages[CreateStorageKey(Prefix_HttpConfig)].Value.AsSerializable(); + return snapshot.Storages[CreateStorageKey(Prefix_HttpConfig)].Value.AsSerializable(); } /// diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index bffab99dd1..04749bbf6b 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -79,8 +79,8 @@ public void Test_GetHttpConfig() engine.Execute().Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.ByteArray)); - Assert.AreEqual(result, new OraclePolicyHttpConfig().ToArray()); + result.Should().BeOfType(typeof(VM.Types.Array)); + Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), new OracleHttpConfig().Timeout); } [TestMethod] From 21974071033ffe3255e6dc63d0e1a9cc8bc5f093 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 11:42:48 +0800 Subject: [PATCH 16/44] Format --- src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs b/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs index 85b645b567..5e763780df 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs @@ -26,7 +26,7 @@ public void Serialize(BinaryWriter writer) public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new VM.Types.Array(referenceCounter, new StackItem[]{Timeout}); + return new VM.Types.Array(referenceCounter, new StackItem[] { Timeout }); } } } From a81a1e5c37ced80d11b5621d1e8fd4e83dc5bb69 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 11:56:52 +0800 Subject: [PATCH 17/44] Fix UT --- src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index a4ef87506a..ca525bf2bd 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -189,7 +189,7 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) /// /// VM /// value - [ContractMethod(0_01000000, ContractParameterType.ByteArray)] + [ContractMethod(0_01000000, ContractParameterType.Array)] private StackItem GetHttpConfig(ApplicationEngine engine, Array args) { return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter); ; From f4e69dc1108d83c42c481feae93fdfed85a5d1b5 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 14:01:10 +0800 Subject: [PATCH 18/44] Fix format and Optimize --- .../Native/Oracle/OraclePolicyContract.cs | 22 ++++++++----------- tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index ca525bf2bd..4fc69e8447 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -44,7 +44,7 @@ internal override bool Initialize(ApplicationEngine engine) if (!base.Initialize(engine)) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem { - Value = new OracleHttpConfig().ToArray() + Value = new OracleHttpConfig() { Timeout = 5000 }.ToArray() }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem { @@ -80,23 +80,20 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) Value = consigneePubKey.ToArray() }); } - byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); - List hasDelegateOracleValidators = snapshot.Storages.Find(prefix_key).Select(p => + + byte[] prefixKey = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); + List delegatedOracleValidators = snapshot.Storages.Find(prefixKey).Select(p => ( p.Key.Key.AsSerializable() )).ToList(); ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); - foreach (var item in oraclePubKeys) + foreach (var item in delegatedOracleValidators) { - if (hasDelegateOracleValidators.Contains(item)) + if (!oraclePubKeys.Contains(item)) { - hasDelegateOracleValidators.Remove(item); + snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, item)); } } - foreach (var item in hasDelegateOracleValidators) - { - snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, item)); - } return true; } @@ -177,8 +174,7 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; int timeOutMilliSeconds = (int)args[0].GetBigInteger(); if (timeOutMilliSeconds < 0) return false; - OracleHttpConfig httpConfig = new OracleHttpConfig(); - httpConfig.Timeout = timeOutMilliSeconds; + OracleHttpConfig httpConfig = new OracleHttpConfig() { Timeout = timeOutMilliSeconds }; StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig)); storage.Value = httpConfig.ToArray(); return true; @@ -192,7 +188,7 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) [ContractMethod(0_01000000, ContractParameterType.Array)] private StackItem GetHttpConfig(ApplicationEngine engine, Array args) { - return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter); ; + return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter); } /// diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs index 04749bbf6b..39cdd523bd 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs @@ -80,7 +80,7 @@ public void Test_GetHttpConfig() engine.Execute().Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Array)); - Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), new OracleHttpConfig().Timeout); + Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), 5000); } [TestMethod] From 0c2b34bbe7fb0e9680a857d6dc91e9411f03cee5 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 20 Feb 2020 13:13:18 +0100 Subject: [PATCH 19/44] Add some UT --- .../Native/Oracle/OraclePolicyContract.cs | 2 +- .../Native}/Oracle/UT_OraclePolicy.cs | 93 +++++++++++++++++-- 2 files changed, 88 insertions(+), 7 deletions(-) rename tests/neo.UnitTests/{ => SmartContract/Native}/Oracle/UT_OraclePolicy.cs (62%) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 4fc69e8447..e1db54f7a7 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -173,7 +173,7 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; int timeOutMilliSeconds = (int)args[0].GetBigInteger(); - if (timeOutMilliSeconds < 0) return false; + if (timeOutMilliSeconds <= 0) return false; OracleHttpConfig httpConfig = new OracleHttpConfig() { Timeout = timeOutMilliSeconds }; StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig)); storage.Value = httpConfig.ToArray(); diff --git a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs similarity index 62% rename from tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs rename to tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index 39cdd523bd..13f99781a9 100644 --- a/tests/neo.UnitTests/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -4,20 +4,15 @@ using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; -using Neo.Oracle; -using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.SmartContract.Native.Oracle; using Neo.SmartContract.Native.Tokens; -using Neo.UnitTests.Extensions; using Neo.UnitTests.Wallets; using Neo.VM; -using Neo.VM.Types; using Neo.Wallets; using System; using System.Linq; -using System.Numerics; +using static Neo.UnitTests.Extensions.Nep5NativeContractExtensions; namespace Neo.UnitTests.Oracle { @@ -68,6 +63,43 @@ public void Test_GetPerRequestFee() Assert.AreEqual(result, 1000); } + [TestMethod] + public void Test_SetPerRequestFee() + { + var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + + // Init + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); + var from = NativeContract.OraclePolicy.GetOracleMultiSigAddress(snapshot); + var value = 12345; + + // Set + + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); + + // Get + + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getPerRequestFee"); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Integer)); + Assert.AreEqual(result, value); + } + [TestMethod] public void Test_GetHttpConfig() { @@ -83,6 +115,55 @@ public void Test_GetHttpConfig() Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), 5000); } + [TestMethod] + public void Test_SetHttpConfig() + { + var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); + + // Init + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); + var from = NativeContract.OraclePolicy.GetOracleMultiSigAddress(snapshot); + var value = 12345; + + // Set wrong (negative) + + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + + // Set good + + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = value }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); + + // Get + + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getHttpConfig"); + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Array)); + Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), value); + } + [TestMethod] public void Test_GetOracleValidators() { From 591b33bfa7b6a93548953f3b22b4e0af6db4b428 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 21 Feb 2020 13:51:40 +0800 Subject: [PATCH 20/44] Fix bug and add UT --- .../Native/Oracle/OraclePolicyContract.cs | 2 +- .../Native/Oracle/UT_OraclePolicy.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index e1db54f7a7..b75b8dbb0e 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -84,7 +84,7 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) byte[] prefixKey = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); List delegatedOracleValidators = snapshot.Storages.Find(prefixKey).Select(p => ( - p.Key.Key.AsSerializable() + p.Key.Key.AsSerializable(1) )).ToList(); ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); foreach (var item in delegatedOracleValidators) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index 13f99781a9..a41b5e1004 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -242,7 +242,23 @@ public void Test_DelegateOracleValidator() tx.Witnesses = context.GetWitnesses(); var engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); + engine.LoadScript(tx.Script); + var state=engine.Execute(); + state.Should().Be(VMState.HALT); + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + + var from = Contract.CreateSignatureContract(pubkey1).ScriptHash; + + + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(tx.Script.ToArray()); + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); } } } From 61bb96a72be47108f3fd140f3bc113ce77eaf828 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 20 Feb 2020 23:57:42 -0600 Subject: [PATCH 21/44] Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs Co-Authored-By: Luchuan --- src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index b75b8dbb0e..bb910ddbde 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -70,7 +70,8 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) StorageKey key = CreateStorageKey(Prefix_Validator, consignorPubKey); if (snapshot.Storages.TryGet(key) != null) { - StorageItem value = snapshot.Storages.GetAndChange(key); + StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem()); + item.Value = consigneePubKey.ToArray(); value.Value = consigneePubKey.ToArray(); } else From 531427ebe80bb759251511417b521fe1162a9c21 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 21 Feb 2020 14:06:48 +0800 Subject: [PATCH 22/44] little change --- .../Native/Oracle/OraclePolicyContract.cs | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index bb910ddbde..9a96bbc476 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -68,19 +68,8 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; StoreView snapshot = engine.Snapshot; StorageKey key = CreateStorageKey(Prefix_Validator, consignorPubKey); - if (snapshot.Storages.TryGet(key) != null) - { - StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem()); - item.Value = consigneePubKey.ToArray(); - value.Value = consigneePubKey.ToArray(); - } - else - { - snapshot.Storages.Add(key, new StorageItem - { - Value = consigneePubKey.ToArray() - }); - } + StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem()); + item.Value = consigneePubKey.ToArray(); byte[] prefixKey = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); List delegatedOracleValidators = snapshot.Storages.Find(prefixKey).Select(p => @@ -88,11 +77,11 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) p.Key.Key.AsSerializable(1) )).ToList(); ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); - foreach (var item in delegatedOracleValidators) + foreach (var validator in delegatedOracleValidators) { - if (!oraclePubKeys.Contains(item)) + if (!oraclePubKeys.Contains(validator)) { - snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, item)); + snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, validator)); } } return true; From 2d8a645daaef114be6e7fcc2a2f9e809ebf2847d Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 21 Feb 2020 14:17:58 +0800 Subject: [PATCH 23/44] format --- .../SmartContract/Native/Oracle/UT_OraclePolicy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index a41b5e1004..43f4732455 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -243,7 +243,7 @@ public void Test_DelegateOracleValidator() var engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); engine.LoadScript(tx.Script); - var state=engine.Execute(); + var state = engine.Execute(); state.Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Boolean)); From 99d6761c933ba06b254eaf3421dedeac67a90e35 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 21 Feb 2020 08:27:59 -0600 Subject: [PATCH 24/44] Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs Co-Authored-By: Shargon --- src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 9a96bbc476..bf2cd7bba0 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -54,7 +54,7 @@ internal override bool Initialize(ApplicationEngine engine) } /// - /// Oracle validator can delegate third party to operate Oracle nodes + /// Consensus node can delegate third party to operate Oracle nodes /// /// VM /// Parameter Array From cc6774ff0e865932eb7b891e099b104088735181 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 21 Feb 2020 23:47:27 +0800 Subject: [PATCH 25/44] add check --- .../Native/Oracle/OraclePolicyContract.cs | 5 +++-- .../Native/Oracle/UT_OraclePolicy.cs | 19 ++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 9a96bbc476..4b5fa4578c 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -62,11 +62,13 @@ internal override bool Initialize(ApplicationEngine engine) [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.ByteArray, ContractParameterType.ByteArray }, ParameterNames = new[] { "consignorPubKey", "consigneePubKey" })] private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { + StoreView snapshot = engine.Snapshot; ECPoint consignorPubKey = args[0].GetSpan().AsSerializable(); ECPoint consigneePubKey = args[1].GetSpan().AsSerializable(); + ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + if (!oraclePubKeys.Contains(consignorPubKey)) return false; UInt160 account = Contract.CreateSignatureRedeemScript(consignorPubKey).ToScriptHash(); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - StoreView snapshot = engine.Snapshot; StorageKey key = CreateStorageKey(Prefix_Validator, consignorPubKey); StorageItem item = snapshot.Storages.GetAndChange(key, () => new StorageItem()); item.Value = consigneePubKey.ToArray(); @@ -76,7 +78,6 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) ( p.Key.Key.AsSerializable(1) )).ToList(); - ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); foreach (var validator in delegatedOracleValidators) { if (!oraclePubKeys.Contains(validator)) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index 43f4732455..3642a060cf 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -197,27 +197,25 @@ public void Test_GetOracleValidatorsCount() [TestMethod] public void Test_DelegateOracleValidator() { + var snapshot = Blockchain.Singleton.GetSnapshot(); + + ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + + ECPoint pubkey0 = oraclePubKeys[0]; byte[] privateKey1 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair keyPair1 = new KeyPair(privateKey1); ECPoint pubkey1 = keyPair1.PublicKey; - byte[] privateKey2 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; - KeyPair keyPair2 = new KeyPair(privateKey2); - ECPoint pubkey2 = keyPair2.PublicKey; - - var snapshot = Blockchain.Singleton.GetSnapshot(); - using ScriptBuilder sb = new ScriptBuilder(); sb.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter { Type = ContractParameterType.ByteArray, - Value = pubkey1.ToArray() + Value = pubkey0.ToArray() }, new ContractParameter { Type = ContractParameterType.ByteArray, - Value = pubkey2.ToArray() + Value = pubkey1.ToArray() }); MyWallet wallet = new MyWallet(); @@ -249,8 +247,7 @@ public void Test_DelegateOracleValidator() result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); - var from = Contract.CreateSignatureContract(pubkey1).ScriptHash; - + var from = Contract.CreateSignatureContract(pubkey0).ScriptHash; engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(tx.Script.ToArray()); From 696399c9bd5166e4b7e1d3e79174d2e65f37fd46 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sun, 23 Feb 2020 21:40:56 +0800 Subject: [PATCH 26/44] change validator --- src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 9233e62610..eb9025ef07 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -147,7 +147,7 @@ public BigInteger GetOracleValidatorsCount(StoreView snapshot) /// Oracle multisignature address public UInt160 GetOracleMultiSigAddress(StoreView snapshot) { - ECPoint[] validators = GetOracleValidators(snapshot); + ECPoint[] validators = PolicyContract.NEO.GetValidators(snapshot); return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); } From 9dfc1f8d123b6c367824f79e18d667c17a099759 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 24 Feb 2020 13:19:17 +0100 Subject: [PATCH 27/44] Add double initialization check --- src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index eb9025ef07..5802a96d6d 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -42,6 +42,7 @@ public OraclePolicyContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; + if (GetPerRequestFee(engine.Snapshot) != 0) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem { Value = new OracleHttpConfig() { Timeout = 5000 }.ToArray() From 5d9fa90899be33716104ec82a95187ccfd8b55ca Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 26 Feb 2020 17:51:08 +0800 Subject: [PATCH 28/44] add UT --- .../Native/Oracle/OraclePolicyContract.cs | 1 - .../Native/Oracle/UT_OraclePolicy.cs | 37 ++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs index 5802a96d6d..eb9025ef07 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs @@ -42,7 +42,6 @@ public OraclePolicyContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - if (GetPerRequestFee(engine.Snapshot) != 0) return false; engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem { Value = new OracleHttpConfig() { Timeout = 5000 }.ToArray() diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index 3642a060cf..c46e715d61 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -75,8 +75,7 @@ public void Test_SetPerRequestFee() var from = NativeContract.OraclePolicy.GetOracleMultiSigAddress(snapshot); var value = 12345; - // Set - + // Set var script = new ScriptBuilder(); script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); @@ -87,6 +86,29 @@ public void Test_SetPerRequestFee() result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); + // Set (wrong witness) + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + + // Set wrong (negative) + + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = -1 }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + // Get script = new ScriptBuilder(); @@ -139,6 +161,17 @@ public void Test_SetHttpConfig() result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + // Set (wrong witness) + script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + engine.Execute().Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + // Set good script = new ScriptBuilder(); From 740ccb76fe529b3f60796e2f10d3e51908ca9baf Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 26 Feb 2020 21:54:22 +0800 Subject: [PATCH 29/44] Add UT --- .../Native/Oracle/UT_OraclePolicy.cs | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index c46e715d61..886ad01bec 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -235,11 +235,17 @@ public void Test_DelegateOracleValidator() ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); ECPoint pubkey0 = oraclePubKeys[0]; + byte[] privateKey1 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair keyPair1 = new KeyPair(privateKey1); ECPoint pubkey1 = keyPair1.PublicKey; + byte[] privateKey2 = { 0x02,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair2 = new KeyPair(privateKey2); + ECPoint pubkey2 = keyPair2.PublicKey; + using ScriptBuilder sb = new ScriptBuilder(); sb.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter { @@ -272,6 +278,7 @@ public void Test_DelegateOracleValidator() wallet.Sign(context); tx.Witnesses = context.GetWitnesses(); + // wrong witness var engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); engine.LoadScript(tx.Script); var state = engine.Execute(); @@ -280,7 +287,30 @@ public void Test_DelegateOracleValidator() result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); - var from = Contract.CreateSignatureContract(pubkey0).ScriptHash; + //wrong witness + using ScriptBuilder sb2 = new ScriptBuilder(); + sb2.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter + { + Type = ContractParameterType.ByteArray, + Value = pubkey1.ToArray() + }, new ContractParameter + { + Type = ContractParameterType.ByteArray, + Value = pubkey2.ToArray() + }); + + var from = Contract.CreateSignatureContract(pubkey1).ScriptHash; + + engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); + engine.LoadScript(sb2.ToArray()); + state = engine.Execute(); + state.Should().Be(VMState.HALT); + result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + + //correct + from = Contract.CreateSignatureContract(pubkey0).ScriptHash; engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(tx.Script.ToArray()); From c693e7cde8d2dfcf019e7df231987036d692f545 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 26 Feb 2020 23:46:36 +0800 Subject: [PATCH 30/44] change UT --- .../neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index 886ad01bec..aa6c1fbb17 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -319,6 +319,7 @@ public void Test_DelegateOracleValidator() result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); + Test_GetOracleValidators(); } } } From 30577c579bef08c2adcf4c9696eba50e5df1faa4 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Thu, 27 Feb 2020 16:42:30 +0800 Subject: [PATCH 31/44] fill UT --- .../Native/Oracle/UT_OraclePolicy.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs index aa6c1fbb17..f65a51be9f 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs @@ -201,6 +201,19 @@ public void Test_SetHttpConfig() public void Test_GetOracleValidators() { var snapshot = Blockchain.Singleton.GetSnapshot(); + ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + + // Fake a oracle validator has cosignor. + ECPoint pubkey0 = oraclePubKeys[0]; // Validator0 is the cosignor + ECPoint cosignorPubKey = oraclePubKeys[1]; // Validator1 is the cosignee + var validator0Key = NativeContract.OraclePolicy.CreateStorageKey(24, pubkey0); // 24 = Prefix_Validator + var validator0Value = new StorageItem() + { + Value = cosignorPubKey.ToArray() + }; + snapshot.Storages.Add(validator0Key, validator0Value); + snapshot.Commit(); + var script = new ScriptBuilder(); script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getOracleValidators"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); @@ -210,6 +223,14 @@ public void Test_GetOracleValidators() var result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Array)); Assert.AreEqual(((VM.Types.Array)result).Count, 7); + + // The validator0's cosignee should be the validator1 + var validators = (VM.Types.Array)result; + var cosignee0Bytes = (VM.Types.ByteArray)validators[0]; + var cosignee1Bytes = (VM.Types.ByteArray)validators[1]; + Assert.AreEqual(cosignee0Bytes, cosignee1Bytes); + VM.Types.ByteArray validator1Bytes = cosignorPubKey.ToArray(); + Assert.AreEqual(cosignee1Bytes, validator1Bytes); } [TestMethod] @@ -271,6 +292,19 @@ public void Test_DelegateOracleValidator() Balance = 1000000 * NativeContract.GAS.Factor } .ToByteArray(); + + // Fake an nonexist validator in delegatedOracleValidators + byte[] fakerPrivateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02}; + KeyPair fakerKeyPair = new KeyPair(fakerPrivateKey); + ECPoint fakerPubkey = fakerKeyPair.PublicKey; + var invalidOracleValidatorKey = NativeContract.OraclePolicy.CreateStorageKey(24, fakerPubkey); // 24 = Prefix_Validator + var invalidOracleValidatorValue = new StorageItem() + { + Value = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01").ToArray() + }; + snapshot.Storages.Add(invalidOracleValidatorKey, invalidOracleValidatorValue); + snapshot.Commit(); var tx = wallet.MakeTransaction(sb.ToArray(), account.ScriptHash, new TransactionAttribute[] { }); @@ -319,6 +353,10 @@ public void Test_DelegateOracleValidator() result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsTrue((result as VM.Types.Boolean).ToBoolean()); + + // The invalid oracle validator should be removed + Assert.IsNull(snapshot.Storages.TryGet(invalidOracleValidatorKey)); + Test_GetOracleValidators(); } } From 985f0a49352106bbc056ffc23987f519c76f4ce8 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Thu, 27 Feb 2020 18:57:08 +0800 Subject: [PATCH 32/44] up ut and fix NeoToken.GetValidators --- .../SmartContract/Native/NativeContract.cs | 2 +- ...clePolicyContract.cs => OracleContract.cs} | 19 ++---- .../SmartContract/Native/Tokens/NeoToken.cs | 8 ++- ...T_OraclePolicy.cs => UT_OracleContract.cs} | 62 ++++++++++--------- 4 files changed, 46 insertions(+), 45 deletions(-) rename src/neo/SmartContract/Native/Oracle/{OraclePolicyContract.cs => OracleContract.cs} (94%) rename tests/neo.UnitTests/SmartContract/Native/Oracle/{UT_OraclePolicy.cs => UT_OracleContract.cs} (83%) diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index 7335d66dc5..dacf659241 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -24,7 +24,7 @@ public abstract class NativeContract public static NeoToken NEO { get; } = new NeoToken(); public static GasToken GAS { get; } = new GasToken(); public static PolicyContract Policy { get; } = new PolicyContract(); - public static OraclePolicyContract OraclePolicy { get; } = new OraclePolicyContract(); + public static OracleContract Oracle { get; } = new OracleContract(); public abstract string ServiceName { get; } public uint ServiceHash { get; } diff --git a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs similarity index 94% rename from src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs rename to src/neo/SmartContract/Native/Oracle/OracleContract.cs index eb9025ef07..7c4f2d5d34 100644 --- a/src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -16,7 +16,7 @@ namespace Neo.Oracle { - public sealed class OraclePolicyContract : NativeContract + public sealed class OracleContract : NativeContract { public override string ServiceName => "Neo.Native.Oracle.Policy"; @@ -26,19 +26,11 @@ public sealed class OraclePolicyContract : NativeContract private const byte Prefix_HttpConfig = 25; private const byte Prefix_PerRequestFee = 26; - /// - /// Constructor - /// - public OraclePolicyContract() + public OracleContract() { Manifest.Features = ContractFeatures.HasStorage; } - /// - /// Initialization.Set default parameter value. - /// - /// VM - /// Returns true if the execution is successful, otherwise returns false internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; @@ -65,7 +57,7 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) StoreView snapshot = engine.Snapshot; ECPoint consignorPubKey = args[0].GetSpan().AsSerializable(); ECPoint consigneePubKey = args[1].GetSpan().AsSerializable(); - ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); if (!oraclePubKeys.Contains(consignorPubKey)) return false; UInt160 account = Contract.CreateSignatureRedeemScript(consignorPubKey).ToScriptHash(); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; @@ -82,6 +74,7 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { if (!oraclePubKeys.Contains(validator)) { + Console.WriteLine("start to delete invalidator...."); snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, validator)); } } @@ -107,7 +100,7 @@ private StackItem GetOracleValidators(ApplicationEngine engine, Array args) /// Authorized Oracle validator public ECPoint[] GetOracleValidators(StoreView snapshot) { - ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); for (int index = 0; index < oraclePubKeys.Length; index++) { var oraclePubKey = oraclePubKeys[index]; @@ -147,7 +140,7 @@ public BigInteger GetOracleValidatorsCount(StoreView snapshot) /// Oracle multisignature address public UInt160 GetOracleMultiSigAddress(StoreView snapshot) { - ECPoint[] validators = PolicyContract.NEO.GetValidators(snapshot); + ECPoint[] validators = NativeContract.NEO.GetValidators(snapshot); return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); } diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index aaea004edf..fd1455ad16 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -203,6 +203,7 @@ private StackItem GetRegisteredValidators(ApplicationEngine engine, Array args) public IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetRegisteredValidators(StoreView snapshot) { byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); + Console.WriteLine("get register validator key: " + prefix_key.ToHexString()); return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), @@ -219,7 +220,12 @@ private StackItem GetValidators(ApplicationEngine engine, Array args) public ECPoint[] GetValidators(StoreView snapshot) { StorageItem storage_count = snapshot.Storages.TryGet(CreateStorageKey(Prefix_ValidatorsCount)); - if (storage_count is null) return Blockchain.StandbyValidators; + if (storage_count is null) + { + ECPoint[] validators = new ECPoint[Blockchain.StandbyValidators.Length]; + System.Array.Copy(Blockchain.StandbyValidators, validators, validators.Length); + return validators; + } ValidatorsCountState state_count = ValidatorsCountState.FromByteArray(storage_count.Value); int count = (int)state_count.Votes.Select((p, i) => new { diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs similarity index 83% rename from tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs rename to tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs index f65a51be9f..66011a238b 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OraclePolicy.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs @@ -17,7 +17,7 @@ namespace Neo.UnitTests.Oracle { [TestClass] - public class UT_OraclePolicy + public class UT_OracleContract { [TestInitialize] public void TestSetup() @@ -34,13 +34,13 @@ public void TestInitialize() snapshot.Storages.Delete(CreateStorageKey(11)); snapshot.PersistingBlock = Blockchain.GenesisBlock; engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); + NativeContract.Oracle.Initialize(engine).Should().BeTrue(); } internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) { StorageKey storageKey = new StorageKey { - Id = NativeContract.OraclePolicy.Id, + Id = NativeContract.Oracle.Id, Key = new byte[sizeof(byte) + (key?.Length ?? 0)] }; storageKey.Key[0] = prefix; @@ -53,7 +53,7 @@ public void Test_GetPerRequestFee() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getPerRequestFee"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getPerRequestFee"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -71,13 +71,13 @@ public void Test_SetPerRequestFee() // Init var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); - var from = NativeContract.OraclePolicy.GetOracleMultiSigAddress(snapshot); + NativeContract.Oracle.Initialize(engine).Should().BeTrue(); + var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); var value = 12345; // Set var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -88,7 +88,7 @@ public void Test_SetPerRequestFee() // Set (wrong witness) script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -100,7 +100,7 @@ public void Test_SetPerRequestFee() // Set wrong (negative) script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = -1 }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setPerRequestFee", new ContractParameter(ContractParameterType.Integer) { Value = -1 }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -112,7 +112,7 @@ public void Test_SetPerRequestFee() // Get script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getPerRequestFee"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getPerRequestFee"); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -127,7 +127,7 @@ public void Test_GetHttpConfig() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getHttpConfig"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -145,14 +145,14 @@ public void Test_SetHttpConfig() // Init var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.OraclePolicy.Initialize(engine).Should().BeTrue(); - var from = NativeContract.OraclePolicy.GetOracleMultiSigAddress(snapshot); + NativeContract.Oracle.Initialize(engine).Should().BeTrue(); + var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); var value = 12345; // Set wrong (negative) var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -163,7 +163,7 @@ public void Test_SetHttpConfig() // Set (wrong witness) script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -175,7 +175,7 @@ public void Test_SetHttpConfig() // Set good script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -187,7 +187,7 @@ public void Test_SetHttpConfig() // Get script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getHttpConfig"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig"); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -201,21 +201,20 @@ public void Test_SetHttpConfig() public void Test_GetOracleValidators() { var snapshot = Blockchain.Singleton.GetSnapshot(); - ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); - // Fake a oracle validator has cosignor. + // Fake a oracle validator has cosignee. + ECPoint[] oraclePubKeys = NativeContract.Oracle.GetOracleValidators(snapshot); ECPoint pubkey0 = oraclePubKeys[0]; // Validator0 is the cosignor ECPoint cosignorPubKey = oraclePubKeys[1]; // Validator1 is the cosignee - var validator0Key = NativeContract.OraclePolicy.CreateStorageKey(24, pubkey0); // 24 = Prefix_Validator + var validator0Key = NativeContract.Oracle.CreateStorageKey(24, pubkey0); // 24 = Prefix_Validator var validator0Value = new StorageItem() { Value = cosignorPubKey.ToArray() }; snapshot.Storages.Add(validator0Key, validator0Value); - snapshot.Commit(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getOracleValidators"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getOracleValidators"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -231,6 +230,9 @@ public void Test_GetOracleValidators() Assert.AreEqual(cosignee0Bytes, cosignee1Bytes); VM.Types.ByteArray validator1Bytes = cosignorPubKey.ToArray(); Assert.AreEqual(cosignee1Bytes, validator1Bytes); + + // clear data + snapshot.Storages.Delete(validator0Key); } [TestMethod] @@ -238,7 +240,7 @@ public void Test_GetOracleValidatorsCount() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.OraclePolicy.Hash, "getOracleValidatorsCount"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getOracleValidatorsCount"); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -253,7 +255,7 @@ public void Test_DelegateOracleValidator() { var snapshot = Blockchain.Singleton.GetSnapshot(); - ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot); + ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); ECPoint pubkey0 = oraclePubKeys[0]; @@ -268,7 +270,7 @@ public void Test_DelegateOracleValidator() ECPoint pubkey2 = keyPair2.PublicKey; using ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter + sb.EmitAppCall(NativeContract.Oracle.Hash, "delegateOracleValidator", new ContractParameter { Type = ContractParameterType.ByteArray, Value = pubkey0.ToArray() @@ -293,20 +295,20 @@ public void Test_DelegateOracleValidator() } .ToByteArray(); + snapshot.Commit(); + // Fake an nonexist validator in delegatedOracleValidators byte[] fakerPrivateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02}; KeyPair fakerKeyPair = new KeyPair(fakerPrivateKey); ECPoint fakerPubkey = fakerKeyPair.PublicKey; - var invalidOracleValidatorKey = NativeContract.OraclePolicy.CreateStorageKey(24, fakerPubkey); // 24 = Prefix_Validator + var invalidOracleValidatorKey = NativeContract.Oracle.CreateStorageKey(24, fakerPubkey); // 24 = Prefix_Validator var invalidOracleValidatorValue = new StorageItem() { - Value = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01").ToArray() + Value = fakerPubkey.ToArray() }; snapshot.Storages.Add(invalidOracleValidatorKey, invalidOracleValidatorValue); - snapshot.Commit(); - var tx = wallet.MakeTransaction(sb.ToArray(), account.ScriptHash, new TransactionAttribute[] { }); ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); @@ -323,7 +325,7 @@ public void Test_DelegateOracleValidator() //wrong witness using ScriptBuilder sb2 = new ScriptBuilder(); - sb2.EmitAppCall(NativeContract.OraclePolicy.Hash, "delegateOracleValidator", new ContractParameter + sb2.EmitAppCall(NativeContract.Oracle.Hash, "delegateOracleValidator", new ContractParameter { Type = ContractParameterType.ByteArray, Value = pubkey1.ToArray() From d042560ba9da5fcfd9e9bde6a1bfe086be9cc14e Mon Sep 17 00:00:00 2001 From: Luchuan Date: Thu, 27 Feb 2020 19:06:03 +0800 Subject: [PATCH 33/44] remove console --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 1 - src/neo/SmartContract/Native/Tokens/NeoToken.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 7c4f2d5d34..ee6a1c8319 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -74,7 +74,6 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) { if (!oraclePubKeys.Contains(validator)) { - Console.WriteLine("start to delete invalidator...."); snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, validator)); } } diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index fd1455ad16..16d6234fae 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -203,7 +203,6 @@ private StackItem GetRegisteredValidators(ApplicationEngine engine, Array args) public IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetRegisteredValidators(StoreView snapshot) { byte[] prefix_key = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator }); - Console.WriteLine("get register validator key: " + prefix_key.ToHexString()); return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.AsSerializable(1), From 704051ab753f1d4c1d7369757109fab1055ef7d1 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 28 Feb 2020 18:14:32 +0800 Subject: [PATCH 34/44] reset NEO.getValidators --- src/neo/SmartContract/Native/Tokens/NeoToken.cs | 7 +------ .../SmartContract/Native/Oracle/UT_OracleContract.cs | 3 ++- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 16d6234fae..aaea004edf 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -219,12 +219,7 @@ private StackItem GetValidators(ApplicationEngine engine, Array args) public ECPoint[] GetValidators(StoreView snapshot) { StorageItem storage_count = snapshot.Storages.TryGet(CreateStorageKey(Prefix_ValidatorsCount)); - if (storage_count is null) - { - ECPoint[] validators = new ECPoint[Blockchain.StandbyValidators.Length]; - System.Array.Copy(Blockchain.StandbyValidators, validators, validators.Length); - return validators; - } + if (storage_count is null) return Blockchain.StandbyValidators; ValidatorsCountState state_count = ValidatorsCountState.FromByteArray(storage_count.Value); int count = (int)state_count.Votes.Select((p, i) => new { diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs index 66011a238b..26b3b45cf6 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs @@ -204,6 +204,7 @@ public void Test_GetOracleValidators() // Fake a oracle validator has cosignee. ECPoint[] oraclePubKeys = NativeContract.Oracle.GetOracleValidators(snapshot); + ECPoint pubkey0 = oraclePubKeys[0]; // Validator0 is the cosignor ECPoint cosignorPubKey = oraclePubKeys[1]; // Validator1 is the cosignee var validator0Key = NativeContract.Oracle.CreateStorageKey(24, pubkey0); // 24 = Prefix_Validator @@ -255,7 +256,7 @@ public void Test_DelegateOracleValidator() { var snapshot = Blockchain.Singleton.GetSnapshot(); - ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); + ECPoint[] oraclePubKeys = NativeContract.Oracle.GetOracleValidators(snapshot); ECPoint pubkey0 = oraclePubKeys[0]; From 953a288e10474973f87a2689a000f5b80bcc9db7 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Mon, 2 Mar 2020 18:51:03 +0800 Subject: [PATCH 35/44] fix GetOracleValidators --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index ee6a1c8319..027a1da0c7 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -99,7 +99,9 @@ private StackItem GetOracleValidators(ApplicationEngine engine, Array args) /// Authorized Oracle validator public ECPoint[] GetOracleValidators(StoreView snapshot) { - ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); + ECPoint[] cnPubKeys = NativeContract.NEO.GetValidators(snapshot); + ECPoint[] oraclePubKeys = new ECPoint[cnPubKeys.Length]; + System.Array.Copy(cnPubKeys, oraclePubKeys, cnPubKeys.Length); for (int index = 0; index < oraclePubKeys.Length; index++) { var oraclePubKey = oraclePubKeys[index]; From aad74d93defe0dc1f7a0b3ad202cb92a3d7c8a04 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 2 Mar 2020 16:14:57 +0100 Subject: [PATCH 36/44] Rename variable --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 027a1da0c7..5fad6fa2c6 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -57,8 +57,8 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) StoreView snapshot = engine.Snapshot; ECPoint consignorPubKey = args[0].GetSpan().AsSerializable(); ECPoint consigneePubKey = args[1].GetSpan().AsSerializable(); - ECPoint[] oraclePubKeys = NativeContract.NEO.GetValidators(snapshot); - if (!oraclePubKeys.Contains(consignorPubKey)) return false; + ECPoint[] cnPubKeys = NativeContract.NEO.GetValidators(snapshot); + if (!cnPubKeys.Contains(consignorPubKey)) return false; UInt160 account = Contract.CreateSignatureRedeemScript(consignorPubKey).ToScriptHash(); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; StorageKey key = CreateStorageKey(Prefix_Validator, consignorPubKey); @@ -72,7 +72,7 @@ private StackItem DelegateOracleValidator(ApplicationEngine engine, Array args) )).ToList(); foreach (var validator in delegatedOracleValidators) { - if (!oraclePubKeys.Contains(validator)) + if (!cnPubKeys.Contains(validator)) { snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, validator)); } @@ -141,8 +141,8 @@ public BigInteger GetOracleValidatorsCount(StoreView snapshot) /// Oracle multisignature address public UInt160 GetOracleMultiSigAddress(StoreView snapshot) { - ECPoint[] validators = NativeContract.NEO.GetValidators(snapshot); - return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash(); + ECPoint[] cnPubKeys = NativeContract.NEO.GetValidators(snapshot); + return Contract.CreateMultiSigRedeemScript(cnPubKeys.Length - (cnPubKeys.Length - 1) / 3, cnPubKeys).ToScriptHash(); } /// From 0c0f9e3780cc620d554f48eba451407fed638964 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Tue, 3 Mar 2020 01:16:17 -0600 Subject: [PATCH 37/44] Update src/neo/SmartContract/Native/Oracle/OracleContract.cs Co-Authored-By: Erik Zhang --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 5fad6fa2c6..5d748a3602 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -14,7 +14,7 @@ using System.Numerics; using Array = Neo.VM.Types.Array; -namespace Neo.Oracle +namespace Neo.SmartContract.Native.Oracle { public sealed class OracleContract : NativeContract { From 88765400e9ae1b8e3861a027711daa1145506ce7 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Tue, 3 Mar 2020 01:16:34 -0600 Subject: [PATCH 38/44] Update src/neo/SmartContract/Native/Oracle/OracleContract.cs Co-Authored-By: Erik Zhang --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 5d748a3602..b80ea1dad9 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -18,7 +18,7 @@ namespace Neo.SmartContract.Native.Oracle { public sealed class OracleContract : NativeContract { - public override string ServiceName => "Neo.Native.Oracle.Policy"; + public override string ServiceName => "Neo.Native.Oracle"; public override int Id => -4; From 2a4196205447680993cee1cf9177f7d281936813 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Tue, 3 Mar 2020 15:25:16 +0800 Subject: [PATCH 39/44] Fix bug --- src/neo/SmartContract/Native/NativeContract.cs | 2 +- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index dacf659241..812de7591e 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -2,8 +2,8 @@ using Neo.IO; using Neo.Ledger; -using Neo.Oracle; using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native.Oracle; using Neo.SmartContract.Native.Tokens; using Neo.VM; using Neo.VM.Types; diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index b80ea1dad9..eff06a7d88 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -2,10 +2,7 @@ using Neo.IO; using Neo.Ledger; using Neo.Persistence; -using Neo.SmartContract; using Neo.SmartContract.Manifest; -using Neo.SmartContract.Native; -using Neo.SmartContract.Native.Oracle; using Neo.VM; using Neo.VM.Types; using System; From e6bb7b9202aeea3cd03a1b9c9eb1bd6c408905aa Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 4 Mar 2020 14:18:25 +0800 Subject: [PATCH 40/44] change logic --- .../Native/Oracle/OracleContract.cs | 28 ++++++++------- .../Native/Oracle/OracleHttpConfig.cs | 32 ----------------- .../Native/Oracle/UT_OracleContract.cs | 36 +++++++------------ 3 files changed, 29 insertions(+), 67 deletions(-) delete mode 100644 src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index eff06a7d88..62461ed990 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Text; using Array = Neo.VM.Types.Array; namespace Neo.SmartContract.Native.Oracle @@ -31,9 +32,9 @@ public OracleContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes("Timeout")), new StorageItem { - Value = new OracleHttpConfig() { Timeout = 5000 }.ToArray() + Value = new ByteArray(BitConverter.GetBytes(5000)).GetSpan().ToArray() }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem { @@ -148,17 +149,16 @@ public UInt160 GetOracleMultiSigAddress(StoreView snapshot) /// VM /// Parameter Array /// Returns true if the execution is successful, otherwise returns false - [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "httpConfig" })] + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.String, ContractParameterType.ByteArray }, ParameterNames = new[] { "configKey", "configValue" })] private StackItem SetHttpConfig(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; - int timeOutMilliSeconds = (int)args[0].GetBigInteger(); - if (timeOutMilliSeconds <= 0) return false; - OracleHttpConfig httpConfig = new OracleHttpConfig() { Timeout = timeOutMilliSeconds }; - StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig)); - storage.Value = httpConfig.ToArray(); + string key = args[0].GetString(); + ByteArray value = args[1].GetSpan().ToArray(); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes(key))); + storage.Value = value.GetSpan().ToArray(); return true; } @@ -167,20 +167,24 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) /// /// VM /// value - [ContractMethod(0_01000000, ContractParameterType.Array)] + [ContractMethod(0_01000000, ContractParameterType.Array, ParameterTypes = new[] { ContractParameterType.String }, ParameterNames = new[] { "configKey" })] private StackItem GetHttpConfig(ApplicationEngine engine, Array args) { - return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter); + StoreView snapshot = engine.Snapshot; + string key = args[0].GetString(); + return GetHttpConfig(snapshot, key); } /// /// Get HttpConfig /// /// snapshot + /// key /// value - public OracleHttpConfig GetHttpConfig(StoreView snapshot) + public ByteArray GetHttpConfig(StoreView snapshot, string key) { - return snapshot.Storages[CreateStorageKey(Prefix_HttpConfig)].Value.AsSerializable(); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes(key))); + return storage.Value; } /// diff --git a/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs b/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs deleted file mode 100644 index 5e763780df..0000000000 --- a/src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Neo.IO; -using Neo.VM; -using Neo.VM.Types; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace Neo.SmartContract.Native.Oracle -{ - public class OracleHttpConfig : ISerializable, IInteroperable - { - public int Timeout { get; set; } - - public int Size => sizeof(int); - - public void Deserialize(BinaryReader reader) - { - Timeout = reader.ReadInt32(); - } - - public void Serialize(BinaryWriter writer) - { - writer.Write(Timeout); - } - - public StackItem ToStackItem(ReferenceCounter referenceCounter) - { - return new VM.Types.Array(referenceCounter, new StackItem[] { Timeout }); - } - } -} diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs index 26b3b45cf6..35a0607b59 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs @@ -12,6 +12,7 @@ using Neo.Wallets; using System; using System.Linq; +using System.Numerics; using static Neo.UnitTests.Extensions.Nep5NativeContractExtensions; namespace Neo.UnitTests.Oracle @@ -127,14 +128,14 @@ public void Test_GetHttpConfig() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig", new ContractParameter(ContractParameterType.String) { Value = "Timeout" }); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); engine.Execute().Should().Be(VMState.HALT); var result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.Array)); - Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), 5000); + result.Should().BeOfType(typeof(VM.Types.ByteArray)); + Assert.AreEqual(result.GetBigInteger(), 5000); } [TestMethod] @@ -147,35 +148,24 @@ public void Test_SetHttpConfig() var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); NativeContract.Oracle.Initialize(engine).Should().BeTrue(); var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); - var value = 12345; - - // Set wrong (negative) - - var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); - engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); - engine.LoadScript(script.ToArray()); - - engine.Execute().Should().Be(VMState.HALT); - var result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.Boolean)); - Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); + var key = "Timeout"; + var value = BitConverter.GetBytes(12345); // Set (wrong witness) - script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = 0 }); + var script = new ScriptBuilder(); + script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); engine.LoadScript(script.ToArray()); engine.Execute().Should().Be(VMState.HALT); - result = engine.ResultStack.Pop(); + var result = engine.ResultStack.Pop(); result.Should().BeOfType(typeof(VM.Types.Boolean)); Assert.IsFalse((result as VM.Types.Boolean).ToBoolean()); // Set good script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.Integer) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -187,14 +177,14 @@ public void Test_SetHttpConfig() // Get script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig"); + script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); engine.Execute().Should().Be(VMState.HALT); result = engine.ResultStack.Pop(); - result.Should().BeOfType(typeof(VM.Types.Array)); - Assert.AreEqual(((VM.Types.Array)result)[0].GetBigInteger(), value); + result.Should().BeOfType(typeof(VM.Types.ByteArray)); + Assert.AreEqual(result.GetBigInteger(), new BigInteger(value)); } [TestMethod] From 66aea1f3ae42a007ffc09e086ad126a570246dcd Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 4 Mar 2020 14:51:22 +0800 Subject: [PATCH 41/44] Fix name --- .../SmartContract/Native/Oracle/OracleContract.cs | 10 +++++----- .../SmartContract/Native/Oracle/UT_OracleContract.cs | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index 62461ed990..b71ff7fe9a 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -32,7 +32,7 @@ public OracleContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes("Timeout")), new StorageItem + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes("HttpTimeout")), new StorageItem { Value = new ByteArray(BitConverter.GetBytes(5000)).GetSpan().ToArray() }); @@ -150,7 +150,7 @@ public UInt160 GetOracleMultiSigAddress(StoreView snapshot) /// Parameter Array /// Returns true if the execution is successful, otherwise returns false [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.String, ContractParameterType.ByteArray }, ParameterNames = new[] { "configKey", "configValue" })] - private StackItem SetHttpConfig(ApplicationEngine engine, Array args) + private StackItem SetConfig(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; UInt160 account = GetOracleMultiSigAddress(snapshot); @@ -168,11 +168,11 @@ private StackItem SetHttpConfig(ApplicationEngine engine, Array args) /// VM /// value [ContractMethod(0_01000000, ContractParameterType.Array, ParameterTypes = new[] { ContractParameterType.String }, ParameterNames = new[] { "configKey" })] - private StackItem GetHttpConfig(ApplicationEngine engine, Array args) + private StackItem GetConfig(ApplicationEngine engine, Array args) { StoreView snapshot = engine.Snapshot; string key = args[0].GetString(); - return GetHttpConfig(snapshot, key); + return GetConfig(snapshot, key); } /// @@ -181,7 +181,7 @@ private StackItem GetHttpConfig(ApplicationEngine engine, Array args) /// snapshot /// key /// value - public ByteArray GetHttpConfig(StoreView snapshot, string key) + public ByteArray GetConfig(StoreView snapshot, string key) { StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes(key))); return storage.Value; diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs index 35a0607b59..7314c8ee68 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs @@ -128,7 +128,7 @@ public void Test_GetHttpConfig() { var snapshot = Blockchain.Singleton.GetSnapshot(); var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig", new ContractParameter(ContractParameterType.String) { Value = "Timeout" }); + script.EmitAppCall(NativeContract.Oracle.Hash, "getConfig", new ContractParameter(ContractParameterType.String) { Value = "HttpTimeout" }); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -139,7 +139,7 @@ public void Test_GetHttpConfig() } [TestMethod] - public void Test_SetHttpConfig() + public void Test_SetConfig() { var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); @@ -148,12 +148,12 @@ public void Test_SetHttpConfig() var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); NativeContract.Oracle.Initialize(engine).Should().BeTrue(); var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); - var key = "Timeout"; + var key = "HttpTimeout"; var value = BitConverter.GetBytes(12345); // Set (wrong witness) var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(null), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -165,7 +165,7 @@ public void Test_SetHttpConfig() // Set good script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "setHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); + script.EmitAppCall(NativeContract.Oracle.Hash, "setConfig", new ContractParameter(ContractParameterType.String) { Value = key }, new ContractParameter(ContractParameterType.ByteArray) { Value = value }); engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(from), snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -177,7 +177,7 @@ public void Test_SetHttpConfig() // Get script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.Oracle.Hash, "getHttpConfig", new ContractParameter(ContractParameterType.String) { Value = key }); + script.EmitAppCall(NativeContract.Oracle.Hash, "getConfig", new ContractParameter(ContractParameterType.String) { Value = key }); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); From 19447cd96b4dd8d0c6107e809b735863c4fa50b6 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 5 Mar 2020 10:46:59 +0800 Subject: [PATCH 42/44] change to const --- src/neo/SmartContract/Native/Oracle/HttpConfig.cs | 7 +++++++ src/neo/SmartContract/Native/Oracle/OracleContract.cs | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/neo/SmartContract/Native/Oracle/HttpConfig.cs diff --git a/src/neo/SmartContract/Native/Oracle/HttpConfig.cs b/src/neo/SmartContract/Native/Oracle/HttpConfig.cs new file mode 100644 index 0000000000..877467c0f7 --- /dev/null +++ b/src/neo/SmartContract/Native/Oracle/HttpConfig.cs @@ -0,0 +1,7 @@ +namespace Neo.SmartContract.Native.Oracle +{ + public class HttpConfig + { + public const string Timeout = "HttpTimeout"; + } +} diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index b71ff7fe9a..cc2ac1a741 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -21,7 +21,7 @@ public sealed class OracleContract : NativeContract public override int Id => -4; private const byte Prefix_Validator = 24; - private const byte Prefix_HttpConfig = 25; + private const byte Prefix_Config = 25; private const byte Prefix_PerRequestFee = 26; public OracleContract() @@ -32,7 +32,7 @@ public OracleContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; - engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes("HttpTimeout")), new StorageItem + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Config, Encoding.UTF8.GetBytes(HttpConfig.Timeout)), new StorageItem { Value = new ByteArray(BitConverter.GetBytes(5000)).GetSpan().ToArray() }); @@ -157,7 +157,7 @@ private StackItem SetConfig(ApplicationEngine engine, Array args) if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; string key = args[0].GetString(); ByteArray value = args[1].GetSpan().ToArray(); - StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes(key))); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Config, Encoding.UTF8.GetBytes(key))); storage.Value = value.GetSpan().ToArray(); return true; } @@ -183,7 +183,7 @@ private StackItem GetConfig(ApplicationEngine engine, Array args) /// value public ByteArray GetConfig(StoreView snapshot, string key) { - StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig, Encoding.UTF8.GetBytes(key))); + StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Config, Encoding.UTF8.GetBytes(key))); return storage.Value; } From 7e64f2c72950255203950eec9e1e16ceb83fd4f4 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Wed, 11 Mar 2020 13:17:59 +0800 Subject: [PATCH 43/44] Add double initialization check and fix ut --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 6 +++++- .../SmartContract/Native/Oracle/UT_OracleContract.cs | 4 +--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index cc2ac1a741..c76de2960f 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -32,6 +32,8 @@ public OracleContract() internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; + if (GetPerRequestFee(engine.Snapshot) != 0) return false; + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_Config, Encoding.UTF8.GetBytes(HttpConfig.Timeout)), new StorageItem { Value = new ByteArray(BitConverter.GetBytes(5000)).GetSpan().ToArray() @@ -225,7 +227,9 @@ private StackItem GetPerRequestFee(ApplicationEngine engine, Array args) /// Value public int GetPerRequestFee(StoreView snapshot) { - return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_PerRequestFee)].Value, 0); + StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_PerRequestFee)); + if (storage is null) return 0; + return BitConverter.ToInt32(storage.Value, 0); } } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs index 7314c8ee68..330bce23a2 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Oracle/UT_OracleContract.cs @@ -35,7 +35,7 @@ public void TestInitialize() snapshot.Storages.Delete(CreateStorageKey(11)); snapshot.PersistingBlock = Blockchain.GenesisBlock; engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.Oracle.Initialize(engine).Should().BeTrue(); + NativeContract.Oracle.Initialize(engine).Should().BeFalse(); // already registered } internal static StorageKey CreateStorageKey(byte prefix, byte[] key = null) { @@ -72,7 +72,6 @@ public void Test_SetPerRequestFee() // Init var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.Oracle.Initialize(engine).Should().BeTrue(); var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); var value = 12345; @@ -146,7 +145,6 @@ public void Test_SetConfig() // Init var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - NativeContract.Oracle.Initialize(engine).Should().BeTrue(); var from = NativeContract.Oracle.GetOracleMultiSigAddress(snapshot); var key = "HttpTimeout"; var value = BitConverter.GetBytes(12345); From 65b823b2087fd6fc49ab233f8446bb9a5f51406f Mon Sep 17 00:00:00 2001 From: Luchuan Date: Wed, 11 Mar 2020 13:21:56 +0800 Subject: [PATCH 44/44] optimize --- src/neo/SmartContract/Native/Oracle/OracleContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/Oracle/OracleContract.cs b/src/neo/SmartContract/Native/Oracle/OracleContract.cs index c76de2960f..c1cbd62932 100644 --- a/src/neo/SmartContract/Native/Oracle/OracleContract.cs +++ b/src/neo/SmartContract/Native/Oracle/OracleContract.cs @@ -229,7 +229,7 @@ public int GetPerRequestFee(StoreView snapshot) { StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_PerRequestFee)); if (storage is null) return 0; - return BitConverter.ToInt32(storage.Value, 0); + return BitConverter.ToInt32(storage.Value); } } }