-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Oracle policy contract #1445
Changes from 14 commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
074fc9a
first commit
doubiliu d173f4c
Merge remote-tracking branch 'upstream/master' into OraclePolicyContract
doubiliu 25b82cd
format
doubiliu 04fdf94
Simplify code
doubiliu e4dc1ac
add UT and add some feature
doubiliu 80bc65f
Fix bug
doubiliu aadf197
Add summary and fix bug
doubiliu 748a3af
format
doubiliu 3c40655
format
doubiliu 6bf9c86
little change
doubiliu 6e3369a
little change
doubiliu 846d195
little change
doubiliu 8b118c0
change Fee & Fix bug
doubiliu 5d375c8
Optimize
shargon 71e6add
add config class
doubiliu 3570d0e
solve conflict
doubiliu bbdf3f9
FiX UT
doubiliu 2197407
Format
doubiliu a81a1e5
Fix UT
doubiliu f4e69dc
Fix format and Optimize
doubiliu 0c2b34b
Add some UT
shargon 591b33b
Fix bug and add UT
doubiliu 61bb96a
Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
doubiliu 531427e
little change
doubiliu 2d8a645
format
doubiliu 99d6761
Update src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
doubiliu cc6774f
add check
doubiliu 8698a5b
Merge branch 'OraclePolicyContract' of github.com:doubiliu/neoUT into…
doubiliu 696399c
change validator
doubiliu 9dfc1f8
Add double initialization check
shargon 5d9fa90
add UT
doubiliu 740ccb7
Add UT
doubiliu c693e7c
change UT
doubiliu 30577c5
fill UT
985f0a4
up ut and fix NeoToken.GetValidators
d042560
remove console
704051a
reset NEO.getValidators
953a288
fix GetOracleValidators
aad74d9
Rename variable
shargon 0c0f9e3
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
doubiliu 8876540
Update src/neo/SmartContract/Native/Oracle/OracleContract.cs
doubiliu 2a41962
Fix bug
doubiliu e6bb7b9
change logic
doubiliu 66aea1f
Fix name
doubiliu 19447cd
change to const
doubiliu 7e64f2c
Add double initialization check and fix ut
65b823b
optimize
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
228 changes: 228 additions & 0 deletions
228
src/neo/SmartContract/Native/Oracle/OraclePolicyContract.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
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.VM; | ||
using Neo.VM.Types; | ||
using System; | ||
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; | ||
|
||
/// <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_TimeOutMilliSeconds), new StorageItem | ||
{ | ||
Value = BitConverter.GetBytes(5000) | ||
}); | ||
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); | ||
if (snapshot.Storages.TryGet(key) != null) | ||
{ | ||
StorageItem value = snapshot.Storages.GetAndChange(key); | ||
doubiliu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
value.Value = consigneePubKey.ToArray(); | ||
} | ||
else | ||
{ | ||
snapshot.Storages.Add(key, new StorageItem | ||
{ | ||
Value = consigneePubKey.ToArray() | ||
}); | ||
} | ||
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 timeout | ||
/// </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[] { "TimeOutMilliSeconds" })] | ||
private StackItem SetTimeOutMilliSeconds(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; | ||
StorageItem storage = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TimeOutMilliSeconds)); | ||
storage.Value = BitConverter.GetBytes(timeOutMilliSeconds); | ||
return true; | ||
} | ||
|
||
/// <summary> | ||
/// Get timeout | ||
/// </summary> | ||
/// <param name="engine">VM</param> | ||
/// <returns>value</returns> | ||
[ContractMethod(0_01000000, ContractParameterType.Integer)] | ||
private StackItem GetTimeOutMilliSeconds(ApplicationEngine engine, Array args) | ||
{ | ||
return new Integer(GetTimeOutMilliSeconds(engine.Snapshot)); | ||
} | ||
|
||
/// <summary> | ||
/// Get timeout | ||
/// </summary> | ||
/// <param name="snapshot">snapshot</param> | ||
/// <returns>value</returns> | ||
public int GetTimeOutMilliSeconds(StoreView snapshot) | ||
{ | ||
return BitConverter.ToInt32(snapshot.Storages[CreateStorageKey(Prefix_TimeOutMilliSeconds)].Value, 0); | ||
} | ||
|
||
/// <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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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
.There was a problem hiding this comment.
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