Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracle policy contract #1445

Merged
merged 47 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
074fc9a
first commit
doubiliu Feb 13, 2020
d173f4c
Merge remote-tracking branch 'upstream/master' into OraclePolicyContract
doubiliu Feb 13, 2020
25b82cd
format
doubiliu Feb 13, 2020
04fdf94
Simplify code
doubiliu Feb 14, 2020
e4dc1ac
add UT and add some feature
doubiliu Feb 14, 2020
80bc65f
Fix bug
doubiliu Feb 15, 2020
aadf197
Add summary and fix bug
doubiliu Feb 15, 2020
748a3af
format
doubiliu Feb 16, 2020
3c40655
format
doubiliu Feb 17, 2020
6bf9c86
little change
doubiliu Feb 17, 2020
6e3369a
little change
doubiliu Feb 17, 2020
846d195
little change
doubiliu Feb 17, 2020
8b118c0
change Fee & Fix bug
doubiliu Feb 18, 2020
5d375c8
Optimize
shargon Feb 18, 2020
71e6add
add config class
doubiliu Feb 20, 2020
3570d0e
solve conflict
doubiliu Feb 20, 2020
bbdf3f9
FiX UT
doubiliu Feb 20, 2020
2197407
Format
doubiliu Feb 20, 2020
a81a1e5
Fix UT
doubiliu Feb 20, 2020
f4e69dc
Fix format and Optimize
doubiliu Feb 20, 2020
0c2b34b
Add some UT
shargon Feb 20, 2020
591b33b
Fix bug and add UT
doubiliu Feb 21, 2020
61bb96a
Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
doubiliu Feb 21, 2020
531427e
little change
doubiliu Feb 21, 2020
2d8a645
format
doubiliu Feb 21, 2020
99d6761
Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
doubiliu Feb 21, 2020
cc6774f
add check
doubiliu Feb 21, 2020
8698a5b
Merge branch 'OraclePolicyContract' of github.com:doubiliu/neoUT into…
doubiliu Feb 21, 2020
696399c
change validator
doubiliu Feb 23, 2020
9dfc1f8
Add double initialization check
shargon Feb 24, 2020
5d9fa90
add UT
doubiliu Feb 26, 2020
740ccb7
Add UT
doubiliu Feb 26, 2020
c693e7c
change UT
doubiliu Feb 26, 2020
30577c5
fill UT
Feb 27, 2020
985f0a4
up ut and fix NeoToken.GetValidators
Feb 27, 2020
d042560
remove console
Feb 27, 2020
704051a
reset NEO.getValidators
Feb 28, 2020
953a288
fix GetOracleValidators
Mar 2, 2020
aad74d9
Rename variable
shargon Mar 2, 2020
0c0f9e3
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
doubiliu Mar 3, 2020
8876540
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
doubiliu Mar 3, 2020
2a41962
Fix bug
doubiliu Mar 3, 2020
e6bb7b9
change logic
doubiliu Mar 4, 2020
66aea1f
Fix name
doubiliu Mar 4, 2020
19447cd
change to const
doubiliu Mar 5, 2020
7e64f2c
Add double initialization check and fix ut
Mar 11, 2020
65b823b
optimize
Mar 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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; }
Expand Down
32 changes: 32 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OracleHttpConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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 });
}
}
}
235 changes: 235 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
using Neo.Cryptography.ECC;
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;
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a general place for these Prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Prefix have a clear counting rule?I think the value of Prefix is ​​a bit confusing, although there will not be a big problem because of the existence of ID. If possible, we can specify a counting rule. @erikzhang

private const byte Prefix_HttpConfig = 25;
private const byte Prefix_PerRequestFee = 26;

/// <summary>
/// Constructor
/// </summary>
public OraclePolicyContract()
{
Manifest.Features = ContractFeatures.HasStorage;
}

/// <summary>
/// Initialization.Set default parameter value.
/// </summary>
/// <param name="engine">VM</param>
/// <returns>Returns true if the execution is successful, otherwise returns false</returns>
internal override bool Initialize(ApplicationEngine engine)
{
if (!base.Initialize(engine)) return false;
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_HttpConfig), new StorageItem
{
Value = new OracleHttpConfig() { Timeout = 5000 }.ToArray()
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem
{
Value = BitConverter.GetBytes(1000)
});
return true;
}

/// <summary>
/// Oracle validator can delegate third party to operate Oracle nodes
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>Returns true if the execution is successful, otherwise returns false</returns>
[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<ECPoint>();
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
ECPoint consigneePubKey = args[1].GetSpan().AsSerializable<ECPoint>();
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();

byte[] prefixKey = StorageKey.CreateSearchPrefix(Id, new[] { Prefix_Validator });
List<ECPoint> delegatedOracleValidators = snapshot.Storages.Find(prefixKey).Select(p =>
(
p.Key.Key.AsSerializable<ECPoint>(1)
)).ToList();
ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot);
foreach (var validator in delegatedOracleValidators)
{
if (!oraclePubKeys.Contains(validator))
{
snapshot.Storages.Delete(CreateStorageKey(Prefix_Validator, validator));
}
}
return true;
}

