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 all 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 @@ -3,6 +3,7 @@
using Neo.IO;
using Neo.Ledger;
using Neo.SmartContract.Manifest;
using Neo.SmartContract.Native.Oracle;
using Neo.SmartContract.Native.Tokens;
using Neo.VM;
using Neo.VM.Types;
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 OracleContract Oracle { get; } = new OracleContract();

public abstract string ServiceName { get; }
public uint ServiceHash { get; }
Expand Down
7 changes: 7 additions & 0 deletions src/neo/SmartContract/Native/Oracle/HttpConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Neo.SmartContract.Native.Oracle
{
public class HttpConfig
{
public const string Timeout = "HttpTimeout";
}
}
235 changes: 235 additions & 0 deletions src/neo/SmartContract/Native/Oracle/OracleContract.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.Manifest;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Array = Neo.VM.Types.Array;

namespace Neo.SmartContract.Native.Oracle
{
public sealed class OracleContract : NativeContract
{
public override string ServiceName => "Neo.Native.Oracle";

public override int Id => -4;

private const byte Prefix_Validator = 24;
private const byte Prefix_Config = 25;
private const byte Prefix_PerRequestFee = 26;

public OracleContract()
{
Manifest.Features = ContractFeatures.HasStorage;
}

internal override bool Initialize(ApplicationEngine engine)
{
if (!base.Initialize(engine)) return false;
shargon marked this conversation as resolved.
Show resolved Hide resolved
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()
});
engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_PerRequestFee), new StorageItem
{
Value = BitConverter.GetBytes(1000)
});
return true;
}

/// <summary>
/// Consensus node can delegate third party to operate Oracle nodes
/// </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)
{
StoreView snapshot = engine.Snapshot;
ECPoint consignorPubKey = args[0].GetSpan().AsSerializable<ECPoint>();
ECPoint consigneePubKey = args[1].GetSpan().AsSerializable<ECPoint>();
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);
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();
foreach (var validator in delegatedOracleValidators)
{
if (!cnPubKeys.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[] 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];
StorageKey key = CreateStorageKey(Prefix_Validator, oraclePubKey);
ECPoint delegatePubKey = snapshot.Storages.TryGet(key)?.Value.AsSerializable<ECPoint>();
if (delegatePubKey != null) { oraclePubKeys[index] = delegatePubKey; }
}
return oraclePubKeys;
shargon marked this conversation as resolved.
Show resolved Hide resolved
}

/// <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[] cnPubKeys = NativeContract.NEO.GetValidators(snapshot);
return Contract.CreateMultiSigRedeemScript(cnPubKeys.Length - (cnPubKeys.Length - 1) / 3, cnPubKeys).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.String, ContractParameterType.ByteArray }, ParameterNames = new[] { "configKey", "configValue" })]
private StackItem SetConfig(ApplicationEngine engine, Array args)
{
StoreView snapshot = engine.Snapshot;
UInt160 account = GetOracleMultiSigAddress(snapshot);
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_Config, Encoding.UTF8.GetBytes(key)));
storage.Value = value.GetSpan().ToArray();
return true;
}

/// <summary>
/// Get HttpConfig
/// </summary>
/// <param name="engine">VM</param>
/// <returns>value</returns>
[ContractMethod(0_01000000, ContractParameterType.Array, ParameterTypes = new[] { ContractParameterType.String }, ParameterNames = new[] { "configKey" })]
private StackItem GetConfig(ApplicationEngine engine, Array args)
{
StoreView snapshot = engine.Snapshot;
string key = args[0].GetString();
return GetConfig(snapshot, key);
}

/// <summary>
/// Get HttpConfig
/// </summary>
/// <param name="snapshot">snapshot</param>
/// <param name="key">key</param>
/// <returns>value</returns>
public ByteArray GetConfig(StoreView snapshot, string key)
{
StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Config, Encoding.UTF8.GetBytes(key)));
return storage.Value;
}

/// <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);
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)
{
StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_PerRequestFee));
if (storage is null) return 0;
return BitConverter.ToInt32(storage.Value);
}
}
}
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