/// <summary>
/// Get current authorized Oracle validator.
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>Authorized Oracle validator</returns>
[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()));
}

/// <summary>
/// Get current authorized Oracle validator
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <returns>Authorized Oracle validator</returns>
public ECPoint[] GetOracleValidators(StoreView snapshot)
{
ECPoint[] oraclePubKeys = PolicyContract.NEO.GetValidators(snapshot);
for (int index = 0; index < oraclePubKeys.Length; index++)
{
var oraclePubKey = oraclePubKeys[index];
StorageKey key = CreateStorageKey(Prefix_Validator, oraclePubKey);
ECPoint delegatePubKey = snapshot.Storages.TryGet(key)?.Value.AsSerializable<ECPoint>();
if (delegatePubKey != null) { oraclePubKeys[index] = delegatePubKey; }
}
return oraclePubKeys;
}

/// <summary>
/// Get number of current authorized Oracle validator
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>The number of authorized Oracle validator</returns>
[ContractMethod(0_01000000, ContractParameterType.Integer)]
private StackItem GetOracleValidatorsCount(ApplicationEngine engine, Array args)
{
return GetOracleValidatorsCount(engine.Snapshot);
}

/// <summary>
/// Get number of current authorized Oracle validator
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <returns>The number of authorized Oracle validator</returns>
public BigInteger GetOracleValidatorsCount(StoreView snapshot)
{
return GetOracleValidators(snapshot).Length;
}

/// <summary>
/// Create a Oracle multisignature address
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <returns>Oracle multisignature address</returns>
public UInt160 GetOracleMultiSigAddress(StoreView snapshot)
{
ECPoint[] validators = GetOracleValidators(snapshot);
return Contract.CreateMultiSigRedeemScript(validators.Length - (validators.Length - 1) / 3, validators).ToScriptHash();
}

/// <summary>
/// Set HttpConfig
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>Returns true if the execution is successful, otherwise returns false</returns>
[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;
int timeOutMilliSeconds = (int)args[0].GetBigInteger();
if (timeOutMilliSeconds <= 0) return false;
OracleHttpConfig httpConfig = new OracleHttpConfig() { Timeout = timeOutMilliSeconds };
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_HttpConfig));
storage.Value = httpConfig.ToArray();
return true;
}

/// <summary>
/// Get HttpConfig
/// </summary>
/// <param name="engine">VM</param>
/// <returns>value</returns>
[ContractMethod(0_01000000, ContractParameterType.Array)]
private StackItem GetHttpConfig(ApplicationEngine engine, Array args)
{
return GetHttpConfig(engine.Snapshot).ToStackItem(engine.ReferenceCounter);
}

/// <summary>
/// Get HttpConfig
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <returns>value</returns>
public OracleHttpConfig GetHttpConfig(StoreView snapshot)
{
return snapshot.Storages[CreateStorageKey(Prefix_HttpConfig)].Value.AsSerializable<OracleHttpConfig>();
}

/// <summary>
/// Set PerRequestFee
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>Returns true if the execution is successful, otherwise returns false</returns>
[ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "fee" })]
private StackItem SetPerRequestFee(ApplicationEngine engine, Array args)
{
StoreView snapshot = engine.Snapshot;
UInt160 account = GetOracleMultiSigAddress(snapshot);
shargon marked this conversation as resolved.
Show resolved Hide resolved
if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false;
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;
}

/// <summary>
/// Get PerRequestFee
/// </summary>
/// <param name="engine">VM</param>
/// <param name="args">Parameter Array</param>
/// <returns>Value</returns>
[ContractMethod(0_01000000, ContractParameterType.Integer, SafeMethod = true)]
private StackItem GetPerRequestFee(ApplicationEngine engine, Array args)
{
return new Integer(GetPerRequestFee(engine.Snapshot));
}

/// <summary>
/// Get PerRequestFee
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <returns>Value</returns>
public int GetPerRequestFee(StoreView snapshot)
{
return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_PerRequestFee)].Value, 0);
}
}
}
4 changes: 2 additions & 2 deletions src/neo/neo.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

doubiliu marked this conversation as resolved.
Show resolved Hide resolved
<PropertyGroup>
<Copyright>2015-2019 The Neo Project</Copyright>
Expand Down Expand Up @@ -30,4 +30,4 @@
<PackageReference Include="Neo.VM" Version="3.0.0-CI00201" />
</ItemGroup>

</Project>
</Project>
Loading